Skip to content

Commit

Permalink
feat: option to remove network adapters
Browse files Browse the repository at this point in the history
Adds the option to remove all network adapters at the end of the image build.

Ref: #6

Signed-off-by: Ryan Johnson <[email protected]>
  • Loading branch information
tenthirtyam committed Apr 27, 2024
1 parent de0c305 commit 4e3919e
Show file tree
Hide file tree
Showing 17 changed files with 262 additions and 30 deletions.
7 changes: 7 additions & 0 deletions .web-docs/components/builder/vsphere-clone/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,13 @@ The settings for guest customization include:
<!-- End of code generated from the comments of the NetworkInterface struct in builder/vsphere/clone/step_customize.go; -->


<!-- Code generated from the comments of the RemoveNetworkConfig struct in builder/vsphere/common/step_remove_network.go; DO NOT EDIT MANUALLY -->

- `remove_network_adapter` (bool) - Remove all network adapters from template. Defaults to `false`.

<!-- End of code generated from the comments of the RemoveNetworkConfig struct in builder/vsphere/common/step_remove_network.go; -->


#### Global Routing Settings

<!-- Code generated from the comments of the GlobalRoutingSettings struct in builder/vsphere/clone/step_customize.go; DO NOT EDIT MANUALLY -->
Expand Down
7 changes: 7 additions & 0 deletions .web-docs/components/builder/vsphere-iso/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,13 @@ In HCL2:
<!-- End of code generated from the comments of the NIC struct in builder/vsphere/iso/step_create.go; -->


<!-- Code generated from the comments of the RemoveNetworkConfig struct in builder/vsphere/common/step_remove_network.go; DO NOT EDIT MANUALLY -->

- `remove_network_adapter` (bool) - Remove all network adapters from template. Defaults to `false`.

<!-- End of code generated from the comments of the RemoveNetworkConfig struct in builder/vsphere/common/step_remove_network.go; -->


## Optional

<!-- Code generated from the comments of the NIC struct in builder/vsphere/iso/step_create.go; DO NOT EDIT MANUALLY -->
Expand Down
3 changes: 3 additions & 0 deletions builder/vsphere/clone/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
CreateSnapshot: b.config.CreateSnapshot,
SnapshotName: b.config.SnapshotName,
},
&common.StepRemoveNetworkAdapter{
Config: &b.config.RemoveNetworkAdapterConfig,
},
&common.StepConvertToTemplate{
ConvertToTemplate: b.config.ConvertToTemplate,
},
Expand Down
31 changes: 16 additions & 15 deletions builder/vsphere/clone/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,22 @@ type Config struct {
commonsteps.HTTPConfig `mapstructure:",squash"`
commonsteps.CDConfig `mapstructure:",squash"`

common.ConnectConfig `mapstructure:",squash"`
CloneConfig `mapstructure:",squash"`
common.LocationConfig `mapstructure:",squash"`
common.HardwareConfig `mapstructure:",squash"`
common.ConfigParamsConfig `mapstructure:",squash"`
common.FlagConfig `mapstructure:",squash"`
common.CDRomConfig `mapstructure:",squash"`
common.RemoveCDRomConfig `mapstructure:",squash"`
common.ReattachCDRomConfig `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.ConnectConfig `mapstructure:",squash"`
CloneConfig `mapstructure:",squash"`
common.LocationConfig `mapstructure:",squash"`
common.HardwareConfig `mapstructure:",squash"`
common.ConfigParamsConfig `mapstructure:",squash"`
common.FlagConfig `mapstructure:",squash"`
common.CDRomConfig `mapstructure:",squash"`
common.RemoveCDRomConfig `mapstructure:",squash"`
common.ReattachCDRomConfig `mapstructure:",squash"`
common.RemoveNetworkAdapterConfig `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"`

// Specifies to create a snapshot of the virtual machine to use as a base for linked clones.
// Defaults to `false`.
Expand Down
2 changes: 2 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.

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

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

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

type RemoveNetworkAdapterConfig struct {
// Remove all network adapters from template. Defaults to `false`.
RemoveNetworkAdapter bool `mapstructure:"remove_network_adapter"`
}

type StepRemoveNetworkAdapter struct {
Config *RemoveNetworkAdapterConfig
}

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

if s.Config.RemoveNetworkAdapter == true {
ui.Say("Removing network adapters...")
err := vm.RemoveNetworkAdapters()
if err != nil {
state.Put("error", fmt.Errorf("error removing network: %v", err))
return multistep.ActionHalt
}
}

return multistep.ActionContinue
}

func (s *StepRemoveNetworkAdapter) Cleanup(state multistep.StateBag) {
// no cleanup
}
31 changes: 31 additions & 0 deletions builder/vsphere/common/step_remove_network_adapter.hcl2spec.go

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

83 changes: 83 additions & 0 deletions builder/vsphere/common/step_remove_network_adapter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// 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 TestStepRemoveNetworkAdapter_Run(t *testing.T) {
tc := []struct {
name string
step *StepRemoveNetworkAdapter
expectedAction multistep.StepAction
vmMock *driver.VirtualMachineMock
expectedVmMock *driver.VirtualMachineMock
errMessage string
}{
{
name: "Successfully remove network adapter",
step: &StepRemoveNetworkAdapter{
Config: &RemoveNetworkAdapterConfig{
RemoveNetworkAdapter: true,
},
},
expectedAction: multistep.ActionContinue,
vmMock: &driver.VirtualMachineMock{
RemoveNetworkAdaptersCalled: true,
},
expectedVmMock: &driver.VirtualMachineMock{
RemoveNetworkAdaptersCalled: true,
},
},
{
name: "Fail to remove network adapter",
step: &StepRemoveNetworkAdapter{
Config: &RemoveNetworkAdapterConfig{
RemoveNetworkAdapter: true,
},
},
expectedAction: multistep.ActionHalt,
vmMock: &driver.VirtualMachineMock{
RemoveNetworkAdaptersCalled: true,
RemoveNetworkAdaptersErr: fmt.Errorf("failed to remove network adapter"),
},
expectedVmMock: &driver.VirtualMachineMock{
RemoveNetworkAdaptersCalled: true,
},
errMessage: "error removing network: failed to remove network adapter",
},
}

for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
state := basicStateBag(nil)
state.Put("vm", c.vmMock)

if action := c.step.Run(context.TODO(), state); action != c.expectedAction {
t.Fatalf("unexpected action %v", action)
}
err, ok := state.Get("error").(error)
if ok {
if err.Error() != c.errMessage {
t.Fatalf("unexpected error %s", err.Error())
}
} else if c.errMessage != "" {
t.Fatalf("expected to fail with %s but it didn't", c.errMessage)
}

if diff := cmp.Diff(c.vmMock, c.expectedVmMock,
cmpopts.IgnoreInterfaces(struct{ error }{})); diff != "" {
t.Fatalf("unexpected VirtualMachine calls: %s", diff)
}
})
}
}
23 changes: 23 additions & 0 deletions builder/vsphere/driver/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ type VirtualMachine interface {
EjectCdroms() error
AddSATAController() error
FindSATAController() (*types.VirtualAHCIController, error)

RemoveNetworkAdapters() error
}

type VirtualMachineDriver struct {
Expand Down Expand Up @@ -1336,3 +1338,24 @@ func findNetworkAdapter(l object.VirtualDeviceList) (types.BaseVirtualEthernetCa

return c[0].(types.BaseVirtualEthernetCard), nil
}

func (vm *VirtualMachineDriver) RemoveNetworkAdapters() error {
devices, err := vm.Devices()
if err != nil {
return fmt.Errorf("error retrieving devices: %s", err)
}

networkAdapters := devices.SelectByType((*types.VirtualEthernetCard)(nil))
if len(networkAdapters) == 0 {
return nil
}

for _, adapter := range networkAdapters {
err = vm.RemoveDevice(false, adapter)
if err != nil {
return fmt.Errorf("error removing network adapter: %s", err)
}
}

return nil
}
10 changes: 10 additions & 0 deletions builder/vsphere/driver/vm_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ type VirtualMachineMock struct {
ReattachCDRomsCalled bool
ReattachCDRomsErr error

RemoveNetworkAdaptersCalled bool
NetworkAdaptersList object.VirtualDeviceList
RemoveNetworkAdaptersErr error

CloneCalled bool
CloneConfig *CloneConfig
CloneError error
Expand Down Expand Up @@ -299,6 +303,12 @@ func (vm *VirtualMachineMock) EjectCdroms() error {
return vm.EjectCdromsErr
}

func (vm *VirtualMachineMock) RemoveNetworkAdapters() error {
vm.RemoveNetworkAdaptersCalled = true
vm.NetworkAdaptersList = nil
return vm.RemoveNetworkAdaptersErr
}

func (vm *VirtualMachineMock) Datacenter() *object.Datacenter {
return nil
}
3 changes: 3 additions & 0 deletions builder/vsphere/iso/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
Config: &b.config.ReattachCDRomConfig,
CDRomConfig: &b.config.CDRomConfig,
},
&common.StepRemoveNetworkAdapter{
Config: &b.config.RemoveNetworkAdapterConfig,
},
&common.StepCreateSnapshot{
CreateSnapshot: b.config.CreateSnapshot,
SnapshotName: b.config.SnapshotName,
Expand Down
31 changes: 16 additions & 15 deletions builder/vsphere/iso/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,22 @@ type Config struct {
commonsteps.HTTPConfig `mapstructure:",squash"`
commonsteps.CDConfig `mapstructure:",squash"`

common.ConnectConfig `mapstructure:",squash"`
CreateConfig `mapstructure:",squash"`
common.LocationConfig `mapstructure:",squash"`
common.HardwareConfig `mapstructure:",squash"`
common.ConfigParamsConfig `mapstructure:",squash"`
common.FlagConfig `mapstructure:",squash"`
commonsteps.ISOConfig `mapstructure:",squash"`
common.CDRomConfig `mapstructure:",squash"`
common.RemoveCDRomConfig `mapstructure:",squash"`
common.ReattachCDRomConfig `mapstructure:",squash"`
common.FloppyConfig `mapstructure:",squash"`
common.RunConfig `mapstructure:",squash"`
common.BootConfig `mapstructure:",squash"`
common.WaitIpConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
common.ConnectConfig `mapstructure:",squash"`
CreateConfig `mapstructure:",squash"`
common.LocationConfig `mapstructure:",squash"`
common.HardwareConfig `mapstructure:",squash"`
common.ConfigParamsConfig `mapstructure:",squash"`
common.FlagConfig `mapstructure:",squash"`
commonsteps.ISOConfig `mapstructure:",squash"`
common.CDRomConfig `mapstructure:",squash"`
common.RemoveCDRomConfig `mapstructure:",squash"`
common.ReattachCDRomConfig `mapstructure:",squash"`
common.RemoveNetworkAdapterConfig `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"`

Expand Down
2 changes: 2 additions & 0 deletions builder/vsphere/iso/config.hcl2spec.go

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- Code generated from the comments of the RemoveNetworkAdapterConfig struct in builder/vsphere/common/step_remove_network_adapter.go; DO NOT EDIT MANUALLY -->

- `remove_network_adapter` (bool) - Remove all network adapters from template. Defaults to `false`.

<!-- End of code generated from the comments of the RemoveNetworkAdapterConfig struct in builder/vsphere/common/step_remove_network_adapter.go; -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- Code generated from the comments of the RemoveNetworkConfig struct in builder/vsphere/common/step_remove_network.go; DO NOT EDIT MANUALLY -->

- `remove_network_adapter` (bool) - Remove all network adapters from template. Defaults to `false`.

<!-- End of code generated from the comments of the RemoveNetworkConfig struct in builder/vsphere/common/step_remove_network.go; -->
2 changes: 2 additions & 0 deletions docs/builders/vsphere-clone.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ can be done via environment variable:

@include 'builder/vsphere/clone/NetworkInterface-not-required.mdx'

@include 'builder/vsphere/common/RemoveNetworkConfig-not-required.mdx'

#### Global Routing Settings

@include 'builder/vsphere/clone/GlobalRoutingSettings.mdx'
Expand Down
Loading

0 comments on commit 4e3919e

Please sign in to comment.