Compare commits

..

2 Commits

Author SHA1 Message Date
Wilken Rivera fd3cc596c7 The original approach of running version, but that seems to bypass wrappedMain entirely 2021-04-05 16:06:41 -04:00
Wilken Rivera 708f9cdfbd Add example test to validate correct output 2021-04-05 16:01:01 -04:00
345 changed files with 6054 additions and 32151 deletions
-12
View File
@@ -1,17 +1,5 @@
## 1.7.2 (Upcoming)
### IMPROVEMENTS:
* builder/alicloud: Add `ramrole` configuration to ECS instance. [GH-10845]
### BUG FIXES:
* builder/proxmox: Update Proxmox Go API to ensure only the first non-loopback
IPv4 address gets returned. [GH-10858]
* builder/vsphere: Fix primary disk resize on clone. [GH-10848]
* core: Fix bug where call to "packer version" sent output to stderr instead of
stdout. [GH-10850]
## 1.7.1 (March 31, 2021)
### NOTES:
-1
View File
@@ -135,7 +135,6 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
InstanceType: b.config.InstanceType,
UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile,
RamRoleName: b.config.RamRoleName,
RegionId: b.config.AlicloudRegion,
InternetChargeType: b.config.InternetChargeType,
InternetMaxBandwidthOut: b.config.InternetMaxBandwidthOut,
-2
View File
@@ -88,7 +88,6 @@ type FlatConfig struct {
AlicloudSourceImage *string `mapstructure:"source_image" required:"true" cty:"source_image" hcl:"source_image"`
ForceStopInstance *bool `mapstructure:"force_stop_instance" required:"false" cty:"force_stop_instance" hcl:"force_stop_instance"`
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"`
RamRoleName *string `mapstructure:"ram_role_name" required:"false" cty:"ram_role_name" hcl:"ram_role_name"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id" hcl:"security_group_id"`
SecurityGroupName *string `mapstructure:"security_group_name" required:"false" cty:"security_group_name" hcl:"security_group_name"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
@@ -206,7 +205,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"source_image": &hcldec.AttrSpec{Name: "source_image", Type: cty.String, Required: false},
"force_stop_instance": &hcldec.AttrSpec{Name: "force_stop_instance", Type: cty.Bool, Required: false},
"disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false},
"ram_role_name": &hcldec.AttrSpec{Name: "ram_role_name", Type: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_name": &hcldec.AttrSpec{Name: "security_group_name", Type: cty.String, Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
-2
View File
@@ -47,8 +47,6 @@ type RunConfig struct {
// E.g., Sysprep a windows which may shutdown the instance within its command.
// The default value is false.
DisableStopInstance bool `mapstructure:"disable_stop_instance" required:"false"`
// Ram Role to apply when launching the instance.
RamRoleName string `mapstructure:"ram_role_name" required:"false"`
// ID of the security group to which a newly
// created instance belongs. Mutual access is allowed between instances in one
// security group. If not specified, the newly created instance will be added
@@ -23,7 +23,6 @@ type stepCreateAlicloudInstance struct {
UserData string
UserDataFile string
instanceId string
RamRoleName string
RegionId string
InternetChargeType string
InternetMaxBandwidthOut int
@@ -116,7 +115,6 @@ func (s *stepCreateAlicloudInstance) buildCreateInstanceRequest(state multistep.
request.RegionId = s.RegionId
request.InstanceType = s.InstanceType
request.InstanceName = s.InstanceName
request.RamRoleName = s.RamRoleName
request.ZoneId = s.ZoneId
sourceImage := state.Get("source_image").(*ecs.Image)
-3
View File
@@ -158,9 +158,6 @@ func getVMIP(state multistep.StateBag) (string, error) {
if addr.IsLoopback() {
continue
}
if addr.To4() == nil {
continue
}
return addr.String(), nil
}
}
+20 -13
View File
@@ -75,7 +75,7 @@ type StepCloneVM struct {
func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packersdk.Ui)
d := state.Get("driver").(driver.Driver)
d := state.Get("driver").(*driver.VCenterDriver)
vmPath := path.Join(s.Location.Folder, s.Location.VMName)
err := d.PreCleanVM(ui, vmPath, s.Force)
@@ -102,18 +102,17 @@ func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multist
}
vm, err := template.Clone(ctx, &driver.CloneConfig{
Name: s.Location.VMName,
Folder: s.Location.Folder,
Cluster: s.Location.Cluster,
Host: s.Location.Host,
ResourcePool: s.Location.ResourcePool,
Datastore: s.Location.Datastore,
LinkedClone: s.Config.LinkedClone,
Network: s.Config.Network,
MacAddress: s.Config.MacAddress,
Annotation: s.Config.Notes,
VAppProperties: s.Config.VAppConfig.Properties,
PrimaryDiskSize: s.Config.DiskSize,
Name: s.Location.VMName,
Folder: s.Location.Folder,
Cluster: s.Location.Cluster,
Host: s.Location.Host,
ResourcePool: s.Location.ResourcePool,
Datastore: s.Location.Datastore,
LinkedClone: s.Config.LinkedClone,
Network: s.Config.Network,
MacAddress: s.Config.MacAddress,
Annotation: s.Config.Notes,
VAppProperties: s.Config.VAppConfig.Properties,
StorageConfig: driver.StorageConfig{
DiskControllerType: s.Config.StorageConfig.DiskControllerType,
Storage: disks,
@@ -128,6 +127,14 @@ func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multist
}
state.Put("vm", vm)
if s.Config.DiskSize > 0 {
err = vm.ResizeDisk(s.Config.DiskSize)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
}
return multistep.ActionContinue
}
-251
View File
@@ -1,251 +0,0 @@
package clone
import (
"bytes"
"context"
"path"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/builder/vsphere/common"
"github.com/hashicorp/packer/builder/vsphere/driver"
)
func TestCreateConfig_Prepare(t *testing.T) {
tc := []struct {
name string
config *CloneConfig
fail bool
expectedErrMsg string
}{
{
name: "Valid config",
config: &CloneConfig{
Template: "template name",
StorageConfig: common.StorageConfig{
DiskControllerType: []string{"test"},
Storage: []common.DiskConfig{
{
DiskSize: 0,
},
},
},
},
fail: true,
expectedErrMsg: "storage[0].'disk_size' is required",
},
{
name: "Storage validate disk_size",
config: &CloneConfig{
StorageConfig: common.StorageConfig{
Storage: []common.DiskConfig{
{
DiskSize: 0,
DiskThinProvisioned: true,
},
},
},
},
fail: true,
expectedErrMsg: "storage[0].'disk_size' is required",
},
{
name: "Storage validate disk_controller_index",
config: &CloneConfig{
StorageConfig: common.StorageConfig{
Storage: []common.DiskConfig{
{
DiskSize: 32768,
DiskControllerIndex: 3,
},
},
},
},
fail: true,
expectedErrMsg: "storage[0].'disk_controller_index' references an unknown disk controller",
},
{
name: "Validate template is set",
config: &CloneConfig{
StorageConfig: common.StorageConfig{
DiskControllerType: []string{"test"},
Storage: []common.DiskConfig{
{
DiskSize: 32768,
},
},
},
},
fail: true,
expectedErrMsg: "'template' is required",
},
{
name: "Validate LinkedClone and DiskSize set at the same time",
config: &CloneConfig{
Template: "template name",
LinkedClone: true,
DiskSize: 32768,
StorageConfig: common.StorageConfig{
DiskControllerType: []string{"test"},
Storage: []common.DiskConfig{
{
DiskSize: 32768,
},
},
},
},
fail: true,
expectedErrMsg: "'linked_clone' and 'disk_size' cannot be used together",
},
{
name: "Validate MacAddress and Network not set at the same time",
config: &CloneConfig{
Template: "template name",
MacAddress: "some mac address",
StorageConfig: common.StorageConfig{
DiskControllerType: []string{"test"},
Storage: []common.DiskConfig{
{
DiskSize: 32768,
},
},
},
},
fail: true,
expectedErrMsg: "'network' is required when 'mac_address' is specified",
},
}
for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
errs := c.config.Prepare()
if c.fail {
if len(errs) == 0 {
t.Fatalf("Config preprare should fail")
}
if errs[0].Error() != c.expectedErrMsg {
t.Fatalf("Expected error message: %s but was '%s'", c.expectedErrMsg, errs[0].Error())
}
} else {
if len(errs) != 0 {
t.Fatalf("Config preprare should not fail: %s", errs[0])
}
}
})
}
}
func TestStepCreateVM_Run(t *testing.T) {
state := new(multistep.BasicStateBag)
state.Put("ui", &packersdk.BasicUi{
Reader: new(bytes.Buffer),
Writer: new(bytes.Buffer),
})
driverMock := driver.NewDriverMock()
state.Put("driver", driverMock)
step := basicStepCloneVM()
step.Force = true
vmPath := path.Join(step.Location.Folder, step.Location.VMName)
vmMock := new(driver.VirtualMachineMock)
driverMock.VM = vmMock
if action := step.Run(context.TODO(), state); action == multistep.ActionHalt {
t.Fatalf("Should not halt.")
}
// Pre clean VM
if !driverMock.PreCleanVMCalled {
t.Fatalf("driver.PreCleanVM should be called.")
}
if driverMock.PreCleanForce != step.Force {
t.Fatalf("Force PreCleanVM should be %t but was %t.", step.Force, driverMock.PreCleanForce)
}
if driverMock.PreCleanVMPath != vmPath {
t.Fatalf("VM path expected to be %s but was %s", vmPath, driverMock.PreCleanVMPath)
}
if !driverMock.FindVMCalled {
t.Fatalf("driver.FindVM should be called.")
}
if !vmMock.CloneCalled {
t.Fatalf("vm.Clone should be called.")
}
if diff := cmp.Diff(vmMock.CloneConfig, driverCreateConfig(step.Config, step.Location)); diff != "" {
t.Fatalf("wrong driver.CreateConfig: %s", diff)
}
vm, ok := state.GetOk("vm")
if !ok {
t.Fatal("state must contain the VM")
}
if vm != driverMock.VM {
t.Fatalf("state doesn't contain the created VM.")
}
}
func basicStepCloneVM() *StepCloneVM {
step := &StepCloneVM{
Config: createConfig(),
Location: basicLocationConfig(),
}
return step
}
func basicLocationConfig() *common.LocationConfig {
return &common.LocationConfig{
VMName: "test-vm",
Folder: "test-folder",
Cluster: "test-cluster",
Host: "test-host",
ResourcePool: "test-resource-pool",
Datastore: "test-datastore",
}
}
func createConfig() *CloneConfig {
return &CloneConfig{
Template: "template name",
StorageConfig: common.StorageConfig{
DiskControllerType: []string{"pvscsi"},
Storage: []common.DiskConfig{
{
DiskSize: 32768,
DiskThinProvisioned: true,
},
},
},
}
}
func driverCreateConfig(config *CloneConfig, location *common.LocationConfig) *driver.CloneConfig {
var disks []driver.Disk
for _, disk := range config.StorageConfig.Storage {
disks = append(disks, driver.Disk{
DiskSize: disk.DiskSize,
DiskEagerlyScrub: disk.DiskEagerlyScrub,
DiskThinProvisioned: disk.DiskThinProvisioned,
ControllerIndex: disk.DiskControllerIndex,
})
}
return &driver.CloneConfig{
StorageConfig: driver.StorageConfig{
DiskControllerType: config.StorageConfig.DiskControllerType,
Storage: disks,
},
Annotation: config.Notes,
Name: location.VMName,
Folder: location.Folder,
Cluster: location.Cluster,
Host: location.Host,
ResourcePool: location.ResourcePool,
Datastore: location.Datastore,
LinkedClone: config.LinkedClone,
Network: config.Network,
MacAddress: config.MacAddress,
VAppProperties: config.VAppConfig.Properties,
PrimaryDiskSize: config.DiskSize,
}
}
+1 -9
View File
@@ -24,9 +24,6 @@ type DriverMock struct {
CreateVMCalled bool
CreateConfig *CreateConfig
VM VirtualMachine
FindVMCalled bool
FindVMName string
}
func NewDriverMock() *DriverMock {
@@ -48,12 +45,7 @@ func (d *DriverMock) NewVM(ref *types.ManagedObjectReference) VirtualMachine {
}
func (d *DriverMock) FindVM(name string) (VirtualMachine, error) {
d.FindVMCalled = true
if d.VM == nil {
d.VM = new(VirtualMachineMock)
}
d.FindVMName = name
return d.VM, d.FindDatastoreErr
return nil, nil
}
func (d *DriverMock) FindCluster(name string) (*Cluster, error) {
+29 -29
View File
@@ -32,7 +32,7 @@ type VirtualMachine interface {
Destroy() error
Configure(config *HardwareConfig) error
Customize(spec types.CustomizationSpec) error
ResizeDisk(diskSize int64) ([]types.BaseVirtualDeviceConfigSpec, error)
ResizeDisk(diskSize int64) error
WaitForIP(ctx context.Context, ipNet *net.IPNet) (string, error)
PowerOn() error
PowerOff() error
@@ -68,19 +68,18 @@ type VirtualMachineDriver struct {
}
type CloneConfig struct {
Name string
Folder string
Cluster string
Host string
ResourcePool string
Datastore string
LinkedClone bool
Network string
MacAddress string
Annotation string
VAppProperties map[string]string
PrimaryDiskSize int64
StorageConfig StorageConfig
Name string
Folder string
Cluster string
Host string
ResourcePool string
Datastore string
LinkedClone bool
Network string
MacAddress string
Annotation string
VAppProperties map[string]string
StorageConfig StorageConfig
}
type HardwareConfig struct {
@@ -340,15 +339,6 @@ func (vm *VirtualMachineDriver) Clone(ctx context.Context, config *CloneConfig)
if err != nil {
return nil, err
}
if config.PrimaryDiskSize > 0 {
deviceResizeSpec, err := vm.ResizeDisk(config.PrimaryDiskSize)
if err != nil {
return nil, fmt.Errorf("failed to resize primary disk: %s", err.Error())
}
configSpec.DeviceChange = append(configSpec.DeviceChange, deviceResizeSpec...)
}
virtualDisks := devices.SelectByType((*types.VirtualDisk)(nil))
virtualControllers := devices.SelectByType((*types.VirtualController)(nil))
@@ -359,7 +349,7 @@ func (vm *VirtualMachineDriver) Clone(ctx context.Context, config *CloneConfig)
storageConfigSpec, err := config.StorageConfig.AddStorageDevices(existingDevices)
if err != nil {
return nil, fmt.Errorf("failed to add storage devices: %s", err.Error())
return nil, err
}
configSpec.DeviceChange = append(configSpec.DeviceChange, storageConfigSpec...)
@@ -607,25 +597,35 @@ func (vm *VirtualMachineDriver) Customize(spec types.CustomizationSpec) error {
return task.Wait(vm.driver.ctx)
}
func (vm *VirtualMachineDriver) ResizeDisk(diskSize int64) ([]types.BaseVirtualDeviceConfigSpec, error) {
func (vm *VirtualMachineDriver) ResizeDisk(diskSize int64) error {
var confSpec types.VirtualMachineConfigSpec
devices, err := vm.vm.Device(vm.driver.ctx)
if err != nil {
return nil, err
return err
}
disk, err := findDisk(devices)
if err != nil {
return nil, err
return err
}
disk.CapacityInKB = diskSize * 1024
return []types.BaseVirtualDeviceConfigSpec{
confSpec.DeviceChange = []types.BaseVirtualDeviceConfigSpec{
&types.VirtualDeviceConfigSpec{
Device: disk,
Operation: types.VirtualDeviceConfigSpecOperationEdit,
},
}, nil
}
task, err := vm.vm.Reconfigure(vm.driver.ctx, confSpec)
if err != nil {
return err
}
_, err = task.WaitForResult(vm.driver.ctx, nil)
return err
}
func (vm *VirtualMachineDriver) PowerOn() error {
+3 -8
View File
@@ -55,9 +55,6 @@ type VirtualMachineMock struct {
RemoveCdromsCalled bool
RemoveCdromsErr error
CloneCalled bool
CloneConfig *CloneConfig
CloneError error
}
func (vm *VirtualMachineMock) Info(params ...string) (*mo.VirtualMachine, error) {
@@ -74,9 +71,7 @@ func (vm *VirtualMachineMock) FloppyDevices() (object.VirtualDeviceList, error)
}
func (vm *VirtualMachineMock) Clone(ctx context.Context, config *CloneConfig) (VirtualMachine, error) {
vm.CloneCalled = true
vm.CloneConfig = config
return vm, vm.CloneError
return nil, nil
}
func (vm *VirtualMachineMock) updateVAppConfig(ctx context.Context, newProps map[string]string) (*types.VmConfigSpec, error) {
@@ -112,8 +107,8 @@ func (vm *VirtualMachineMock) Customize(spec types.CustomizationSpec) error {
return nil
}
func (vm *VirtualMachineMock) ResizeDisk(diskSize int64) ([]types.BaseVirtualDeviceConfigSpec, error) {
return nil, nil
func (vm *VirtualMachineMock) ResizeDisk(diskSize int64) error {
return nil
}
func (vm *VirtualMachineMock) PowerOn() error {
+6 -88
View File
@@ -1,7 +1,6 @@
package driver
import (
"context"
"testing"
"github.com/vmware/govmomi/simulator"
@@ -62,7 +61,7 @@ func TestVirtualMachineDriver_Configure(t *testing.T) {
}
}
func TestVirtualMachineDriver_CreateVMWithMultipleDisks(t *testing.T) {
func TestVirtualMachineDriver_CreateVM(t *testing.T) {
sim, err := NewVCenterSimulator()
if err != nil {
t.Fatalf("should not fail: %s", err.Error())
@@ -72,9 +71,10 @@ func TestVirtualMachineDriver_CreateVMWithMultipleDisks(t *testing.T) {
_, datastore := sim.ChooseSimulatorPreCreatedDatastore()
config := &CreateConfig{
Name: "mock name",
Host: "DC0_H0",
Datastore: datastore.Name,
Annotation: "mock annotation",
Name: "mock name",
Host: "DC0_H0",
Datastore: datastore.Name,
NICs: []NIC{
{
Network: "VM Network",
@@ -98,90 +98,8 @@ func TestVirtualMachineDriver_CreateVMWithMultipleDisks(t *testing.T) {
},
}
vm, err := sim.driver.CreateVM(config)
_, err = sim.driver.CreateVM(config)
if err != nil {
t.Fatalf("unexpected error %s", err.Error())
}
devices, err := vm.Devices()
if err != nil {
t.Fatalf("unexpected error %s", err.Error())
}
var disks []*types.VirtualDisk
for _, device := range devices {
switch d := device.(type) {
case *types.VirtualDisk:
disks = append(disks, d)
}
}
if len(disks) != 2 {
t.Fatalf("unexpected number of devices")
}
}
func TestVirtualMachineDriver_CloneWithPrimaryDiskResize(t *testing.T) {
sim, err := NewVCenterSimulator()
if err != nil {
t.Fatalf("should not fail: %s", err.Error())
}
defer sim.Close()
_, datastore := sim.ChooseSimulatorPreCreatedDatastore()
vm, _ := sim.ChooseSimulatorPreCreatedVM()
config := &CloneConfig{
Name: "mock name",
Host: "DC0_H0",
Datastore: datastore.Name,
PrimaryDiskSize: 204800,
StorageConfig: StorageConfig{
DiskControllerType: []string{"pvscsi"},
Storage: []Disk{
{
DiskSize: 3072,
DiskThinProvisioned: true,
ControllerIndex: 0,
},
{
DiskSize: 20480,
DiskThinProvisioned: true,
ControllerIndex: 0,
},
},
},
}
clonedVM, err := vm.Clone(context.TODO(), config)
if err != nil {
t.Fatalf("unexpected error %s", err.Error())
}
devices, err := clonedVM.Devices()
if err != nil {
t.Fatalf("unexpected error %s", err.Error())
}
var disks []*types.VirtualDisk
for _, device := range devices {
switch d := device.(type) {
case *types.VirtualDisk:
disks = append(disks, d)
}
}
if len(disks) != 3 {
t.Fatalf("unexpected number of devices")
}
if disks[0].CapacityInKB != config.PrimaryDiskSize*1024 {
t.Fatalf("unexpected disk size for primary disk: %d", disks[0].CapacityInKB)
}
if disks[1].CapacityInKB != config.StorageConfig.Storage[0].DiskSize*1024 {
t.Fatalf("unexpected disk size for primary disk: %d", disks[1].CapacityInKB)
}
if disks[2].CapacityInKB != config.StorageConfig.Storage[1].DiskSize*1024 {
t.Fatalf("unexpected disk size for primary disk: %d", disks[2].CapacityInKB)
}
}
+2
View File
@@ -95,6 +95,8 @@ func TestHelperProcess(*testing.T) {
os.Exit((&BuildCommand{Meta: commandMeta()}).Run(args))
case "hcl2_upgrade":
os.Exit((&HCL2UpgradeCommand{Meta: commandMeta()}).Run(args))
case "version":
os.Exit((&VersionCommand{Meta: commandMeta()}).Run(args))
default:
fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
os.Exit(2)
+26
View File
@@ -1,11 +1,37 @@
package command
import (
"fmt"
"testing"
"github.com/hashicorp/packer/version"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
)
func TestVersionCommand_implements(t *testing.T) {
var _ cli.Command = &VersionCommand{}
}
func Test_version(t *testing.T) {
tc := []struct {
command []string
env []string
expected string
}{
{[]string{"version"}, nil, fmt.Sprintf("Packer v%s", version.FormattedVersion()) + "\n"},
{[]string{"version", "&"}, nil, fmt.Sprintf("Packer v%s", version.FormattedVersion()) + "\n"},
}
for _, tc := range tc {
t.Run(fmt.Sprintf("packer %s", tc.command), func(t *testing.T) {
p := helperCommand(t, tc.command...)
bs, err := p.Output()
fmt.Println(err)
if err != nil {
t.Fatalf("%v: %s", err, bs)
}
assert.Equal(t, tc.expected, string(bs))
})
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ require (
github.com/Azure/go-autorest/autorest/to v0.3.0
github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0
github.com/Telmate/proxmox-api-go v0.0.0-20210331182840-ff89a0cebcfa
github.com/Telmate/proxmox-api-go v0.0.0-20210320143302-fea68269e6b0
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190418113227-25233c783f4e
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20170113022742-e6dbea820a9f
github.com/antihax/optional v1.0.0
+2 -2
View File
@@ -82,8 +82,8 @@ github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0/go.mod h1:P+3VS0ETiQPyWOx3
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/Telmate/proxmox-api-go v0.0.0-20200715182505-ec97c70ba887/go.mod h1:OGWyIMJ87/k/GCz8CGiWB2HOXsOVDM6Lpe/nFPkC4IQ=
github.com/Telmate/proxmox-api-go v0.0.0-20210331182840-ff89a0cebcfa h1:n4g0+o4DDX6WGTRfdj1Ux+49vSwtxtqFGB5XtxoDphI=
github.com/Telmate/proxmox-api-go v0.0.0-20210331182840-ff89a0cebcfa/go.mod h1:ayPkdmEKnlssqLQ9K1BE1jlsaYhXVwkoduXI30oQF0I=
github.com/Telmate/proxmox-api-go v0.0.0-20210320143302-fea68269e6b0 h1:LeBf+Ex12uqA6dWZp73Qf3dzpV/LvB9SRmHgPBwnXrQ=
github.com/Telmate/proxmox-api-go v0.0.0-20210320143302-fea68269e6b0/go.mod h1:ayPkdmEKnlssqLQ9K1BE1jlsaYhXVwkoduXI30oQF0I=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw=
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
+2 -10
View File
@@ -126,15 +126,6 @@ func realMain() int {
// wrappedMain is called only when we're wrapped by panicwrap and
// returns the exit status to exit with.
func wrappedMain() int {
// WARNING: WrappedMain causes unexpected behaviors when writing to stderr
// and stdout. Anything in this function written to stderr will be captured
// by the logger, but will not be written to the terminal. Anything in
// this function written to standard out must be prefixed with ErrorPrefix
// or OutputPrefix to be sent to the right terminal stream, but adding
// these prefixes can cause nondeterministic results for output from
// other, asynchronous methods. Try to avoid modifying output in this
// function if at all possible.
// If there is no explicit number of Go threads to use, then set it
if os.Getenv("GOMAXPROCS") == "" {
runtime.GOMAXPROCS(runtime.NumCPU())
@@ -475,8 +466,9 @@ func inPlugin() bool {
return os.Getenv(pluginsdk.MagicCookieKey) == pluginsdk.MagicCookieValue
}
// junk
func init() {
// Seed the random number generator
rand.Seed(time.Now().UTC().UnixNano())
}
var backgroundCheckFn func(int) (bool, error)
+9
View File
@@ -2,6 +2,7 @@ package main
import (
"math/rand"
"os"
"reflect"
"strings"
"testing"
@@ -67,3 +68,11 @@ func TestRandom(t *testing.T) {
t.Fatal("math.rand is not seeded properly")
}
}
func ExampleWrappedMain() {
os.Setenv("PACKER_WRAP_COOKIE", "49C22B1A-3A93-4C98-97FA-E07D18C787B5")
backgroundCheckFn = func(_ int) (bool, error) { return true, nil }
os.Args = []string{"packer", "version"}
wrappedMain()
//Output: Packer v1.7.2-dev
}
@@ -52,7 +52,6 @@ type FlatConfig struct {
AlicloudSourceImage *string `mapstructure:"source_image" required:"true" cty:"source_image" hcl:"source_image"`
ForceStopInstance *bool `mapstructure:"force_stop_instance" required:"false" cty:"force_stop_instance" hcl:"force_stop_instance"`
DisableStopInstance *bool `mapstructure:"disable_stop_instance" required:"false" cty:"disable_stop_instance" hcl:"disable_stop_instance"`
RamRoleName *string `mapstructure:"ram_role_name" required:"false" cty:"ram_role_name" hcl:"ram_role_name"`
SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id" hcl:"security_group_id"`
SecurityGroupName *string `mapstructure:"security_group_name" required:"false" cty:"security_group_name" hcl:"security_group_name"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
@@ -178,7 +177,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"source_image": &hcldec.AttrSpec{Name: "source_image", Type: cty.String, Required: false},
"force_stop_instance": &hcldec.AttrSpec{Name: "force_stop_instance", Type: cty.Bool, Required: false},
"disable_stop_instance": &hcldec.AttrSpec{Name: "disable_stop_instance", Type: cty.Bool, Required: false},
"ram_role_name": &hcldec.AttrSpec{Name: "ram_role_name", Type: cty.String, Required: false},
"security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false},
"security_group_name": &hcldec.AttrSpec{Name: "security_group_name", Type: cty.String, Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
+1 -1
View File
@@ -301,7 +301,7 @@ func (a *AgentNetworkInterface) UnmarshalJSON(b []byte) error {
a.IPAddresses = make([]net.IP, len(intermediate.IPAddresses))
for idx, ip := range intermediate.IPAddresses {
a.IPAddresses[idx] = net.ParseIP((strings.Split(ip.IPAddress, "%"))[0])
a.IPAddresses[idx] = net.ParseIP(ip.IPAddress)
if a.IPAddresses[idx] == nil {
return fmt.Errorf("Could not parse %s as IP", ip.IPAddress)
}
-5
View File
@@ -628,11 +628,6 @@ func NewConfigQemuFromApi(vmr *VmRef, client *Client) (config *ConfigQemu, err e
diskConfMap["storage_type"] = storageType
// cloud-init disks not always have the size sent by the API, which results in a crash
if diskConfMap["size"] == nil && strings.Contains(fileName.(string), "cloudinit") {
diskConfMap["size"] = "4M" // default cloud-init disk size
}
// Convert to gigabytes if disk size was received in terabytes
sizeIsInTerabytes, err := regexp.MatchString("[0-9]+T", diskConfMap["size"].(string))
if err != nil {
+1 -1
View File
@@ -78,7 +78,7 @@ github.com/NaverCloudPlatform/ncloud-sdk-go-v2/ncloud
github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server
# github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d
github.com/StackExchange/wmi
# github.com/Telmate/proxmox-api-go v0.0.0-20210331182840-ff89a0cebcfa
# github.com/Telmate/proxmox-api-go v0.0.0-20210320143302-fea68269e6b0
## explicit
github.com/Telmate/proxmox-api-go/proxmox
# github.com/agext/levenshtein v1.2.1
+1 -1
View File
@@ -14,7 +14,7 @@ const Version = "1.7.2"
// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""
const VersionPrerelease = "dev"
var PackerVersion *pluginVersion.PluginVersion
@@ -1,42 +0,0 @@
import CommandLineTerminal from '@hashicorp/react-command-line-terminal'
import { useEffect, useState } from 'react'
export default function AnimatedTerminal({
lines,
frameLength = 1000,
paused,
loop,
}) {
// Determine the total number of frames
let totalFrames = 0
lines.forEach((line) => {
let frames = line.frames ? line.frames : 1
if (Array.isArray(line.code)) {
totalFrames += line.code.length * frames
} else {
totalFrames += frames
}
})
// Set up Animation
const [frame, setFrame] = useState(0)
useEffect(() => {
let interval = setInterval(() => {
if (paused) return
if (loop) return setFrame((frame) => frame + 1)
if (frame + 1 < totalFrames) {
setFrame((frame) => frame + 1)
}
}, frameLength)
return () => clearInterval(interval)
}, [frame])
// Reset Frames if our lines change
useEffect(() => {
setFrame(0)
}, [lines])
const renderedLines = [...lines.slice(0, frame)]
return <CommandLineTerminal product="packer" lines={renderedLines} />
}
-33
View File
@@ -1,33 +0,0 @@
import s from './style.module.css'
import Button from '@hashicorp/react-button'
export default function BrandedCta({ heading, content, links }) {
return (
<div className={s.brandedCta}>
<div className={`g-grid-container ${s.contentContainer}`}>
<h2 className={`g-type-display-2 ${s.heading}`}>{heading}</h2>
<div className="content-and-links">
<p className={`g-type-body-large ${s.content}`}>{content}</p>
<div className={s.links}>
{links.map((link, stableIdx) => {
return (
<Button
// eslint-disable-next-line react/no-array-index-key
key={stableIdx}
linkType={link.type || ''}
theme={{
variant: stableIdx === 0 ? 'primary' : 'secondary',
brand: 'packer',
background: 'light',
}}
title={link.text}
url={link.url}
/>
)
})}
</div>
</div>
</div>
</div>
)
}
@@ -1,67 +0,0 @@
.brandedCta {
padding: 88px 0;
background-color: var(--packer-secondary);
background-image: url('/img/branded-cta/cta-right.svg');
background-position: bottom right;
background-size: auto 100%;
background-repeat: no-repeat;
@media (--small) {
background-position: bottom 0 right -130px;
}
@media (462px <= width < 600px) {
background-position: bottom 0 right -260px;
}
@media (width < 462px) {
background-position: bottom 0 right -170px;
}
}
.contentContainer {
@media (width >= 992px) {
display: flex;
}
@media (width < 992px) {
flex-direction: column;
}
}
.heading {
color: var(--black);
margin-top: 0;
@media (width >= 992px) {
flex-basis: 33.3%;
margin: 0;
}
}
.content {
max-width: 647px;
margin: 0;
color: var(--gray-2);
}
.content-and-links {
@media (width >= 992px) {
flex-basis: 66.6%;
margin-left: 32px;
}
& .g-type-body-large {
max-width: 35em;
}
}
.links {
margin-top: 40px;
margin-bottom: -16px;
& a {
margin-right: 16px;
margin-bottom: 16px;
}
}
@@ -1 +0,0 @@
<svg width="18" height="18" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M17.25 9A8.25 8.25 0 1 1 .75 9a8.25 8.25 0 0 1 16.5 0zm-11.47.223l1.72 1.72 4.19-4.504A.75.75 0 1 1 12.75 7.5l-4.72 5.034a.748.748 0 0 1-1.06 0l-2.25-2.25a.75.75 0 1 1 1.06-1.06z" fill="#2E71E5"/></svg>

Before

Width:  |  Height:  |  Size: 326 B

-5
View File
@@ -1,5 +0,0 @@
import s from './style.module.css'
export default function ChecklistWrapper({ children }) {
return <div className={s.root}>{children}</div>
}
@@ -1,20 +0,0 @@
.root {
& ul {
list-style: none;
margin-left: 2rem;
& li {
color: #525252;
&::before {
content: '';
display: block;
width: 18px;
margin-left: calc(-1 * 1.6rem);
height: 18px;
top: 7px;
background: url('./check-circle-filled.svg');
}
}
}
}
@@ -1,48 +0,0 @@
import Alert from '@hashicorp/react-alert'
import Button from '@hashicorp/react-button'
import s from './style.module.css'
export default function HomepageHero({
heading,
heroFeature,
subheading,
links,
alert,
}) {
return (
<div className={s.homepageHero}>
<div className={s.gridContainer}>
<div className={s.content}>
{alert ? (
<Alert
url={alert.url}
tag={alert.tag}
product="packer"
text={alert.text}
textColor="dark"
/>
) : null}
<h1 className={s.heading}>{heading}</h1>
<p className={s.subheading}>{subheading}</p>
<div className={s.links}>
{links.map((link, index) => (
<Button
key={link.text}
title={link.text}
linkType={link.type}
url={link.url}
theme={{
variant: index === 0 ? 'primary' : 'secondary',
brand: index === 0 ? 'packer' : 'neutral',
}}
/>
))}
</div>
</div>
<div className={s.heroFeature}>
<div className={s.heroFeatureFrame}>{heroFeature}</div>
</div>
</div>
</div>
)
}
@@ -1,90 +0,0 @@
.homepageHero {
min-height: min(45vw, 600px);
padding: 64px 0;
display: flex;
flex-direction: column;
justify-content: center;
background-color: #f0fbff;
background-image: url(/img/homepage-hero/hero-right.svg);
background-position: bottom -250px right;
background-repeat: no-repeat;
background-size: contain;
@media (--medium-up) {
background-position: top right;
}
}
.gridContainer {
composes: g-grid-container from global;
position: relative;
@media (--large) {
display: grid;
grid-template-columns: 1fr 1fr;
align-items: center;
width: 100%;
}
}
.content {
max-width: 350px;
display: flex;
flex-direction: column;
text-align: center;
color: var(--gray-2);
@media (--medium-up) {
max-width: 550px;
}
@media (--large) {
align-items: flex-start;
text-align: left;
width: 100%;
}
}
.heading {
composes: g-type-display-1 from global;
margin-top: 12px;
margin-bottom: 24px;
}
.heroFeature {
display: none;
position: relative;
@media (--large) {
display: flex;
min-height: 500px;
}
}
.heroFeatureFrame {
position: absolute;
width: calc(100% + 80px);
height: 100%;
}
.links {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
width: 100%;
& a {
margin-right: 8px;
margin-bottom: 8px;
}
@media (--large) {
width: auto;
justify-content: flex-start;
}
}
.subheading {
composes: g-type-body-large from global;
color: inherit;
margin: 0;
font-size: 17px;
line-height: 25px;
margin-bottom: 40px;
}
@@ -1,21 +0,0 @@
import TextSplitWithImage from '@hashicorp/react-text-split-with-image'
export default function IntegrationsTextSplit({
heading,
links,
content,
image,
}) {
return (
<TextSplitWithImage
textSplit={{
heading,
product: 'packer',
content,
linkStyle: 'buttons',
links,
}}
image={image}
/>
)
}
@@ -29,6 +29,12 @@ to match Terraform Registry tier labels.
}
}
/* add margin-top to separate from the adjacent
search bar present on docs pages */
:global(.g-search) + .root {
margin-top: 40px;
}
.text {
/* composes */
composes: g-type-body-small-strong from global;
+11 -22
View File
@@ -7,37 +7,24 @@ import {
import renderPageMdx from '@hashicorp/react-docs-page/render-page-mdx'
import resolveNavData from './utils/resolve-nav-data'
async function generateStaticPaths({
navDataFile,
localContentDir,
remotePluginsFile,
}) {
const navData = await resolveNavData(navDataFile, localContentDir, {
remotePluginsFile,
})
async function generateStaticPaths(navDataFile, contentDir, options = {}) {
const navData = await resolveNavData(navDataFile, contentDir, options)
const paths = await getPathsFromNavData(navData)
return paths
}
async function generateStaticProps({
additionalComponents,
localContentDir,
mainBranch = 'main',
async function generateStaticProps(
navDataFile,
localContentDir,
params,
product,
remotePluginsFile,
}) {
// Build the currentPath from page parameters
const currentPath = params.page ? params.page.join('/') : ''
// Resolve navData, including the possibility that this
// page is a remote plugin docs, in which case we'll provide
// the MDX fileString in the resolved navData
{ remotePluginsFile, additionalComponents, mainBranch = 'main' } = {}
) {
const navData = await resolveNavData(navDataFile, localContentDir, {
remotePluginsFile,
currentPath,
})
const navNode = getNodeFromPath(currentPath, navData, localContentDir)
const pathToMatch = params.page ? params.page.join('/') : ''
const navNode = getNodeFromPath(pathToMatch, navData, localContentDir)
const { filePath, remoteFile, pluginTier } = navNode
// Fetch the MDX file content
const mdxString = remoteFile
@@ -54,7 +41,7 @@ async function generateStaticProps({
// (current options are "Official" or "Community")
function mdxContentHook(mdxContent) {
if (pluginTier) {
const tierMdx = `<br/><PluginTierLabel tier="${pluginTier}" />\n\n`
const tierMdx = `<PluginTierLabel tier="${pluginTier}" />\n\n`
mdxContent = tierMdx + mdxContent
}
return mdxContent
@@ -64,6 +51,8 @@ async function generateStaticProps({
productName: product.name,
mdxContentHook,
})
// Build the currentPath from page parameters
const currentPath = !params.page ? '' : params.page.join('/')
return {
currentPath,
@@ -16,7 +16,7 @@ const validateRouteStructure = require('@hashicorp/react-docs-sidenav/utils/vali
* @returns {array} the resolved navData. This includes NavBranch nodes pulled from remote plugin repositories, as well as filePath properties on all local NavLeaf nodes, and remoteFile properties on all NavLeafRemote nodes.
*/
async function resolveNavData(navDataFile, localContentDir, options = {}) {
const { remotePluginsFile, currentPath } = options
const { remotePluginsFile } = options
// Read in files
const navDataPath = path.join(process.cwd(), navDataFile)
const navData = JSON.parse(fs.readFileSync(navDataPath, 'utf8'))
@@ -24,11 +24,7 @@ async function resolveNavData(navDataFile, localContentDir, options = {}) {
let withPlugins = navData
if (remotePluginsFile) {
// Resolve plugins, this yields branches with NavLeafRemote nodes
withPlugins = await mergeRemotePlugins(
remotePluginsFile,
navData,
currentPath
)
withPlugins = await mergeRemotePlugins(remotePluginsFile, navData)
}
// Resolve local filePaths for NavLeaf nodes
const withFilePaths = await validateFilePaths(withPlugins, localContentDir)
@@ -44,16 +40,14 @@ async function resolveNavData(navDataFile, localContentDir, options = {}) {
// fetch and parse all remote plugin docs, merge them into the
// broader tree of docs navData, and return the docs navData
// with the merged plugin docs
async function mergeRemotePlugins(remotePluginsFile, navData, currentPath) {
async function mergeRemotePlugins(remotePluginsFile, navData) {
// Read in and parse the plugin configuration JSON
const remotePluginsPath = path.join(process.cwd(), remotePluginsFile)
const pluginEntries = JSON.parse(fs.readFileSync(remotePluginsPath, 'utf-8'))
// Add navData for each plugin's component.
// Note that leaf nodes include a remoteFile property object with the full MDX fileString
const pluginEntriesWithDocs = await Promise.all(
pluginEntries.map(
async (entry) => await resolvePluginEntryDocs(entry, currentPath)
)
pluginEntries.map(resolvePluginEntryDocs)
)
// group navData by component type, to prepare to merge plugin docs
// into the broader tree of navData.
@@ -119,7 +113,7 @@ async function mergeRemotePlugins(remotePluginsFile, navData, currentPath) {
return { ...n, routes: routesWithPlugins }
})
// return the merged navData, which now includes special NavLeaf nodes
// for plugin docs with remoteFile properties
// for plugin docs with { filePath, fileString } remoteFile properties
return navDataWithPlugins
}
@@ -131,14 +125,8 @@ async function mergeRemotePlugins(remotePluginsFile, navData, currentPath) {
// Note that navData leaf nodes have a special remoteFile property,
// which contains { filePath, fileString } data for the remote
// plugin doc .mdx file
async function resolvePluginEntryDocs(pluginConfigEntry, currentPath) {
const {
title,
path: slug,
repo,
version,
sourceBranch = 'main',
} = pluginConfigEntry
async function resolvePluginEntryDocs(pluginConfigEntry) {
const { title, path: slug, repo, version } = pluginConfigEntry
const docsMdxFiles = await fetchPluginDocs({ repo, tag: version })
// We construct a special kind of "NavLeaf" node, with a remoteFile property,
// consisting of a { filePath, fileString, sourceUrl }, where:
@@ -161,7 +149,7 @@ async function resolvePluginEntryDocs(pluginConfigEntry, currentPath) {
const { nav_title, sidebar_title } = frontmatter
const title = nav_title || sidebar_title || basename
// construct sourceUrl (used for "Edit this page" link)
const sourceUrl = `https://github.com/${repo}/blob/${sourceBranch}/${filePath}`
const sourceUrl = `https://github.com/${repo}/blob/${version}/${filePath}`
// determine pluginTier
const pluginOwner = repo.split('/')[0]
const pluginTier = pluginOwner === 'hashicorp' ? 'official' : 'community'
@@ -204,21 +192,8 @@ async function resolvePluginEntryDocs(pluginConfigEntry, currentPath) {
const prefixedPath = path.join(pathPrefix, n.path)
return { ...n, path: prefixedPath }
})
// If currentPath is provided, then remove the remoteFile
// from all nodes except the currentPath. This ensures we deliver
// only a single fileString in our getStaticProps JSON.
// Without this optimization, we would send all fileStrings
// for all NavLeafRemote nodes
const withOptimizedFileStrings = visitNavLeaves(withPrefixedPaths, (n) => {
if (!n.remoteFile) return n
const noCurrentPath = typeof currentPath === 'undefined'
const isPathMatch = currentPath === n.path
if (noCurrentPath || isPathMatch) return n
const { filePath } = n.remoteFile
return { ...n, remoteFile: { filePath } }
})
// Return the component, with processed navData
return { type, navData: withOptimizedFileStrings }
//
return { type, navData: withPrefixedPaths }
})
const componentsObj = components.reduce((acc, component) => {
if (!component) return acc
@@ -1,21 +0,0 @@
import Button from '@hashicorp/react-button'
import s from './style.module.css'
export default function SectionBreakCta({ heading, link }) {
return (
<div className={s.sectionBreakCta}>
<hr />
<h4 className={s.heading}>{heading}</h4>
<Button
title={link.text}
url={link.url}
theme={{
brand: 'neutral',
variant: 'tertiary-neutral',
background: 'light',
}}
linkType="outbound"
/>
</div>
)
}
@@ -1,33 +0,0 @@
.sectionBreakCta {
padding: 88px 24px;
max-width: 800px;
display: grid;
grid-gap: 24px;
text-align: center;
position: relative;
box-shadow: 0 8px 12px rgba(37, 38, 45, 0.08);
margin: 0 16px;
background-color: var(--white);
align-items: center;
@media (--medium-up) {
margin: 0 auto 104px auto;
}
& hr {
position: absolute;
top: 56px;
left: calc(50% - 32px);
width: 64px;
background-color: var(--packer);
margin-top: 0;
margin-bottom: 24px;
}
}
.heading {
composes: g-type-display-4 from global;
margin: 0;
@media (--medium-up) {
padding: 0 88px;
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ export default function PackerSubnav() {
{ text: 'GitHub', url: 'https://www.github.com/hashicorp/packer' },
{ text: 'Download', url: '/downloads' },
]}
currentPath={router.asPath}
currentPath={router.pathname}
menuItemsAlign="right"
menuItems={subnavItems}
constrainWidth
@@ -3,6 +3,7 @@ description: |
The `alicloud-ecs` Packer builder plugin provide the capability to build
customized images based on an existing base images.
page_title: Alicloud Image Builder
sidebar_title: Alicloud ECS
---
# Alicloud Image Builder
@@ -1,6 +1,7 @@
---
description: Packer supports building VHDs in Azure Resource manager.
page_title: Azure arm - Builders
sidebar_title: ARM
---
# Azure Resource Manager Builder
+28 -27
View File
@@ -5,6 +5,7 @@ description: >
a VM in Azure.
page_title: Azure chroot - Builders
sidebar_title: chroot
---
# Azure Builder (chroot)
@@ -260,36 +261,36 @@ build {
</Tab>
<Tab heading="JSON">
```json
{
"variables": {
"client_id": "{{env `ARM_CLIENT_ID`}}",
"client_secret": "{{env `ARM_CLIENT_SECRET`}}",
"subscription_id": "{{env `ARM_SUBSCRIPTION_ID`}}",
"resource_group": "{{env `ARM_IMAGE_RESOURCEGROUP_ID`}}"
},
"builders": [
{
"type": "azure-chroot",
```json
{
"variables": {
"client_id": "{{env `ARM_CLIENT_ID`}}",
"client_secret": "{{env `ARM_CLIENT_SECRET`}}",
"subscription_id": "{{env `ARM_SUBSCRIPTION_ID`}}",
"resource_group": "{{env `ARM_IMAGE_RESOURCEGROUP_ID`}}"
},
"builders": [
{
"type": "azure-chroot",
"client_id": "{{user `client_id`}}",
"client_secret": "{{user `client_secret`}}",
"subscription_id": "{{user `subscription_id`}}",
"client_id": "{{user `client_id`}}",
"client_secret": "{{user `client_secret`}}",
"subscription_id": "{{user `subscription_id`}}",
"image_resource_id": "/subscriptions/{{user `subscription_id`}}/resourceGroups/{{user `resource_group`}}/providers/Microsoft.Compute/images/MyDebianOSImage-{{timestamp}}",
"image_resource_id": "/subscriptions/{{user `subscription_id`}}/resourceGroups/{{user `resource_group`}}/providers/Microsoft.Compute/images/MyDebianOSImage-{{timestamp}}",
"source": "credativ:Debian:9:latest"
}
],
"provisioners": [
{
"inline": ["apt-get update", "apt-get upgrade -y"],
"inline_shebang": "/bin/sh -x",
"type": "shell"
}
]
}
```
"source": "credativ:Debian:9:latest"
}
],
"provisioners": [
{
"inline": ["apt-get update", "apt-get upgrade -y"],
"inline_shebang": "/bin/sh -x",
"type": "shell"
}
]
}
```
</Tab>
</Tabs>
@@ -5,6 +5,7 @@ description: >
multiple builders depending on the strategy you want to use to build the
images.
page_title: Azure images - Builders
sidebar_title: Azure
---
# Azure Virtual Machine Image Builders
@@ -5,6 +5,7 @@ description: |
source, runs any provisioning necessary on the instance after launching it and
then creates a new template from that instance.
page_title: CloudStack - Builders
sidebar_title: CloudStack
---
# CloudStack Builder
@@ -3,6 +3,7 @@ description: |
Community-maintained builders are not part of the core Packer binary, but
can run alongside Packer with minimal extra effort.
page_title: Community - Builders
sidebar_title: Community-Supported
---
# Community Builders
+1
View File
@@ -4,6 +4,7 @@ description: |
modify the core source code of Packer itself. Documentation for creating new
builders is covered in the custom builders page of the Packer plugin section.
page_title: Custom - Builders
sidebar_title: Custom
---
# Custom Builder
@@ -11,6 +11,7 @@ description: >
launched within DigitalOcean.
page_title: DigitalOcean - Builders
sidebar_title: DigitalOcean
---
# DigitalOcean Builder
@@ -66,4 +67,4 @@ In addition to the builder options, a
@include 'packer-plugin-sdk/communicator/SSH-not-required.mdx'
@include 'packer-plugin-sdk/communicator/SSH-Private-Key-File-not-required.mdx'
@include 'packer-plugin-sdk/communicator/SSH-Private-Key-File-not-required.mdx'
+1
View File
@@ -4,6 +4,7 @@ description: |
from a file. It can be used to debug post-processors without incurring high
wait times.
page_title: File - Builders
sidebar_title: File
---
# File Builder
@@ -3,6 +3,7 @@ description: |
The googlecompute Packer builder is able to create images for use with Google
Cloud Compute Engine (GCE) based on existing images.
page_title: Google Compute - Builders
sidebar_title: Google Cloud
---
# Google Compute Builder
@@ -6,6 +6,7 @@ description: |
image. This reusable image can then be used as the foundation of new servers
that are launched within the Hetzner Cloud.
page_title: Hetzner Cloud - Builders
sidebar_title: Hetzner Cloud
---
# Hetzner Cloud Builder
@@ -4,6 +4,7 @@ description: |
The builder takes a source image, runs any provisioning necessary on
the image after launching it, then creates a reusable image.
page_title: HyperOne - Builders
sidebar_title: HyperOne
---
# HyperOne Builder
@@ -3,6 +3,7 @@ description: |
The Hyper-V Packer builder is able to create Hyper-V virtual machines and
export them.
page_title: Hyper-V - Builders
sidebar_title: Hyper-V
---
# HyperV Builder
@@ -5,6 +5,7 @@ description: |
The Hyper-V Packer builder is able to create Hyper-V virtual machines and
export them.
page_title: Hyper-V ISO - Builders
sidebar_title: ISO
---
# Hyper-V Builder (from an ISO)
@@ -5,6 +5,7 @@ description: >-
The Hyper-V Packer builder is able to clone an existing Hyper-V virtual
machine and export them.
page_title: Hyper-V Builder (from a vmcx)
sidebar_title: VMCX
---
# Hyper-V Builder (from a vmcx)
+2
View File
@@ -3,6 +3,7 @@ description: |
Builders are responsible for creating machines and generating images from them
for various platforms.
page_title: Builders
sidebar_title: Builders
---
# Builders
@@ -16,3 +17,4 @@ See the [`source`](/docs/templates/hcl_templates/blocks/source) block documentat
about configuring builders in the Packer language.
For information on an individual builder, choose it from the sidebar. Each
builder has its own configuration options and parameters.
@@ -3,6 +3,7 @@ description: |
The `jdcloud` Packer builder helps you to build instance images
based on an existing image
page_title: JDCloud Image Builder
sidebar_title: JDCloud
---
# JDCloud Image Builder
+1 -1
View File
@@ -11,6 +11,7 @@ description: >
within all Linode regions.
page_title: Linode - Builders
sidebar_title: Linode
---
# Linode Builder
@@ -47,7 +48,6 @@ can also be supplied to override the typical auto-generated key:
See https://github.com/tcort/markdown-link-check/issues/109
-->
### Required
- `linode_token` (string) - The client TOKEN to use to access your account.
+1
View File
@@ -4,6 +4,7 @@ description: |
container, runs provisioners within this container, then exports the container
as a tar.gz of the root file system.
page_title: LXC - Builders
sidebar_title: LXC
---
# LXC Builder
+1
View File
@@ -7,6 +7,7 @@ description: >
an LXD image.
page_title: LXD - Builders
sidebar_title: LXD
---
# LXD Builder
+1
View File
@@ -3,6 +3,7 @@ description: |
The ncloud builder allows you to create server images using the NAVER Cloud
Platform.
page_title: Naver Cloud Platform - Builders
sidebar_title: NAVER Cloud
---
# NAVER CLOUD PLATFORM Builder
+1
View File
@@ -5,6 +5,7 @@ description: |
without incurring high wait times. It does not create any kind of image or
artifact.
page_title: Null - Builders
sidebar_title: 'Null'
---
# Null Builder
+2 -2
View File
@@ -1,6 +1,7 @@
---
description: The 1&1 builder is able to create images for 1&1 cloud.
page_title: 1&1 - Builders
sidebar_title: 1&amp;1
---
# 1&1 Builder
@@ -46,9 +47,8 @@ can also be supplied to override the typical auto-generated key:
while waiting for the build to complete. Default value "600".
<!-- markdown-link-check-disable -->
- `url` (string) - Endpoint for the 1&1 REST API. Default URL
"<https://cloudpanel-api.1and1.com/v1>"
"<https://cloudpanel-api.1and1.com/v1>"
<!-- markdown-link-check-enable -->
## Example
+3 -7
View File
@@ -11,6 +11,7 @@ description: >
within OpenStack.
page_title: OpenStack - Builders
sidebar_title: OpenStack
---
# OpenStack Builder
@@ -131,7 +132,6 @@ builders "openstack" {
insecure = "true"
}
```
</Tab>
</Tabs>
@@ -155,7 +155,6 @@ Here is a basic example. This is a working example to build a Ubuntu 12.04 LTS
"flavor": "2"
}
```
</Tab>
<Tab heading="HCL2">
@@ -171,7 +170,6 @@ builders "openstack" {
flavor = "2"
}
```
</Tab>
</Tabs>
@@ -192,7 +190,6 @@ by Metacloud.
"flavor": "2"
}
```
</Tab>
<Tab heading="HCL2">
@@ -205,10 +202,10 @@ builders "openstack" {
flavor = "2"
}
```
</Tab>
</Tabs>
In this case, the connection information for connecting to OpenStack doesn't
appear in the template. That is because I source a standard OpenStack script
with environment variables set before I run this. This script is setting
@@ -269,7 +266,6 @@ by Selectel VPC.
"volume_type": "fast.ru-3a"
}
```
</Tab>
<Tab heading="HCL2">
@@ -291,10 +287,10 @@ builders "openstack" {
volume_type = "fast.ru-3a"
}
```
</Tab>
</Tabs>
## Notes on OpenStack Authorization
The simplest way to get all settings for authorization against OpenStack is to
@@ -3,6 +3,7 @@ description: |
The oracle-classic builder is able to create new custom images for use with
Oracle Cloud Infrastructure Classic Compute.
page_title: Oracle Cloud Infrastructure Classic - Builders
sidebar_title: Oracle Classic
---
# Oracle Cloud Infrastructure Classic Compute Builder
@@ -1,6 +1,7 @@
---
description: Packer is able to create custom images using Oracle Cloud Infrastructure.
page_title: Oracle - Builders
sidebar_title: Oracle
---
# Oracle Builder
+7 -7
View File
@@ -3,6 +3,7 @@ description: |
The oracle-oci builder is able to create new custom images for use with Oracle
Cloud Infrastructure (OCI).
page_title: Oracle OCI - Builders
sidebar_title: Oracle OCI
---
# Oracle Cloud Infrastructure (OCI) Builder
@@ -188,19 +189,18 @@ can also be supplied to override the typical auto-generated key:
- `use_private_ip` (boolean) - Use private ip addresses to connect to the
instance via ssh.
- `shape_config` (object) - The shape configuration for an instance. The shape configuration determines the resources
- `shape_config` (object) - The shape configuration for an instance. The shape configuration determines the resources
allocated to an instance. Options:
- `ocpus` (required when using flexible shapes or memory_in_gbs is set) (float32) - The total number of OCPUs available to the instance.
- `memory_in_gbs` (optional) (float32) - The total amount of memory, in gigabytes, available to the instance.
<!-- markdown-link-check-disable -->
- `metadata` (map of strings) - Metadata optionally contains custom metadata
key/value pairs provided in the configuration. While this can be used to
set metadata\["user_data"\] the explicit "user_data" and
"user_data_file" values will have precedence. An instance's metadata can
be obtained from at [http://169.254.169.254](http://169.254.169.254) on
the launched instance.
key/value pairs provided in the configuration. While this can be used to
set metadata\["user_data"\] the explicit "user_data" and
"user_data_file" values will have precedence. An instance's metadata can
be obtained from at [http://169.254.169.254](http://169.254.169.254) on
the launched instance.
<!-- markdown-link-check-enable -->
- `user_data` (string) - User data to be used by cloud-init. See [the Oracle
@@ -7,6 +7,7 @@ description: >
the root device section in the Outscale documentation.
page_title: Outscale BSU - Builders
sidebar_title: BSU
---
# OMI Builder (BSU backed)
@@ -3,6 +3,7 @@ description: |
The osc-bsusurrogate Packer builder is like the chroot builder, but does not
require running inside an Outscale virtual machine.
page_title: Outscale BSU Surrogate - Builders
sidebar_title: BSU Surrogate
---
# BSU Surrogate Builder
@@ -3,6 +3,7 @@ description: |
The osc-bsuvolume Packer builder is like the BSU builder, but is intended to
create BSU volumes rather than a machine image.
page_title: Outscale BSU Volume - Builders
sidebar_title: BSU Volume
---
# BSU Volume Builder
@@ -9,6 +9,7 @@ description: >
in the Outscale documentation.
page_title: Outscale chroot - Builders
sidebar_title: chroot
---
# OMI Builder (chroot)
@@ -5,6 +5,7 @@ description: >
multiple builders depending on the strategy you want to use to build the OMI.
page_title: Outscale OMI - Builders
sidebar_title: Outscale
---
# Outscale OMI Builder
@@ -3,6 +3,7 @@ description: |
The Parallels Packer builder is able to create Parallels Desktop for Mac
virtual machines and export them in the PVM format.
page_title: Parallels - Builders
sidebar_title: Parallels
---
# Parallels Builder
@@ -6,6 +6,7 @@ description: |
virtual machines and export them in the PVM format, starting from an ISO
image.
page_title: Parallels ISO - Builders
sidebar_title: ISO
---
# Parallels Builder (from an ISO)
@@ -6,6 +6,7 @@ description: |
machines and export them in the PVM format, starting from an existing PVM
(exported virtual machine image).
page_title: Parallels PVM - Builders
sidebar_title: PVM
---
# Parallels Builder (from a PVM)
@@ -1,6 +1,7 @@
---
description: The ProfitBricks builder is able to create images for ProfitBricks cloud.
page_title: ProfitBricks - Builders
sidebar_title: ProfitBricks
---
# ProfitBricks Builder
@@ -62,7 +63,7 @@ can also be supplied to override the typical auto-generated key:
- `snapshot_password` (string) - Password for the snapshot.
<!-- markdown-link-check-disable -->
- `url` (string) - Endpoint for the ProfitBricks REST API. Default URL
"<https://api.profitbricks.com/rest/v2>"
"<https://api.profitbricks.com/rest/v2>"
<!-- markdown-link-check-enable -->
## Example
@@ -5,6 +5,7 @@ description: |
template name, runs any provisioning necessary on the image after
launching it, then creates a virtual machine template.
page_title: Proxmox Clone - Builders
sidebar_title: Clone
---
# Proxmox Builder (from an image)
@@ -3,13 +3,14 @@ description: >
The Proxmox Packer builder is able to create Cloud-Init virtual machine images
on a Proxmox server.
page_title: Proxmox - Builders
sidebar_title: Proxmox
---
# Proxmox Builder
The Proxmox Packer builder is able to create
[Proxmox](https://www.proxmox.com/en/proxmox-ve) virtual
machines and store them as new Proxmox Virtual Machine images.
machines and store them as new Proxmox Virutal Machine images.
Packer is able to target both ISO and existing Cloud-Init images:
@@ -5,6 +5,7 @@ description: |
necessary on the image after launching it, then creates a virtual machine
template.
page_title: Proxmox ISO - Builders
sidebar_title: ISO
---
# Proxmox Builder (from an ISO)
@@ -222,7 +223,7 @@ builder.
Defaults to `lsi`.
- `cloud_init` (bool) - If true, add a Cloud-Init CDROM drive after the virtual machine has been converted to a template.
Defaults to `false`.
Defaults to `false`.
- `cloud_init_storage_pool` - (string) - Name of the Proxmox storage pool
to store the Cloud-Init CDROM on. If not given, the storage pool of the boot device will be used.
+1
View File
@@ -4,6 +4,7 @@ modeline: |
description: |
The Qemu Packer builder is able to create KVM virtual machine images.
page_title: QEMU - Builders
sidebar_title: QEMU
---
# QEMU Builder
+2 -2
View File
@@ -11,6 +11,7 @@ description: >
servers that are launched within Scaleway.
page_title: Scaleway - Builders
sidebar_title: Scaleway
---
# Scaleway Builder
@@ -69,7 +70,6 @@ access tokens:
"ssh_private_key_file": "~/.ssh/id_rsa"
}
```
</Tab>
<Tab heading="HCL2">
@@ -86,10 +86,10 @@ builders "scaleway" {
ssh_private_key_file = "~/.ssh/id_rsa"
}
```
</Tab>
</Tabs>
When you do not specify the `ssh_private_key_file`, a temporary SSH keypair
is generated to connect the server. This key will only allow the `root` user to
connect the server.
@@ -3,6 +3,7 @@ description: |
The `tencentcloud-cvm` Packer builder plugin provide the capability to build
customized images based on an existing base images.
page_title: Tencentcloud Image Builder
sidebar_title: Tencent Cloud
---
# Tencentcloud Image Builder
+1
View File
@@ -10,6 +10,7 @@ description: >
Cloud API to create images.
page_title: Triton - Builders
sidebar_title: Triton
---
# Triton Builder
@@ -3,6 +3,7 @@ description: |
The `ucloud-uhost` Packer builder plugin provides the capability to build
customized images based on an existing base image for use in UHost Instance.
page_title: UCloud Image Builder
sidebar_title: UCloud
---
# UCloud Image Builder
+6 -5
View File
@@ -3,6 +3,7 @@ description: |
The Vagrant Packer builder is able to launch Vagrant boxes and
re-package them into .box files
page_title: Vagrant - Builders
sidebar_title: Vagrant
---
# Vagrant Builder
@@ -184,13 +185,13 @@ build {
## Regarding output directory and new box
After Packer completes building and provisioning a new Vagrant Box file, it is worth
noting that the new box file will need to be added to Vagrant. For a beginner to Packer
After Packer completes building and provisioning a new Vagrant Box file, it is worth
noting that the new box file will need to be added to Vagrant. For a beginner to Packer
and Vagrant, it may seem as if a simple 'vagrant up' in the output directory will run the
the newly created Box. This is not the case.
the newly created Box. This is not the case.
Rather, create a new directory (to avoid Vagarant init collisions), add the new
package.box to Vagrant and init. Then run vagrant up to bring up the new box created
Rather, create a new directory (to avoid Vagarant init collisions), add the new
package.box to Vagrant and init. Then run vagrant up to bring up the new box created
by Packer. You will now be able to connect to the new box with provisioned changes.
```
@@ -5,6 +5,7 @@ description: >
export them in the OVA or OVF format.
page_title: VirtualBox - Builders
sidebar_title: VirtualBox
---
# VirtualBox Builder
@@ -5,6 +5,7 @@ description: |
The VirtualBox Packer builder is able to create VirtualBox virtual machines
and export them in the OVF format, starting from an ISO image.
page_title: VirtualBox ISO - Builders
sidebar_title: ISO
---
# VirtualBox Builder (from an ISO)
@@ -6,6 +6,7 @@ description: |
and export them in the OVF format, starting from an existing OVF/OVA (exported
virtual machine image).
page_title: VirtualBox OVF/OVA - Builders
sidebar_title: OVF
---
# VirtualBox Builder (from an OVF/OVA)
@@ -7,6 +7,7 @@ description: >
and export them in the OVF format, starting from an ISO image.
page_title: VirtualBox Snapshot - Builders
sidebar_title: VM
---
# VirtualBox Builder (from an existing VM)
@@ -3,6 +3,7 @@ description: |
The VMware Packer builder is able to create VMware virtual machines for use
with any VMware product.
page_title: VMware - Builders
sidebar_title: VMware
---
# VMware Builder
@@ -8,6 +8,7 @@ description: |
VMware Player on Linux. It can also build machines directly on VMware vSphere
Hypervisor using SSH as opposed to the vSphere API.
page_title: VMware ISO - Builders
sidebar_title: VMWare ISO
---
# VMware Builder (from ISO)
@@ -7,6 +7,7 @@ description: |
virtual machines on hosts running VMware Fusion Professional for OS X, VMware
Workstation for Linux and Windows, and VMware Player on Linux.
page_title: VMware VMX - Builders
sidebar_title: VMWare VMX
---
# VMware Builder (from VMX)
@@ -5,6 +5,7 @@ description: >
This VMware Packer builder uses the vSphere API to clone an existing vSphere
template and create a new virtual machine remotely.
page_title: VSphere Clone - Builders
sidebar_title: VSphere Clone
---
# VMWare Vsphere Clone Builder
@@ -5,6 +5,7 @@ description: |
This VMware Packer builder starts from an ISO and creates a vm using the
vSphere API to build on a remote VMWare machine.
page_title: VSphere ISO - Builders
sidebar_title: VSphere ISO
---
# Packer Builder for VMware vSphere
+1
View File
@@ -3,6 +3,7 @@ description: |
The yandex Packer builder is able to create images for use with
Yandex.Cloud based on existing images.
page_title: Yandex Compute - Builders
sidebar_title: Yandex.Cloud
---
# Yandex Compute Builder
+1
View File
@@ -5,6 +5,7 @@ description: |
template are executed in parallel, unless otherwise specified. And the
artifacts that are created will be outputted at the end of the build.
page_title: packer build - Commands
sidebar_title: <tt>build</tt>
---
# `build` Command
@@ -3,6 +3,7 @@ description: |
The `packer console` command allows you to experiment with Packer variable
interpolations.
page_title: packer console - Commands
sidebar_title: <tt>console</tt>
---
# `console` Command
+1
View File
@@ -5,6 +5,7 @@ description: |
of Packer. After you update to a new Packer release, you should run the fix
command to make sure your templates work with the new release.
page_title: packer fix - Commands
sidebar_title: <tt>fix</tt>
---
# `fix` Command
+1
View File
@@ -3,6 +3,7 @@ description: |
The `packer fmt` Packer command is used to format HCL2
configuration files to a canonical format and style.
page_title: packer fmt - Commands
sidebar_title: <tt>fmt</tt>
---
# `fmt` Command
+12 -8
View File
@@ -1,9 +1,10 @@
---
description: |
The `packer hcl2_upgrade` Packer command is used to transpile a JSON
configuration template to its formatted HCL2 counterpart. The command will
configuration template to it's formatted HCL2 counterpart. The command will
return a zero exit status on success, and a non-zero exit status on failure.
page_title: packer hcl2_upgrade - Commands
sidebar_title: <tt>hcl2_upgrade</tt>
---
-> **Note:** This command is Beta, and currently being improved upon; do not
@@ -34,13 +35,16 @@ From **v1.7.1**, the `hcl2_upgrade` command can upgrade a variables file.
```json
{
"variables": {
"aws_region": null,
"aws_secondary_region": "{{ env `AWS_DEFAULT_REGION` }}",
"aws_secret_key": "",
"aws_access_key": ""
},
"sensitive-variables": ["aws_secret_key", "aws_access_key"]
"variables": {
"aws_region": null,
"aws_secondary_region": "{{ env `AWS_DEFAULT_REGION` }}",
"aws_secret_key": "",
"aws_access_key": "",
},
"sensitive-variables": [
"aws_secret_key",
"aws_access_key",
]
}
```
+1
View File
@@ -6,6 +6,7 @@ description: |
additional options as well. Subcommands are executed with `packer SUBCOMMAND`,
where "SUBCOMMAND" is the actual command you wish to execute.
page_title: Commands
sidebar_title: Commands (CLI)
---
# Packer Commands (CLI)
+2 -1
View File
@@ -2,6 +2,7 @@
description: |
The `packer init` Packer command is used to download Packer plugin binaries.
page_title: packer init - Commands
sidebar_title: <tt>init</tt>
---
# `init` Command
@@ -36,6 +37,7 @@ for the ones that are missing.
`packer init -upgrade` will try to get the latest versions for all plugins.
Import a plugin using the [`required_plugin`](/docs/templates/hcl_templates/blocks/packer#specifying-plugin-requirements)
block :
@@ -53,7 +55,6 @@ packer {
HashiCorp does not officially verify third party Packer plugins, plugins not under the HashiCorp namespace `hashicorp/*`; as with all open source tools, please do your own due diligence when using a new tool.
## Plugin Selection
Plugin selection depends on the source and version constraints defined within the `required_plugins` block.
For each of the required plugins Packer will query the source repository `github.com/azr/happycloud` whose fully qualified address
is `https://github.com/azr/packer-plugin-happycloud` for a plugin matching the version constraints for the host operating system.

Some files were not shown because too many files have changed in this diff Show More