Skip to content

Commit

Permalink
bugfix: ordering locks to avoid deadlock (#676)
Browse files Browse the repository at this point in the history
  • Loading branch information
ms-henglu authored Nov 20, 2024
1 parent ba1f58d commit c95c788
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ FEATURES:
BUG FIXES:
- Fix a bug when `body` contains an unknown float number, the provider will crash.
- Fix the crash that occurs when no tenant ID is configured in Azure CLI.
- Fix a bug that using multiple locks can result in a deadlock.

## v2.0.1
BREAKING CHANGES:
Expand Down
14 changes: 9 additions & 5 deletions internal/services/azapi_data_plane_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"reflect"
"slices"
"time"

"github.com/Azure/terraform-provider-azapi/internal/clients"
Expand Down Expand Up @@ -419,10 +420,11 @@ func (r *DataPlaneResource) CreateUpdate(ctx context.Context, plan tfsdk.Plan, s
diagnostics.AddError("Invalid body", fmt.Sprintf(`The argument "body" is invalid: %s`, err.Error()))
return
}

for _, id := range AsStringList(model.Locks) {
locks.ByID(id)
defer locks.UnlockByID(id)
lockIds := AsStringList(model.Locks)
slices.Sort(lockIds)
for _, lockId := range lockIds {
locks.ByID(lockId)
defer locks.UnlockByID(lockId)
}

_, err = client.CreateOrUpdateThenPoll(ctx, id, body, clients.NewRequestOptions(model.CreateHeaders, model.CreateQueryParameters))
Expand Down Expand Up @@ -593,7 +595,9 @@ func (r *DataPlaneResource) Delete(ctx context.Context, request resource.DeleteR
return
}

for _, lockId := range AsStringList(model.Locks) {
lockIds := AsStringList(model.Locks)
slices.Sort(lockIds)
for _, lockId := range lockIds {
locks.ByID(lockId)
defer locks.UnlockByID(lockId)
}
Expand Down
9 changes: 7 additions & 2 deletions internal/services/azapi_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"reflect"
"slices"
"strings"
"time"

Expand Down Expand Up @@ -670,7 +671,9 @@ func (r *AzapiResource) CreateUpdate(ctx context.Context, requestPlan tfsdk.Plan
}

// create/update the resource
for _, lockId := range AsStringList(plan.Locks) {
lockIds := AsStringList(plan.Locks)
slices.Sort(lockIds)
for _, lockId := range lockIds {
locks.ByID(lockId)
defer locks.UnlockByID(lockId)
}
Expand Down Expand Up @@ -953,7 +956,9 @@ func (r *AzapiResource) Delete(ctx context.Context, request resource.DeleteReque
return
}

for _, lockId := range AsStringList(model.Locks) {
lockIds := AsStringList(model.Locks)
slices.Sort(lockIds)
for _, lockId := range lockIds {
locks.ByID(lockId)
defer locks.UnlockByID(lockId)
}
Expand Down
9 changes: 6 additions & 3 deletions internal/services/azapi_resource_action_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package services
import (
"context"
"fmt"
"slices"
"time"

"github.com/Azure/terraform-provider-azapi/internal/clients"
Expand Down Expand Up @@ -315,9 +316,11 @@ func (r *ActionResource) Action(ctx context.Context, model ActionResourceModel,
return
}

for _, id := range AsStringList(model.Locks) {
locks.ByID(id)
defer locks.UnlockByID(id)
lockIds := AsStringList(model.Locks)
slices.Sort(lockIds)
for _, lockId := range lockIds {
locks.ByID(lockId)
defer locks.UnlockByID(lockId)
}

var client clients.Requester
Expand Down
2 changes: 1 addition & 1 deletion internal/services/azapi_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1464,7 +1464,7 @@ resource "azapi_resource" "test2" {
}
}
locks = [azapi_resource.routeTable.id, azapi_resource.resourceGroup.id]
locks = [azapi_resource.resourceGroup.id, azapi_resource.routeTable.id]
}
`, r.template(data), data.RandomInteger, data.RandomString)
}
Expand Down
9 changes: 6 additions & 3 deletions internal/services/azapi_update_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"slices"
"time"

"github.com/Azure/terraform-provider-azapi/internal/clients"
Expand Down Expand Up @@ -381,9 +382,11 @@ func (r *AzapiUpdateResource) CreateUpdate(ctx context.Context, plan tfsdk.Plan,
requestBody = (*id.ResourceDef).GetWriteOnly(utils.NormalizeObject(requestBody))
}

for _, id := range AsStringList(model.Locks) {
locks.ByID(id)
defer locks.UnlockByID(id)
lockIds := AsStringList(model.Locks)
slices.Sort(lockIds)
for _, lockId := range lockIds {
locks.ByID(lockId)
defer locks.UnlockByID(lockId)
}

_, err = client.CreateOrUpdate(ctx, id.AzureResourceId, id.ApiVersion, requestBody, clients.NewRequestOptions(model.UpdateHeaders, model.UpdateQueryParameters))
Expand Down

0 comments on commit c95c788

Please sign in to comment.