Skip to content

Commit 8306867

Browse files
authored
Merge pull request #340 from gomorpheus/mvm-datastore-null-fix
2 parents 2a5c028 + fbff45d commit 8306867

File tree

2 files changed

+85
-10
lines changed

2 files changed

+85
-10
lines changed

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
module github.com/gomorpheus/terraform-provider-morpheus
22

3-
go 1.22.7
4-
toolchain go1.24.1
3+
go 1.23.0
4+
5+
toolchain go1.24.2
56

67
require (
7-
github.com/davecgh/go-spew v1.1.1
88
github.com/gomorpheus/morpheus-go-sdk v0.5.3
99
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
1010
github.com/hashicorp/terraform-plugin-docs v0.21.0

morpheus/resource_mvm_instance.go

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"fmt"
77
"log"
8+
"strconv"
89
"time"
910

1011
"github.com/gomorpheus/morpheus-go-sdk"
@@ -360,11 +361,16 @@ func resourceMVMInstanceCreate(ctx context.Context, d *schema.ResourceData, meta
360361
var itemResponsePayload ResourcePoolOptions
361362
json.Unmarshal(resourcePoolResp.Body, &itemResponsePayload)
362363
var resourcePoolId int
364+
resourcePoolFound := false
363365
for _, v := range itemResponsePayload.Data {
364366
if v.ProviderType == "mvm" && v.Name == d.Get("resource_pool_name").(string) {
365367
resourcePoolId = v.Id
368+
resourcePoolFound = true
366369
}
367370
}
371+
if !resourcePoolFound {
372+
return diag.Errorf("resource pool with name %s not found with providerType mvm", d.Get("resource_pool_name").(string))
373+
}
368374

369375
config["resourcePoolId"] = resourcePoolId
370376
config["poolProviderType"] = "mvm"
@@ -590,16 +596,33 @@ func resourceMVMInstanceRead(ctx context.Context, d *schema.ResourceData, meta i
590596
d.Set("labels", instance.Labels)
591597

592598
var evars []map[string]interface{}
599+
evarMap := make(map[string]string, len(instance.EnvironmentVariables))
593600
for i := 0; i < len(instance.EnvironmentVariables); i++ {
594601
evar := instance.EnvironmentVariables[i]
595602
row := make(map[string]interface{})
596603
row["name"] = evar.Name
597-
row["value"] = fmt.Sprintf("%v", evar.Value)
604+
value := fmt.Sprintf("%v", evar.Value)
605+
row["value"] = value
598606
row["export"] = evar.Export
599607
row["masked"] = evar.Masked
608+
evarMap[evar.Name] = value
600609
evars = append(evars, row)
601610
}
602-
d.Set("evar", evars)
611+
612+
// If the evar field is set, we need to check if the evars match
613+
if d.Get("evar") != nil {
614+
for _, row := range d.Get("evar").([]interface{}) {
615+
evarData := row.(map[string]interface{})
616+
evarName := evarData["name"].(string)
617+
value := evarData["value"].(string)
618+
619+
if mapValue, exists := evarMap[evarName]; exists {
620+
if mapValue != value {
621+
return diag.Errorf("evar %s is missing from returned evar map", evarName)
622+
}
623+
}
624+
}
625+
}
603626

604627
// Tags
605628
tags := make(map[string]interface{})
@@ -632,19 +655,59 @@ func resourceMVMInstanceRead(ctx context.Context, d *schema.ResourceData, meta i
632655
d.Set("primary_ip_address", instance.ConnectionInfo[0].Ip)
633656

634657
var volumes []map[string]interface{}
635-
// iterate over the array of svcports
658+
// iterate over the array of volumes
636659
for i := 0; i < len(instance.Volumes); i++ {
637660
row := make(map[string]interface{})
638661
volume := instance.Volumes[i]
639662
row["uuid"] = volume.Uuid
640663
row["root"] = volume.RootVolume.(bool)
641664
row["name"] = volume.Name
642-
row["size"] = volume.Size.(float64)
643-
row["storage_type"] = volume.StorageType.(float64)
644-
row["datastore_id"] = volume.DatastoreId.(int)
665+
if volume.Size != nil {
666+
row["size"] = volume.Size.(float64)
667+
}
668+
if volume.StorageType != nil {
669+
row["storage_type"] = volume.StorageType.(float64)
670+
}
671+
if volume.DatastoreId != nil {
672+
datastoreId, errConv := convertToInt(volume.DatastoreId)
673+
if errConv != nil {
674+
log.Printf("Error converting datastore ID to int: %s", errConv)
675+
676+
return diag.FromErr(errConv)
677+
}
678+
679+
row["datastore_id"] = datastoreId
680+
}
645681
volumes = append(volumes, row)
646682
}
647-
d.Set("storage_volume", volumes)
683+
684+
// If the storage_volume field is set, we need to check if the volumes match
685+
// And it there is a match, we need to set the uuid in the state
686+
var volumesForState []map[string]interface{}
687+
if d.Get("storage_volume") != nil {
688+
for _, row := range d.Get("storage_volume").([]interface{}) {
689+
volumeData := row.(map[string]interface{})
690+
volumeName := volumeData["name"]
691+
datastoreId := volumeData["datastore_id"]
692+
693+
found := false
694+
for _, v := range volumes {
695+
if v["name"] == volumeName && v["datastore_id"] == datastoreId {
696+
found = true
697+
volumeData["uuid"] = v["uuid"]
698+
volumesForState = append(volumesForState, volumeData)
699+
700+
break
701+
}
702+
}
703+
if !found {
704+
return diag.Errorf("storage_volume %s is missing from returned storage volume map", volumeName)
705+
}
706+
}
707+
}
708+
if len(volumesForState) > 0 {
709+
d.Set("storage_volume", volumesForState)
710+
}
648711

649712
var networkInterfaces []map[string]interface{}
650713
// iterate over the array of svcports
@@ -662,6 +725,18 @@ func resourceMVMInstanceRead(ctx context.Context, d *schema.ResourceData, meta i
662725
return diags
663726
}
664727

728+
// convertToInt converts a value to an int, supporting both int and string types.
729+
func convertToInt(value interface{}) (int, error) {
730+
switch v := value.(type) {
731+
case int:
732+
return v, nil
733+
case string:
734+
return strconv.Atoi(v)
735+
default:
736+
return 0, fmt.Errorf("unsupported type %T for conversion to int", value)
737+
}
738+
}
739+
665740
func resourceMVMInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
666741
client := meta.(*morpheus.Client)
667742
id := d.Id()

0 commit comments

Comments
 (0)