Add ISO builder which creates an empty VM
This commit is contained in:
parent
f909669670
commit
df40ffbe8d
4
build.sh
4
build.sh
|
@ -11,3 +11,7 @@ rm -f bin/*
|
|||
GOOS=darwin go build -o bin/packer-builder-vsphere-clone.macos ./clone
|
||||
GOOS=linux go build -o bin/packer-builder-vsphere-clone.linux ./clone
|
||||
GOOS=windows go build -o bin/packer-builder-vsphere-clone.exe ./clone
|
||||
|
||||
GOOS=darwin go build -o bin/packer-builder-vsphere-iso.macos ./iso
|
||||
GOOS=linux go build -o bin/packer-builder-vsphere-iso.linux ./iso
|
||||
GOOS=windows go build -o bin/packer-builder-vsphere-iso.exe ./iso
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package clone
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
packerCommon "github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
|
@ -75,18 +73,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
b.runner = packerCommon.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
b.runner.Run(state)
|
||||
|
||||
// If there was an error, return that
|
||||
if rawErr, ok := state.GetOk("error"); ok {
|
||||
return nil, rawErr.(error)
|
||||
}
|
||||
|
||||
// If we were interrupted or cancelled, then just exit.
|
||||
if _, ok := state.GetOk(multistep.StateCancelled); ok {
|
||||
return nil, errors.New("Build was cancelled.")
|
||||
}
|
||||
|
||||
if _, ok := state.GetOk(multistep.StateHalted); ok {
|
||||
return nil, errors.New("Build was halted.")
|
||||
if err := common.CheckRunStatus(state); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
artifact := &common.Artifact{
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
package clone
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
builderT "github.com/hashicorp/packer/helper/builder/testing"
|
||||
commonT "github.com/jetbrains-infra/packer-builder-vsphere/common/testing"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/common"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/common"
|
||||
)
|
||||
|
||||
func TestBuilderAcc_default(t *testing.T) {
|
||||
config := defaultConfig()
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
Builder: &Builder{},
|
||||
Template: renderConfig(config),
|
||||
Template: commonT.RenderConfig(config),
|
||||
Check: checkDefault(t, config["vm_name"].(string), config["host"].(string), "datastore1"),
|
||||
})
|
||||
}
|
||||
|
@ -33,7 +32,7 @@ func defaultConfig() map[string]interface{} {
|
|||
"ssh_username": "root",
|
||||
"ssh_password": "jetbrains",
|
||||
}
|
||||
config["vm_name"] = fmt.Sprintf("test-%v", rand.Intn(1000))
|
||||
config["vm_name"] = commonT.NewVMName()
|
||||
return config
|
||||
}
|
||||
|
||||
|
@ -100,7 +99,7 @@ func TestBuilderAcc_artifact(t *testing.T) {
|
|||
config := defaultConfig()
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
Builder: &Builder{},
|
||||
Template: renderConfig(config),
|
||||
Template: commonT.RenderConfig(config),
|
||||
Check: checkArtifact(t),
|
||||
})
|
||||
}
|
||||
|
@ -133,7 +132,7 @@ func folderConfig() string {
|
|||
config := defaultConfig()
|
||||
config["folder"] = "folder1/folder2"
|
||||
config["linked_clone"] = true // speed up
|
||||
return renderConfig(config)
|
||||
return commonT.RenderConfig(config)
|
||||
}
|
||||
|
||||
func checkFolder(t *testing.T, folder string) builderT.TestCheckFunc {
|
||||
|
@ -171,7 +170,7 @@ func resourcePoolConfig() string {
|
|||
config := defaultConfig()
|
||||
config["resource_pool"] = "pool1/pool2"
|
||||
config["linked_clone"] = true // speed up
|
||||
return renderConfig(config)
|
||||
return commonT.RenderConfig(config)
|
||||
}
|
||||
|
||||
func checkResourcePool(t *testing.T, pool string) builderT.TestCheckFunc {
|
||||
|
@ -208,7 +207,7 @@ func TestBuilderAcc_datastore(t *testing.T) {
|
|||
func datastoreConfig() string {
|
||||
config := defaultConfig()
|
||||
config["template"] = "alpine-host4" // on esxi-4.vsphere65.test
|
||||
return renderConfig(config)
|
||||
return commonT.RenderConfig(config)
|
||||
}
|
||||
|
||||
func checkDatastore(t *testing.T, name string) builderT.TestCheckFunc {
|
||||
|
@ -251,7 +250,7 @@ func TestBuilderAcc_multipleDatastores(t *testing.T) {
|
|||
func multipleDatastoresConfig() string {
|
||||
config := defaultConfig()
|
||||
config["host"] = "esxi-4.vsphere65.test" // host with 2 datastores
|
||||
return renderConfig(config)
|
||||
return commonT.RenderConfig(config)
|
||||
}
|
||||
|
||||
func TestBuilderAcc_linkedClone(t *testing.T) {
|
||||
|
@ -265,7 +264,7 @@ func TestBuilderAcc_linkedClone(t *testing.T) {
|
|||
func linkedCloneConfig() string {
|
||||
config := defaultConfig()
|
||||
config["linked_clone"] = true
|
||||
return renderConfig(config)
|
||||
return commonT.RenderConfig(config)
|
||||
}
|
||||
|
||||
func checkLinkedClone(t *testing.T) builderT.TestCheckFunc {
|
||||
|
@ -303,7 +302,7 @@ func hardwareConfig() string {
|
|||
config["RAM_reservation"] = 1024
|
||||
config["linked_clone"] = true // speed up
|
||||
|
||||
return renderConfig(config)
|
||||
return commonT.RenderConfig(config)
|
||||
}
|
||||
|
||||
func checkHardware(t *testing.T) builderT.TestCheckFunc {
|
||||
|
@ -358,7 +357,7 @@ func RAMReservationConfig() string {
|
|||
config["RAM_reserve_all"] = true
|
||||
config["linked_clone"] = true // speed up
|
||||
|
||||
return renderConfig(config)
|
||||
return commonT.RenderConfig(config)
|
||||
}
|
||||
|
||||
func checkRAMReservation(t *testing.T) builderT.TestCheckFunc {
|
||||
|
@ -391,7 +390,7 @@ func sshKeyConfig() string {
|
|||
config["ssh_password"] = ""
|
||||
config["ssh_private_key_file"] = "../test-key.pem"
|
||||
config["linked_clone"] = true // speed up
|
||||
return renderConfig(config)
|
||||
return commonT.RenderConfig(config)
|
||||
}
|
||||
|
||||
func TestBuilderAcc_snapshot(t *testing.T) {
|
||||
|
@ -405,7 +404,7 @@ func TestBuilderAcc_snapshot(t *testing.T) {
|
|||
func snapshotConfig() string {
|
||||
config := defaultConfig()
|
||||
config["create_snapshot"] = true
|
||||
return renderConfig(config)
|
||||
return commonT.RenderConfig(config)
|
||||
}
|
||||
|
||||
func checkSnapshot(t *testing.T) builderT.TestCheckFunc {
|
||||
|
@ -439,7 +438,7 @@ func templateConfig() string {
|
|||
config := defaultConfig()
|
||||
config["convert_to_template"] = true
|
||||
config["linked_clone"] = true // speed up
|
||||
return renderConfig(config)
|
||||
return commonT.RenderConfig(config)
|
||||
}
|
||||
|
||||
func checkTemplate(t *testing.T) builderT.TestCheckFunc {
|
||||
|
@ -460,22 +459,6 @@ func checkTemplate(t *testing.T) builderT.TestCheckFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func renderConfig(config map[string]interface{}) string {
|
||||
t := map[string][]map[string]interface{}{
|
||||
"builders": {
|
||||
map[string]interface{}{
|
||||
"type": "test",
|
||||
},
|
||||
},
|
||||
}
|
||||
for k, v := range config {
|
||||
t["builders"][0][k] = v
|
||||
}
|
||||
|
||||
j, _ := json.Marshal(t)
|
||||
return string(j)
|
||||
}
|
||||
|
||||
func testConn(t *testing.T) *driver.Driver {
|
||||
d, err := driver.NewDriver(&driver.ConnectConfig{
|
||||
VCenterServer: "vcenter.vsphere65.test",
|
||||
|
|
|
@ -3,7 +3,6 @@ package clone
|
|||
import (
|
||||
packerCommon "github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/common"
|
||||
|
@ -13,7 +12,7 @@ type Config struct {
|
|||
packerCommon.PackerConfig `mapstructure:",squash"`
|
||||
common.ConnectConfig `mapstructure:",squash"`
|
||||
CloneConfig `mapstructure:",squash"`
|
||||
HardwareConfig `mapstructure:",squash"`
|
||||
common.HardwareConfig `mapstructure:",squash"`
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
common.ShutdownConfig `mapstructure:",squash"`
|
||||
CreateSnapshot bool `mapstructure:"create_snapshot"`
|
||||
|
@ -24,14 +23,8 @@ type Config struct {
|
|||
|
||||
func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c := new(Config)
|
||||
{
|
||||
err := config.Decode(c, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: &c.ctx,
|
||||
}, raws...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := common.DecodeConfig(c, &c.ctx, raws...); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
errs := new(packer.MultiError)
|
||||
|
|
|
@ -1,42 +1,21 @@
|
|||
package clone
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"fmt"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/common"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type HardwareConfig struct {
|
||||
CPUs int32 `mapstructure:"CPUs"`
|
||||
CPUReservation int64 `mapstructure:"CPU_reservation"`
|
||||
CPULimit int64 `mapstructure:"CPU_limit"`
|
||||
RAM int64 `mapstructure:"RAM"`
|
||||
RAMReservation int64 `mapstructure:"RAM_reservation"`
|
||||
RAMReserveAll bool `mapstructure:"RAM_reserve_all"`
|
||||
DiskSize int64 `mapstructure:"disk_size"`
|
||||
NestedHV bool `mapstructure:"NestedHV"`
|
||||
}
|
||||
|
||||
func (c *HardwareConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if c.RAMReservation > 0 && c.RAMReserveAll != false {
|
||||
errs = append(errs, fmt.Errorf("'RAM_reservation' and 'RAM_reserve_all' cannot be used together"))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
type StepConfigureHardware struct {
|
||||
config *HardwareConfig
|
||||
config *common.HardwareConfig
|
||||
}
|
||||
|
||||
func (s *StepConfigureHardware) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
|
||||
if *s.config != (HardwareConfig{}) {
|
||||
if *s.config != (common.HardwareConfig{}) {
|
||||
ui.Say("Customizing hardware parameters...")
|
||||
|
||||
err := vm.Configure(&driver.HardwareConfig{
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/multistep"
|
||||
"errors"
|
||||
)
|
||||
|
||||
func CheckRunStatus(state *multistep.BasicStateBag) error {
|
||||
// If there was an error, return that
|
||||
if rawErr, ok := state.GetOk("error"); ok {
|
||||
return rawErr.(error)
|
||||
}
|
||||
|
||||
// If we were interrupted or cancelled, then just exit.
|
||||
if _, ok := state.GetOk(multistep.StateCancelled); ok {
|
||||
return errors.New("Build was cancelled.")
|
||||
}
|
||||
|
||||
if _, ok := state.GetOk(multistep.StateHalted); ok {
|
||||
return errors.New("Build was halted.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
func DecodeConfig(cfg interface{}, ctx *interpolate.Context, raws ...interface{}) error {
|
||||
err := config.Decode(cfg, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: ctx,
|
||||
}, raws...)
|
||||
return err
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||
)
|
||||
|
||||
type HardwareConfig struct {
|
||||
CPUs int32 `mapstructure:"CPUs"`
|
||||
CPUReservation int64 `mapstructure:"CPU_reservation"`
|
||||
CPULimit int64 `mapstructure:"CPU_limit"`
|
||||
RAM int64 `mapstructure:"RAM"`
|
||||
RAMReservation int64 `mapstructure:"RAM_reservation"`
|
||||
RAMReserveAll bool `mapstructure:"RAM_reserve_all"`
|
||||
DiskSize int64 `mapstructure:"disk_size"`
|
||||
NestedHV bool `mapstructure:"NestedHV"`
|
||||
}
|
||||
|
||||
func (c *HardwareConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if c.RAMReservation > 0 && c.RAMReserveAll != false {
|
||||
errs = append(errs, fmt.Errorf("'RAM_reservation' and 'RAM_reserve_all' cannot be used together"))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func (c *HardwareConfig) ToDriverHardwareConfig() driver.HardwareConfig {
|
||||
return driver.HardwareConfig{
|
||||
CPUs: c.CPUs,
|
||||
CPUReservation: c.CPUReservation,
|
||||
CPULimit: c.CPULimit,
|
||||
RAM: c.RAM,
|
||||
RAMReservation: c.RAMReservation,
|
||||
RAMReserveAll: c.RAMReserveAll,
|
||||
DiskSize: c.DiskSize,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func NewVMName() string {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
return fmt.Sprintf("test-%v", rand.Intn(1000))
|
||||
}
|
||||
|
||||
func RenderConfig(config map[string]interface{}) string {
|
||||
t := map[string][]map[string]interface{}{
|
||||
"builders": {
|
||||
map[string]interface{}{
|
||||
"type": "test",
|
||||
},
|
||||
},
|
||||
}
|
||||
for k, v := range config {
|
||||
t["builders"][0][k] = v
|
||||
}
|
||||
|
||||
j, _ := json.Marshal(t)
|
||||
return string(j)
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
packerCommon "github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/common"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type Builder struct {
|
||||
config *Config
|
||||
runner multistep.Runner
|
||||
}
|
||||
|
||||
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||
c, warnings, errs := NewConfig(raws...)
|
||||
if errs != nil {
|
||||
return warnings, errs
|
||||
}
|
||||
b.config = c
|
||||
|
||||
return warnings, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("comm", &b.config.Comm)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
steps := []multistep.Step{}
|
||||
|
||||
steps = append(steps,
|
||||
&common.StepConnect{
|
||||
Config: &b.config.ConnectConfig,
|
||||
},
|
||||
&StepCreateVM{
|
||||
config: &b.config.CreateConfig,
|
||||
},
|
||||
)
|
||||
|
||||
if b.config.CDRomConfig.ISOPath != "" {
|
||||
steps = append(steps,
|
||||
&StepAddCDRom{
|
||||
config: &b.config.CDRomConfig,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Run!
|
||||
b.runner = packerCommon.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
b.runner.Run(state)
|
||||
|
||||
if err := common.CheckRunStatus(state); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
artifact := &common.Artifact{
|
||||
Name: b.config.VMName,
|
||||
VM: state.Get("vm").(*driver.VirtualMachine),
|
||||
}
|
||||
return artifact, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Cancel() {
|
||||
if b.runner != nil {
|
||||
b.runner.Cancel()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
builderT "github.com/hashicorp/packer/helper/builder/testing"
|
||||
commonT "github.com/jetbrains-infra/packer-builder-vsphere/common/testing"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBuilderAcc_default(t *testing.T) {
|
||||
config := defaultConfig()
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
Builder: &Builder{},
|
||||
Template: commonT.RenderConfig(config),
|
||||
})
|
||||
}
|
||||
|
||||
func defaultConfig() map[string]interface{} {
|
||||
config := map[string]interface{}{
|
||||
"vcenter_server": "vcenter.vsphere65.test",
|
||||
"username": "root",
|
||||
"password": "jetbrains",
|
||||
"insecure_connection": true,
|
||||
|
||||
"host": "esxi-1.vsphere65.test",
|
||||
|
||||
"ssh_username": "root",
|
||||
"ssh_password": "jetbrains",
|
||||
|
||||
"vm_name": commonT.NewVMName(),
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
packerCommon "github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/common"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
packerCommon.PackerConfig `mapstructure:",squash"`
|
||||
common.ConnectConfig `mapstructure:",squash"`
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
common.ShutdownConfig `mapstructure:",squash"`
|
||||
CreateSnapshot bool `mapstructure:"create_snapshot"`
|
||||
ConvertToTemplate bool `mapstructure:"convert_to_template"`
|
||||
|
||||
CreateConfig `mapstructure:",squash"`
|
||||
CDRomConfig `mapstructure:",squash"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c := new(Config)
|
||||
if err := common.DecodeConfig(c, &c.ctx, raws...); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
errs := new(packer.MultiError)
|
||||
errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, c.ConnectConfig.Prepare()...)
|
||||
errs = packer.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...)
|
||||
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare()...)
|
||||
errs = packer.MultiErrorAppend(errs, c.CreateConfig.Prepare()...)
|
||||
|
||||
if len(errs.Errors) > 0 {
|
||||
return nil, nil, errs
|
||||
}
|
||||
|
||||
return c, nil, nil
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type CDRomConfig struct {
|
||||
ISOPath string `mapstructure:"iso_path"`
|
||||
}
|
||||
|
||||
func (c *CDRomConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
type StepAddCDRom struct {
|
||||
config *CDRomConfig
|
||||
}
|
||||
|
||||
func (s *StepAddCDRom) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Adding CDRom ...")
|
||||
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
err := vm.AddCdrom(s.config.ISOPath)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepAddCDRom) Cleanup(state multistep.StateBag) {
|
||||
// nothing
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/common"
|
||||
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type CreateConfig struct {
|
||||
common.HardwareConfig `mapstructure:",squash"`
|
||||
|
||||
DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"`
|
||||
DiskControllerType string `mapstructure:"disk_controller_type"`
|
||||
|
||||
VMName string `mapstructure:"vm_name"`
|
||||
Folder string `mapstructure:"folder"`
|
||||
Host string `mapstructure:"host"`
|
||||
ResourcePool string `mapstructure:"resource_pool"`
|
||||
Datastore string `mapstructure:"datastore"`
|
||||
GuestOSType string `mapstructure:"guest_os_type"`
|
||||
}
|
||||
|
||||
func (c *CreateConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
// needed to avoid changing the original config in case of errors
|
||||
tmp := *c
|
||||
|
||||
// do recursive calls
|
||||
errs = append(errs, tmp.HardwareConfig.Prepare()...)
|
||||
|
||||
// check for errors
|
||||
if tmp.VMName == "" {
|
||||
errs = append(errs, fmt.Errorf("Target VM name is required"))
|
||||
}
|
||||
if tmp.Host == "" {
|
||||
errs = append(errs, fmt.Errorf("vSphere host is required"))
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
// set default values
|
||||
if tmp.GuestOSType == "" {
|
||||
tmp.GuestOSType = "otherGuest"
|
||||
}
|
||||
|
||||
// change the original config
|
||||
*c = tmp
|
||||
|
||||
return []error{}
|
||||
}
|
||||
|
||||
type StepCreateVM struct {
|
||||
config *CreateConfig
|
||||
}
|
||||
|
||||
func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
d := state.Get("driver").(*driver.Driver)
|
||||
|
||||
ui.Say("Creating VM...")
|
||||
|
||||
vm, err := d.CreateVM(&driver.CreateConfig{
|
||||
HardwareConfig: s.config.HardwareConfig.ToDriverHardwareConfig(),
|
||||
|
||||
DiskThinProvisioned: s.config.DiskThinProvisioned,
|
||||
DiskControllerType: s.config.DiskControllerType,
|
||||
Name: s.config.VMName,
|
||||
Folder: s.config.Folder,
|
||||
Host: s.config.Host,
|
||||
ResourcePool: s.config.ResourcePool,
|
||||
Datastore: s.config.Datastore,
|
||||
GuestOS: s.config.GuestOSType,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
state.Put("vm", vm)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepCreateVM) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
if !cancelled && !halted {
|
||||
return
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
st := state.Get("vm")
|
||||
if st == nil {
|
||||
return
|
||||
}
|
||||
vm := st.(*driver.VirtualMachine)
|
||||
|
||||
ui.Say("Destroying VM...")
|
||||
|
||||
err := vm.Destroy()
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
export PACKER_ACC=1
|
||||
go test -v "$@"
|
Loading…
Reference in New Issue