Skip to content

Commit

Permalink
fix: r/vsphere_compute_cluster_vm_group add vm to exist group
Browse files Browse the repository at this point in the history
I have added code to allow for existing groups to be updated with new vm's, this new code needs cluster import to be ran first on vm group.

#1878

Signed-off-by: Jared Burns <[email protected]>
  • Loading branch information
burnsjared0415 committed Sep 16, 2024
1 parent 46c4ce8 commit 9ceaafe
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 2 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# <!-- markdownlint-disable first-line-h1 no-inline-html -->

## 2.9.2 (not Released)

BUG FIX:

* `resource/vsphere_compute_cluster_vm_group.go`: Add new code to handle updating existing VM groups. This will need put ran in conjunction with Import.
([#2260]https://github.com/hashicorp/terraform-provider-vsphere/pull/2260)


## 2.9.1 (September 9, 2024)

BUG FIX:
Expand Down
119 changes: 117 additions & 2 deletions vsphere/resource_vsphere_compute_cluster_vm_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package vsphere

import (
"context"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -63,6 +64,17 @@ func resourceVSphereComputeClusterVMGroupCreate(d *schema.ResourceData, meta int
return err
}

// Check if the VM group already exists
exists, err := resourceVSphereComputeClusterVMGroupFindEntry(cluster, name)
if err != nil {
return err
}

if exists != nil {
log.Printf("[DEBUG] %s: VM group already exists, calling update", exists.Name)
return resourceVSphereComputeClusterVMGroupUpdate(d, meta)
}

info, err := expandClusterVMGroup(d, meta, name)
if err != nil {
return err
Expand Down Expand Up @@ -140,17 +152,82 @@ func resourceVSphereComputeClusterVMGroupUpdate(d *schema.ResourceData, meta int
return err
}

info, err := expandClusterVMGroup(d, meta, name)
// Retrieve the existing VM group information
existingGroup, err := getCurrentVMsInGroup(cluster, name)
if err != nil {
return err
}

// Check if existingGroup is nil
if existingGroup == nil {
return fmt.Errorf("VM group %s not found", name)
}

// Expand the new VM group information
newInfo, err := expandClusterVMGroup(d, meta, name)
if err != nil {
return err
}

// Convert existing and new VMs to string slices for diffVMs
existingVMs := make([]string, len(existingGroup.Vm))
for i, vm := range existingGroup.Vm {
existingVMs[i] = vm.Value
}

newVMs := make([]string, len(newInfo.Vm))
for i, vm := range newInfo.Vm {
newVMs[i] = vm.Value
}

// Use diffVMs to find added and removed VMs
addedVMs, removedVMs := diffVMs(existingVMs, newVMs)

// Log the added and removed VMs
log.Printf("[DEBUG] Added VMs: %v", addedVMs)
log.Printf("[DEBUG] Removed VMs: %v", removedVMs)

// Convert addedVMs and removedVMs back to ManagedObjectReference slices
addedVMRefs := make([]types.ManagedObjectReference, len(addedVMs))
for i, vm := range addedVMs {
addedVMRefs[i] = types.ManagedObjectReference{
Type: "VirtualMachine",
Value: vm,
}
}

removedVMRefs := make([]types.ManagedObjectReference, len(removedVMs))
for i, vm := range removedVMs {
removedVMRefs[i] = types.ManagedObjectReference{
Type: "VirtualMachine",
Value: vm,
}
}

// Merge existing VMs with added VMs and remove duplicates
mergedVMs := append(existingGroup.Vm, addedVMRefs...)
vmMap := make(map[types.ManagedObjectReference]bool)
for _, vm := range mergedVMs {
vmMap[vm] = true
}
for _, vm := range removedVMRefs {
delete(vmMap, vm)
}
uniqueVMs := make([]types.ManagedObjectReference, 0, len(vmMap))
for vm := range vmMap {
uniqueVMs = append(uniqueVMs, vm)
}

// Update the VM group information with the merged list
newInfo.Vm = uniqueVMs

spec := &types.ClusterConfigSpecEx{
GroupSpec: []types.ClusterGroupSpec{
{
ArrayUpdateSpec: types.ArrayUpdateSpec{
Operation: types.ArrayUpdateOperationEdit,
},
Info: info,
Info: newInfo,
},
},
}
Expand Down Expand Up @@ -397,3 +474,41 @@ func resourceVSphereComputeClusterVMGroupClient(meta interface{}) (*govmomi.Clie
}
return client, nil
}

func diffVMs(oldVMs, newVMs []string) ([]string, []string) {
oldVMMap := make(map[string]bool)
for _, vm := range oldVMs {
oldVMMap[vm] = true
}

var addedVMs, removedVMs []string
for _, vm := range newVMs {
if !oldVMMap[vm] {
addedVMs = append(addedVMs, vm)
}
delete(oldVMMap, vm)
}

for vm := range oldVMMap {
removedVMs = append(removedVMs, vm)
}

return addedVMs, removedVMs
}

// getCurrentVMsInGroup retrieves the current VMs in the specified VM group from the vSphere cluster.
func getCurrentVMsInGroup(cluster *object.ClusterComputeResource, groupName string) (*types.ClusterVmGroup, error) {
ctx := context.TODO()
groups, err := cluster.Configuration(ctx)
if err != nil {
return nil, err
}

for _, group := range groups.Group {
if vmGroup, ok := group.(*types.ClusterVmGroup); ok && vmGroup.Name == groupName {
return vmGroup, nil
}
}

return nil, fmt.Errorf("VM group %s not found", groupName)
}

0 comments on commit 9ceaafe

Please sign in to comment.