77 "context"
88 "fmt"
99 "log"
10+ "slices"
1011 "time"
1112
1213 "github.com/google/uuid"
@@ -405,6 +406,36 @@ func resourceSubscriptionDelete(d *pluginsdk.ResourceData, meta interface{}) err
405406 if subscriptionName == "" || subscriptionId == "" {
406407 return fmt .Errorf ("one or both of Subscription Name (%q) and Subscription ID (%q) could not be determined" , subscriptionName , subscriptionId )
407408 }
409+
410+ // The below order matters: Cancel the subscription, then removing the alias.
411+ // The alias is the *main* handle of this terraform resource, we shall only delete it as the last step to avoid trailing partial state,
412+ // which otherwise can't be mitigated by a second `terraform run` (the Read() regards this resource is gone since alias is deleted).
413+
414+ // Cancel the Subscription
415+ if ! meta .(* clients.Client ).Features .Subscription .PreventCancellationOnDestroy {
416+ if slices .Contains ([]subscriptions.SubscriptionState {subscriptions .SubscriptionStateDisabled , subscriptions .SubscriptionStateWarned }, pointer .From (sub .Model .State )) {
417+ log .Printf ("[DEBUG] Subscription %s is already cancelled" , subscriptionId )
418+ } else {
419+ log .Printf ("[DEBUG] Cancelling subscription %s" , subscriptionId )
420+
421+ opts := subscriptionAlias .DefaultSubscriptionCancelOperationOptions ()
422+ // TODO: support a Provider `features` flag to enable deleting a Subscription containing Resources
423+ // This is a dangerous operation, and likely wants a similar default value as to that for Resource Groups
424+ if _ , err := aliasClient .SubscriptionCancel (ctx , subscriptionResourceId , opts ); err != nil {
425+ return fmt .Errorf ("failed to cancel Subscription: %+v" , err )
426+ }
427+
428+ deadline , _ := ctx .Deadline ()
429+ deleteDeadline := time .Until (deadline )
430+
431+ if err := waitForSubscriptionStateToSettle (ctx , client , subscriptionResourceId , "Cancelled" , deleteDeadline ); err != nil {
432+ return fmt .Errorf ("failed to cancel Subscription %q (Alias %q): %+v" , subscriptionId , id .AliasName , err )
433+ }
434+ }
435+ } else {
436+ log .Printf ("[DEBUG] Skipping subscription %s cancellation due to feature flag." , * id )
437+ }
438+
408439 // remove the alias
409440 if _ , count , err := checkExistingAliases (ctx , * aliasClient , subscriptionId ); err != nil {
410441 if count > 1 {
@@ -419,27 +450,6 @@ func resourceSubscriptionDelete(d *pluginsdk.ResourceData, meta interface{}) err
419450 }
420451 }
421452
422- // Cancel the Subscription
423- if ! meta .(* clients.Client ).Features .Subscription .PreventCancellationOnDestroy {
424- log .Printf ("[DEBUG] Cancelling subscription %s" , subscriptionId )
425-
426- opts := subscriptionAlias .DefaultSubscriptionCancelOperationOptions ()
427- // TODO: support a Provider `features` flag to enable deleting a Subscription containing Resources
428- // This is a dangerous operation, and likely wants a similar default value as to that for Resource Groups
429- if _ , err := aliasClient .SubscriptionCancel (ctx , subscriptionResourceId , opts ); err != nil {
430- return fmt .Errorf ("failed to cancel Subscription: %+v" , err )
431- }
432-
433- deadline , _ := ctx .Deadline ()
434- deleteDeadline := time .Until (deadline )
435-
436- if err := waitForSubscriptionStateToSettle (ctx , client , subscriptionResourceId , "Cancelled" , deleteDeadline ); err != nil {
437- return fmt .Errorf ("failed to cancel Subscription %q (Alias %q): %+v" , subscriptionId , id .AliasName , err )
438- }
439- } else {
440- log .Printf ("[DEBUG] Skipping subscription %s cancellation due to feature flag." , * id )
441- }
442-
443453 return nil
444454}
445455
0 commit comments