Skip to content

Commit 5244f34

Browse files
authored
Hotfix 271124-1 (#69)
- Fixed some issues with the ensure processes where we could get nil pointers - Added a new process to delete vms that were created but the creation process failed - Added the enforce of the flag force_changes on the create where it will delete vms if the pre-exist - Fixed some issues with the getVms method where the id was not being escaped - Added a fix for the intel macs where we now add the user to the sudoers list if not present - Added a fix where if PD failed to install we would get an error with dependencies
1 parent 2e2ff7a commit 5244f34

File tree

13 files changed

+340
-137
lines changed

13 files changed

+340
-137
lines changed

internal/apiclient/get_vms.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"strconv"
7+
"strings"
78

89
"terraform-provider-parallels-desktop/internal/apiclient/apimodels"
910
"terraform-provider-parallels-desktop/internal/constants"
@@ -18,6 +19,7 @@ func GetVms(ctx context.Context, config HostConfig, filterField, filterValue str
1819
diagnostic := diag.Diagnostics{}
1920
response := make([]apimodels.VirtualMachine, 0)
2021
urlHost := helpers.GetHostUrl(config.Host)
22+
filterValue = strings.ReplaceAll(filterValue, "\"", "")
2123
var url string
2224

2325
if config.IsOrchestrator {

internal/common/ensure_machine_as_internal_ip.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"terraform-provider-parallels-desktop/internal/apiclient"
88
"terraform-provider-parallels-desktop/internal/apiclient/apimodels"
99

10+
"terraform-provider-parallels-desktop/internal/constants"
11+
1012
"github.com/hashicorp/terraform-plugin-framework/diag"
1113
"github.com/hashicorp/terraform-plugin-log/tflog"
1214
)
@@ -19,16 +21,33 @@ func EnsureMachineHasInternalIp(ctx context.Context, hostConfig apiclient.HostCo
1921
diagnostics.Append(ensureRunningDiag...)
2022
return nil, diagnostics
2123
}
24+
if refreshVm == nil {
25+
diagnostics.AddError("There was an error getting the vm", "vm is nil")
26+
return nil, diagnostics
27+
}
2228

23-
maxRetries := 10
29+
maxRetries := constants.DEFAULT_OPERATION_MAX_RETRY_COUNT
2430
retryCount := 0
2531
for {
2632
diagnostics = diag.Diagnostics{}
2733
retryCount += 1
34+
// We have run out of retries, add an error and break out of the loop
35+
if retryCount >= maxRetries {
36+
diagnostics.AddError("Error in Internal IP", "We could not get the internal IP of the machine")
37+
break
38+
}
39+
2840
if refreshVm.InternalIpAddress == "" || refreshVm.InternalIpAddress == "-" {
2941
updatedVm, checkVmDiag := apiclient.GetVm(ctx, hostConfig, refreshVm.ID)
3042
if checkVmDiag.HasError() {
3143
diagnostics.Append(checkVmDiag...)
44+
tflog.Error(ctx, "Error getting vm Internal IP")
45+
continue
46+
}
47+
if updatedVm == nil {
48+
diagnostics.AddError("Error in Internal IP", "VM not found")
49+
tflog.Error(ctx, "Error getting vm Internal IP, VM not found")
50+
continue
3251
}
3352

3453
// If we have the internal IP, break out of the loop
@@ -39,13 +58,7 @@ func EnsureMachineHasInternalIp(ctx context.Context, hostConfig apiclient.HostCo
3958
break
4059
}
4160

42-
// We have run out of retries, add an error and break out of the loop
43-
if retryCount >= maxRetries {
44-
diagnostics.AddError("error getting vm Internal IP", "We could not get the internal IP of the machine")
45-
break
46-
}
47-
48-
time.Sleep(10 * time.Second)
61+
time.Sleep(constants.DEFAULT_OPERATION_RETRY_INTERVAL_IN_SECONDS * time.Second)
4962
} else {
5063
break
5164
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package common
2+
3+
import (
4+
"context"
5+
"strings"
6+
"time"
7+
8+
"terraform-provider-parallels-desktop/internal/apiclient"
9+
"terraform-provider-parallels-desktop/internal/constants"
10+
11+
"github.com/hashicorp/terraform-plugin-framework/diag"
12+
"github.com/hashicorp/terraform-plugin-log/tflog"
13+
)
14+
15+
func EnsureMachineIsRemoved(ctx context.Context, hostConfig apiclient.HostConfig, vmIdOrName string) diag.Diagnostics {
16+
diagnostics := diag.Diagnostics{}
17+
maxRetries := constants.DEFAULT_OPERATION_MAX_RETRY_COUNT
18+
vmIdOrName = strings.ReplaceAll(vmIdOrName, "\"", "")
19+
retryCount := 0
20+
for {
21+
diagnostics = diag.Diagnostics{}
22+
retryCount += 1
23+
24+
// We have run out of retries, add an error and break out of the loop
25+
if retryCount >= maxRetries {
26+
diagnostics.AddError("Error starting vm", "Could not verify the state of the machine after starting, retry count exceeded")
27+
break
28+
}
29+
30+
currentVm, refreshDiags := apiclient.GetVm(ctx, hostConfig, vmIdOrName)
31+
if refreshDiags.HasError() {
32+
diagnostics.Append(refreshDiags...)
33+
continue
34+
}
35+
36+
// If the machine is not found, return ok as we cannot remove something that does not exist
37+
if currentVm == nil {
38+
// We are waiting for half of the time to wait for the orchestrator to update
39+
time.Sleep(constants.DEFAULT_OPERATION_RETRY_INTERVAL_IN_SECONDS * time.Second)
40+
currentVm, refreshDiags := apiclient.GetVm(ctx, hostConfig, vmIdOrName)
41+
if refreshDiags.HasError() {
42+
diagnostics.Append(refreshDiags...)
43+
continue
44+
}
45+
if currentVm == nil {
46+
diagnostics = diag.Diagnostics{}
47+
break
48+
}
49+
}
50+
51+
tflog.Info(ctx, "Checking if "+currentVm.Name+" is running")
52+
// making sure the VM is stopped before removing it
53+
if _, ensureStopped := EnsureMachineStopped(ctx, hostConfig, currentVm); ensureStopped.HasError() {
54+
diagnostics.Append(ensureStopped...)
55+
continue
56+
}
57+
58+
// Refresh the state of the machine
59+
refreshedVm, refreshedVmDiag := apiclient.GetVm(ctx, hostConfig, currentVm.ID)
60+
if refreshedVmDiag.HasError() {
61+
diagnostics.Append(refreshedVmDiag...)
62+
continue
63+
}
64+
65+
if refreshedVm == nil {
66+
// We are waiting for half of the time to wait for the orchestrator to update
67+
time.Sleep(constants.DEFAULT_OPERATION_RETRY_INTERVAL_IN_SECONDS * time.Second)
68+
refreshedVm, refreshDiags := apiclient.GetVm(ctx, hostConfig, vmIdOrName)
69+
if refreshDiags.HasError() {
70+
diagnostics.Append(refreshDiags...)
71+
continue
72+
}
73+
if refreshedVm == nil {
74+
diagnostics = diag.Diagnostics{}
75+
break
76+
}
77+
}
78+
79+
// The machine is stopped, we can remove it
80+
if refreshedVm.State == "stopped" {
81+
tflog.Info(ctx, "Machine "+currentVm.Name+" is stopped, removing it")
82+
if removeDiag := apiclient.DeleteVm(ctx, hostConfig, refreshedVm.ID); removeDiag.HasError() {
83+
diagnostics.Append(removeDiag...)
84+
continue
85+
}
86+
// The machine has been removed, break out of the loop
87+
break
88+
}
89+
90+
time.Sleep(constants.DEFAULT_OPERATION_RETRY_INTERVAL_IN_SECONDS * time.Second)
91+
}
92+
93+
return diagnostics
94+
}

internal/common/ensure_machine_running.go

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"terraform-provider-parallels-desktop/internal/apiclient"
99
"terraform-provider-parallels-desktop/internal/apiclient/apimodels"
10+
"terraform-provider-parallels-desktop/internal/constants"
1011

1112
"github.com/hashicorp/terraform-plugin-framework/diag"
1213
"github.com/hashicorp/terraform-plugin-log/tflog"
@@ -15,66 +16,79 @@ import (
1516
func EnsureMachineRunning(ctx context.Context, hostConfig apiclient.HostConfig, vm *apimodels.VirtualMachine) (*apimodels.VirtualMachine, diag.Diagnostics) {
1617
diagnostics := diag.Diagnostics{}
1718

18-
returnVm, refreshDiags := apiclient.GetVm(ctx, hostConfig, vm.ID)
19+
currentVm, refreshDiags := apiclient.GetVm(ctx, hostConfig, vm.ID)
1920
if refreshDiags.HasError() {
2021
diagnostics.Append(refreshDiags...)
2122
return vm, diagnostics
2223
}
2324

24-
maxRetries := 20
25+
if currentVm == nil {
26+
diagnostics.AddError("There was an error getting the vm", "vm is nil")
27+
return vm, diagnostics
28+
}
29+
30+
maxRetries := constants.DEFAULT_OPERATION_MAX_RETRY_COUNT
2531
retryCount := 0
2632
for {
2733
diagnostics = diag.Diagnostics{}
2834
retryCount += 1
29-
if returnVm.State != "running" {
30-
tflog.Info(ctx, "Machine "+returnVm.Name+" is not running, starting it"+fmt.Sprintf("[%v/%v]", retryCount, maxRetries))
35+
36+
// We have run out of retries, add an error and break out of the loop
37+
if retryCount >= maxRetries {
38+
diagnostics.AddError("Error starting vm", "Could not verify the state of the machine after starting, retry count exceeded")
39+
break
40+
}
41+
42+
if currentVm.State != "running" {
43+
tflog.Info(ctx, "Machine "+currentVm.Name+" is not running, starting it"+fmt.Sprintf("[%v/%v]", retryCount, maxRetries))
3144
op := apiclient.MachineStateOpStart
32-
if returnVm.State == "suspended" || returnVm.State == "paused" {
45+
if currentVm.State == "suspended" || currentVm.State == "paused" {
3346
op = apiclient.MachineStateOpResume
3447
}
35-
result, stateDiag := apiclient.SetMachineState(ctx, hostConfig, returnVm.ID, op)
48+
stateResult, stateDiag := apiclient.SetMachineState(ctx, hostConfig, currentVm.ID, op)
3649
if stateDiag.HasError() {
3750
diagnostics.Append(stateDiag...)
51+
continue
3852
}
3953

40-
if !result {
54+
if !stateResult {
4155
diagnostics.AddError("Error starting vm", "Could not set the state of the machine to running")
56+
continue
4257
}
4358

44-
tflog.Info(ctx, "Checking if "+returnVm.Name+" is running")
59+
tflog.Info(ctx, "Checking if "+currentVm.Name+" is running")
4560

46-
updatedVm, checkVmDiag := apiclient.GetVm(ctx, hostConfig, returnVm.ID)
47-
if checkVmDiag.HasError() {
48-
diagnostics.Append(checkVmDiag...)
61+
refreshedVm, refreshedVmDiag := apiclient.GetVm(ctx, hostConfig, currentVm.ID)
62+
if refreshedVmDiag.HasError() {
63+
diagnostics.Append(refreshedVmDiag...)
64+
continue
65+
}
66+
if refreshedVm == nil {
67+
diagnostics.AddError("Error starting vm", "Could not verify the state of the machine after starting, retry count exceeded")
68+
continue
4969
}
5070

5171
// The machine is running, lets check if we have the tools initialized
52-
if updatedVm.State == "running" {
72+
if refreshedVm.State == "running" {
5373
echoHelloCommand := apimodels.PostScriptItem{
5474
Command: "echo 'I am running'",
55-
VirtualMachineId: updatedVm.ID,
75+
VirtualMachineId: refreshedVm.ID,
5676
}
5777

5878
// Only breaking out of the loop if the script executes successfully
5979
if _, execDiag := apiclient.ExecuteScript(ctx, hostConfig, echoHelloCommand); !execDiag.HasError() {
60-
tflog.Info(ctx, "Machine "+returnVm.Name+" is running")
80+
tflog.Info(ctx, "Machine "+currentVm.Name+" is running")
6181
diagnostics = diag.Diagnostics{}
62-
returnVm = updatedVm
82+
currentVm = refreshedVm
6383
break
6484
}
6585
}
6686

67-
// We have run out of retries, add an error and break out of the loop
68-
if retryCount >= maxRetries {
69-
diagnostics.AddError("Error starting vm", "Could not verify the state of the machine after starting, retry count exceeded")
70-
break
71-
}
72-
73-
time.Sleep(10 * time.Second)
87+
time.Sleep(constants.DEFAULT_OPERATION_RETRY_INTERVAL_IN_SECONDS * time.Second)
7488
} else {
7589
break
7690
}
7791
}
7892

79-
return returnVm, diagnostics
93+
return currentVm, diagnostics
8094
}

internal/common/ensure_machine_stopped.go

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"terraform-provider-parallels-desktop/internal/apiclient"
99
"terraform-provider-parallels-desktop/internal/apiclient/apimodels"
10+
"terraform-provider-parallels-desktop/internal/constants"
1011

1112
"github.com/hashicorp/terraform-plugin-framework/diag"
1213
"github.com/hashicorp/terraform-plugin-log/tflog"
@@ -15,58 +16,66 @@ import (
1516
func EnsureMachineStopped(ctx context.Context, hostConfig apiclient.HostConfig, vm *apimodels.VirtualMachine) (*apimodels.VirtualMachine, diag.Diagnostics) {
1617
diagnostics := diag.Diagnostics{}
1718

18-
returnVm, refreshDiags := apiclient.GetVm(ctx, hostConfig, vm.ID)
19+
currentVm, refreshDiags := apiclient.GetVm(ctx, hostConfig, vm.ID)
1920
if refreshDiags.HasError() {
2021
diagnostics.Append(refreshDiags...)
2122
return vm, diagnostics
2223
}
24+
if currentVm == nil {
25+
diagnostics.AddError("There was an error getting the vm", "vm is nil")
26+
return vm, diagnostics
27+
}
2328

24-
maxRetries := 30
29+
maxRetries := constants.DEFAULT_OPERATION_MAX_RETRY_COUNT
2530
retryCount := 0
2631
for {
2732
diagnostics = diag.Diagnostics{}
2833
retryCount += 1
29-
if returnVm.State != "stopped" {
30-
tflog.Info(ctx, "Machine "+returnVm.Name+" is not stopped, stopping it"+fmt.Sprintf("[%v/%v]", retryCount, maxRetries))
31-
result, stateDiag := apiclient.SetMachineState(ctx, hostConfig, returnVm.ID, apiclient.MachineStateOpStop)
34+
35+
// We have run out of retries, add an error and break out of the loop
36+
if retryCount >= maxRetries {
37+
diagnostics.AddError("error stopping vm", "error stopping vm")
38+
break
39+
}
40+
41+
if currentVm.State != "stopped" {
42+
tflog.Info(ctx, "Machine "+currentVm.Name+" is not stopped, stopping it"+fmt.Sprintf("[%v/%v]", retryCount, maxRetries))
43+
result, stateDiag := apiclient.SetMachineState(ctx, hostConfig, currentVm.ID, apiclient.MachineStateOpStop)
3244
if stateDiag.HasError() {
3345
diagnostics.Append(stateDiag...)
46+
continue
3447
}
3548

3649
if !result {
37-
diagnostics.AddError("error stopping vm", "error stopping vm")
50+
diagnostics.AddError("error stopping vm", "Could not set the state of the machine to stopped")
51+
continue
3852
}
3953

40-
tflog.Info(ctx, "Checking if "+returnVm.Name+" is stopped")
54+
tflog.Info(ctx, "Checking if "+currentVm.Name+" is stopped")
4155

42-
updatedVm, checkVmDiag := apiclient.GetVm(ctx, hostConfig, returnVm.ID)
43-
if checkVmDiag.HasError() {
44-
diagnostics.Append(checkVmDiag...)
56+
refreshedVm, refreshedVmDiag := apiclient.GetVm(ctx, hostConfig, currentVm.ID)
57+
if refreshedVmDiag.HasError() {
58+
diagnostics.Append(refreshedVmDiag...)
59+
continue
4560
}
46-
if updatedVm == nil {
47-
diagnostics.AddError("error stopping vm", "VM not found")
48-
return returnVm, diagnostics
61+
if refreshedVm == nil {
62+
diagnostics.AddError("error stopping vm", "Could not verify the state of the machine after stopping, vm is nil")
63+
continue
4964
}
5065

5166
// All if good, break out of the loop
52-
if updatedVm.State == "stopped" {
53-
tflog.Info(ctx, "Machine "+returnVm.Name+" is stopped")
67+
if refreshedVm.State == "stopped" {
68+
tflog.Info(ctx, "Machine "+currentVm.Name+" is stopped")
5469
diagnostics = diag.Diagnostics{}
55-
returnVm = updatedVm
56-
break
57-
}
58-
59-
// We have run out of retries, add an error and break out of the loop
60-
if retryCount >= maxRetries {
61-
diagnostics.AddError("error stopping vm", "error stopping vm")
70+
currentVm = refreshedVm
6271
break
6372
}
6473

65-
time.Sleep(10 * time.Second)
74+
time.Sleep(constants.DEFAULT_OPERATION_RETRY_INTERVAL_IN_SECONDS * time.Second)
6675
} else {
6776
break
6877
}
6978
}
7079

71-
return returnVm, diagnostics
80+
return currentVm, diagnostics
7281
}

0 commit comments

Comments
 (0)