github.phpd.cn/hashicorp/packer@v1.3.2/builder/azure/arm/step_delete_resource_group.go (about) 1 package arm 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/hashicorp/packer/builder/azure/common/constants" 8 retry "github.com/hashicorp/packer/common" 9 "github.com/hashicorp/packer/helper/multistep" 10 "github.com/hashicorp/packer/packer" 11 ) 12 13 const ( 14 maxResourcesToDelete = 50 15 ) 16 17 type StepDeleteResourceGroup struct { 18 client *AzureClient 19 delete func(ctx context.Context, state multistep.StateBag, resourceGroupName string) error 20 say func(message string) 21 error func(e error) 22 } 23 24 func NewStepDeleteResourceGroup(client *AzureClient, ui packer.Ui) *StepDeleteResourceGroup { 25 var step = &StepDeleteResourceGroup{ 26 client: client, 27 say: func(message string) { ui.Say(message) }, 28 error: func(e error) { ui.Error(e.Error()) }, 29 } 30 31 step.delete = step.deleteResourceGroup 32 return step 33 } 34 35 func (s *StepDeleteResourceGroup) deleteResourceGroup(ctx context.Context, state multistep.StateBag, resourceGroupName string) error { 36 var err error 37 if state.Get(constants.ArmIsExistingResourceGroup).(bool) { 38 s.say("\nThe resource group was not created by Packer, only deleting individual resources ...") 39 var deploymentName = state.Get(constants.ArmDeploymentName).(string) 40 err = s.deleteDeploymentResources(ctx, deploymentName, resourceGroupName) 41 if err != nil { 42 return err 43 } 44 45 if keyVaultDeploymentName, ok := state.GetOk(constants.ArmKeyVaultDeploymentName); ok { 46 err = s.deleteDeploymentResources(ctx, keyVaultDeploymentName.(string), resourceGroupName) 47 if err != nil { 48 return err 49 } 50 } 51 52 return nil 53 } else { 54 s.say("\nThe resource group was created by Packer, deleting ...") 55 f, err := s.client.GroupsClient.Delete(ctx, resourceGroupName) 56 if err == nil { 57 if state.Get(constants.ArmAsyncResourceGroupDelete).(bool) { 58 // No need to wait for the complition for delete if request is Accepted 59 s.say(fmt.Sprintf("\nResource Group is being deleted, not waiting for deletion due to config. Resource Group Name '%s'", resourceGroupName)) 60 } else { 61 f.WaitForCompletion(ctx, s.client.GroupsClient.Client) 62 } 63 64 } 65 66 if err != nil { 67 s.say(s.client.LastError.Error()) 68 } 69 return err 70 } 71 } 72 73 func (s *StepDeleteResourceGroup) deleteDeploymentResources(ctx context.Context, deploymentName, resourceGroupName string) error { 74 maxResources := int32(maxResourcesToDelete) 75 76 deploymentOperations, err := s.client.DeploymentOperationsClient.ListComplete(ctx, resourceGroupName, deploymentName, &maxResources) 77 if err != nil { 78 s.reportIfError(err, resourceGroupName) 79 return err 80 } 81 82 for deploymentOperations.NotDone() { 83 deploymentOperation := deploymentOperations.Value() 84 // Sometimes an empty operation is added to the list by Azure 85 if deploymentOperation.Properties.TargetResource == nil { 86 deploymentOperations.Next() 87 continue 88 } 89 90 resourceName := *deploymentOperation.Properties.TargetResource.ResourceName 91 resourceType := *deploymentOperation.Properties.TargetResource.ResourceType 92 93 s.say(fmt.Sprintf(" -> %s : '%s'", 94 resourceType, 95 resourceName)) 96 97 err := retry.Retry(10, 600, 10, func(attempt uint) (bool, error) { 98 err := deleteResource(ctx, s.client, 99 resourceType, 100 resourceName, 101 resourceGroupName) 102 if err != nil { 103 s.reportIfError(err, resourceName) 104 return false, nil 105 } 106 107 return true, nil 108 }) 109 110 if err = deploymentOperations.Next(); err != nil { 111 return err 112 } 113 } 114 115 return nil 116 } 117 118 func (s *StepDeleteResourceGroup) reportIfError(err error, resourceName string) { 119 if err != nil { 120 s.say(fmt.Sprintf("Error deleting resource. Please delete manually.\n\n"+ 121 "Name: %s\n"+ 122 "Error: %s", resourceName, err.Error())) 123 s.error(err) 124 } 125 } 126 127 func (s *StepDeleteResourceGroup) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { 128 s.say("Deleting resource group ...") 129 130 var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string) 131 s.say(fmt.Sprintf(" -> ResourceGroupName : '%s'", resourceGroupName)) 132 133 err := s.delete(ctx, state, resourceGroupName) 134 if err != nil { 135 state.Put(constants.Error, err) 136 s.error(err) 137 138 return multistep.ActionHalt 139 } 140 141 state.Put(constants.ArmIsResourceGroupCreated, false) 142 143 return multistep.ActionContinue 144 } 145 146 func (*StepDeleteResourceGroup) Cleanup(multistep.StateBag) { 147 }