Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
powertim authored and Timothee Christin committed Nov 15, 2023
2 parents 0a82910 + 2447b6e commit d51f175
Show file tree
Hide file tree
Showing 18 changed files with 536 additions and 106 deletions.
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ updates:
interval: "daily"
allow:
- dependency-name: "github.com/hashicorp/packer-plugin-sdk"

- dependency-name: "github.com/vmware/govmomi"
3 changes: 3 additions & 0 deletions builder/vsphere/clone/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
&common.StepConfigureHardware{
Config: &b.config.HardwareConfig,
},
&common.StepAddFlag{
FlagConfig: b.config.FlagConfig,
},
&common.StepAddCDRom{
Config: &b.config.CDRomConfig,
},
Expand Down
20 changes: 10 additions & 10 deletions builder/vsphere/clone/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ type Config struct {
common.LocationConfig `mapstructure:",squash"`
common.HardwareConfig `mapstructure:",squash"`
common.ConfigParamsConfig `mapstructure:",squash"`

common.CDRomConfig `mapstructure:",squash"`
common.RemoveCDRomConfig `mapstructure:",squash"`
common.FloppyConfig `mapstructure:",squash"`
common.RunConfig `mapstructure:",squash"`
common.BootConfig `mapstructure:",squash"`
common.WaitIpConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
common.ShutdownConfig `mapstructure:",squash"`
common.FlagConfig `mapstructure:",squash"`
common.CDRomConfig `mapstructure:",squash"`
common.RemoveCDRomConfig `mapstructure:",squash"`
common.FloppyConfig `mapstructure:",squash"`
common.RunConfig `mapstructure:",squash"`
common.BootConfig `mapstructure:",squash"`
common.WaitIpConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
common.ShutdownConfig `mapstructure:",squash"`

// Create a snapshot when set to `true`, so the VM can be used as a base
// for linked clones. Defaults to `false`.
Expand Down Expand Up @@ -79,8 +79,8 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
errs = packersdk.MultiErrorAppend(errs, c.CloneConfig.Prepare()...)
errs = packersdk.MultiErrorAppend(errs, c.LocationConfig.Prepare()...)
errs = packersdk.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...)
errs = packersdk.MultiErrorAppend(errs, c.FlagConfig.Prepare(&c.HardwareConfig)...)
errs = packersdk.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...)

errs = packersdk.MultiErrorAppend(errs, c.CDRomConfig.Prepare()...)
errs = packersdk.MultiErrorAppend(errs, c.CDConfig.Prepare(&c.ctx)...)
errs = packersdk.MultiErrorAppend(errs, c.BootConfig.Prepare(&c.ctx)...)
Expand Down
4 changes: 4 additions & 0 deletions builder/vsphere/clone/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 90 additions & 0 deletions builder/vsphere/common/step_add_flag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

//go:generate packer-sdc struct-markdown
//go:generate packer-sdc mapstructure-to-hcl2 -type FlagConfig

package common

import (
"context"
"fmt"

"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
"github.com/vmware/govmomi/vim25/types"
)

type FlagConfig struct {
// Enable Virtualization Based Security option for virtual machine. Defaults to `false`.
// Requires `vvtd_enabled` and `NestedHV` to be set to `true`.
// Requires `vTPM` to be set to `true`.
// Requires `firmware` to be set to `efi-secure`.
VbsEnabled bool `mapstructure:"vbs_enabled"`
// Enable IO/MMU option for virtual machine. Defaults to `false`.
VvtdEnabled bool `mapstructure:"vvtd_enabled"`
}

func (c *FlagConfig) Prepare(h *HardwareConfig) []error {
var errs []error

if h == nil {
return append(errs, fmt.Errorf("no hardware config provided"))
}

if c.VbsEnabled {
if !c.VvtdEnabled {
errs = append(errs, fmt.Errorf("`vvtd_enabled` must be set to `true` when `vbs_enabled` is set to `true`"))
}

if !h.NestedHV {
errs = append(errs, fmt.Errorf("`nestedhv` must be set to `true` when `vbs_enabled` is set to `true`"))
}

if !h.VTPMEnabled {
errs = append(errs, fmt.Errorf("`vtpm` must be set to `true` when `vbs_enabled` is set to `true`"))
}

if h.Firmware != "efi-secure" {
errs = append(errs, fmt.Errorf("`firmware` must be set to `efi-secure` when `vbs_enabled` is set to `true`"))
}
}

return errs
}

type StepAddFlag struct {
FlagConfig FlagConfig
}

func (s *StepAddFlag) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packersdk.Ui)
vm := state.Get("vm").(driver.VirtualMachine)

var info *types.VirtualMachineFlagInfo

if s.FlagConfig.VbsEnabled || s.FlagConfig.VvtdEnabled {
info = &types.VirtualMachineFlagInfo{}

if s.FlagConfig.VbsEnabled {
info.VbsEnabled = &s.FlagConfig.VbsEnabled
}

if s.FlagConfig.VvtdEnabled {
info.VvtdEnabled = &s.FlagConfig.VvtdEnabled
}

ui.Say("Adding virtual machine flags...")
if err := vm.AddFlag(ctx, info); err != nil {
state.Put("error", fmt.Errorf("error adding virtual machine flag: %v", err))
return multistep.ActionHalt
}
}

return multistep.ActionContinue
}

func (s *StepAddFlag) Cleanup(state multistep.StateBag) {
// Nothing to clean up.
}
33 changes: 33 additions & 0 deletions builder/vsphere/common/step_add_flag.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

196 changes: 196 additions & 0 deletions builder/vsphere/common/step_add_flag_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package common

import (
"context"
"fmt"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/hashicorp/packer-plugin-sdk/multistep"
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
)

func TestFlagConfig_Prepare(t *testing.T) {
tc := []struct {
name string
config *FlagConfig
hardwareConfig *HardwareConfig
fail bool
expectedErrMsg string
}{
{
name: "Should not fail for empty config",
config: new(FlagConfig),
hardwareConfig: new(HardwareConfig),
fail: false,
expectedErrMsg: "",
},
{
name: "VbsEnabled but VvtdEnabled not set",
config: &FlagConfig{
VbsEnabled: true,
},
hardwareConfig: &HardwareConfig{
Firmware: "efi-secure",
NestedHV: true,
VTPMEnabled: true,
},
fail: true,
expectedErrMsg: "`vvtd_enabled` must be set to `true` when `vbs_enabled` is set to `true`",
},
{
name: "VbsEnabled but NestedHV not set",
config: &FlagConfig{
VbsEnabled: true,
VvtdEnabled: true,
},
hardwareConfig: &HardwareConfig{
Firmware: "efi-secure",
VTPMEnabled: true,
},
fail: true,
expectedErrMsg: "`nestedhv` must be set to `true` when `vbs_enabled` is set to `true`",
},
{
name: "VbsEnabled but VTPMEnabled not set",
config: &FlagConfig{
VbsEnabled: true,
VvtdEnabled: true,
},
hardwareConfig: &HardwareConfig{
NestedHV: true,
Firmware: "efi-secure",
},
fail: true,
expectedErrMsg: "`vtpm` must be set to `true` when `vbs_enabled` is set to `true`",
},
{
name: "VbsEnabled but Firmware not set to efi-secure",
config: &FlagConfig{
VbsEnabled: true,
VvtdEnabled: true,
},
hardwareConfig: &HardwareConfig{
NestedHV: true,
VTPMEnabled: true,
Firmware: "efi",
},
fail: true,
expectedErrMsg: "`firmware` must be set to `efi-secure` when `vbs_enabled` is set to `true`",
},
{
name: "VbsEnabled and all required fields set",
config: &FlagConfig{
VbsEnabled: true,
VvtdEnabled: true,
},
hardwareConfig: &HardwareConfig{
NestedHV: true,
VTPMEnabled: true,
Firmware: "efi-secure",
},
fail: false,
expectedErrMsg: "",
},
}

for _, c := range tc {
errs := c.config.Prepare(c.hardwareConfig)
if c.fail {
if len(errs) == 0 {
t.Fatalf("Config prepare 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 prepare should not fail")
}
}
}
}

func TestStepAddFlag_Run(t *testing.T) {
tc := []struct {
name string
state *multistep.BasicStateBag
step *StepAddFlag
vmMock *driver.VirtualMachineMock
expectedAction multistep.StepAction
expectedVmMock *driver.VirtualMachineMock
fail bool
errMessage string
}{
{
name: "Add Flag",
state: basicStateBag(nil),
step: &StepAddFlag{
FlagConfig: FlagConfig{
VbsEnabled: true,
VvtdEnabled: true,
},
},
vmMock: new(driver.VirtualMachineMock),
expectedAction: multistep.ActionContinue,
expectedVmMock: &driver.VirtualMachineMock{
AddFlagCalled: true,
AddFlagCalledTimes: 1,
AddFlagVbsEnabledValues: true,
AddFlagVvtdEnabledValues: true,
},
fail: false,
errMessage: "",
},
{
name: "Fail to add flag",
state: basicStateBag(nil),
step: &StepAddFlag{
FlagConfig: FlagConfig{
VbsEnabled: true,
VvtdEnabled: false,
},
},
vmMock: &driver.VirtualMachineMock{
AddFlagErr: fmt.Errorf("AddFlag error"),
},
expectedAction: multistep.ActionHalt,
expectedVmMock: &driver.VirtualMachineMock{
AddFlagCalled: true,
AddFlagCalledTimes: 1,
AddFlagVbsEnabledValues: true,
AddFlagVvtdEnabledValues: false,
},
fail: true,
errMessage: fmt.Sprintf("error adding virtual machine flag: %v", fmt.Errorf("AddFlag error")),
},
}

for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
c.state.Put("vm", c.vmMock)
if action := c.step.Run(context.TODO(), c.state); action != c.expectedAction {
t.Fatalf("unexpected action %v", action)
}
err, ok := c.state.Get("error").(error)
if ok {
if err.Error() != c.errMessage {
t.Fatalf("unexpected error %s", err.Error())
}
} else {
if c.fail {
t.Fatalf("expected to fail but it didn't")
}
}

if diff := cmp.Diff(c.vmMock, c.expectedVmMock,
cmpopts.IgnoreInterfaces(struct{ error }{})); diff != "" {
t.Fatalf("unexpected VirtualMachine calls: %s", diff)
}
})
}
}
2 changes: 1 addition & 1 deletion builder/vsphere/driver/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func (d *VCenterDriver) UpdateContentLibraryItem(item *library.Item, name string
item.Patch(&library.Item{
ID: item.ID,
Name: name,
Description: description,
Description: &description,
})
return lm.UpdateLibraryItem(d.ctx, item)
}
Expand Down
Loading

0 comments on commit d51f175

Please sign in to comment.