func()

in cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go [769:918]


func (p *BicepProvider) Destroy(
	ctx context.Context,
	options provisioning.DestroyOptions,
) (*provisioning.DestroyResult, error) {
	modulePath := p.modulePath()
	p.console.ShowSpinner(ctx, "Discovering resources to delete...", input.Step)
	defer p.console.StopSpinner(ctx, "", input.StepDone)
	compileResult, err := p.compileBicep(ctx, modulePath)
	if err != nil {
		return nil, fmt.Errorf("creating template: %w", err)
	}

	scope, err := p.scopeForTemplate(compileResult.Template)
	if err != nil {
		return nil, fmt.Errorf("computing deployment scope: %w", err)
	}

	completedDeployments, err := p.deploymentManager.CompletedDeployments(ctx, scope, p.env.Name(), "")
	if err != nil {
		return nil, fmt.Errorf("finding completed deployments: %w", err)
	}

	if len(completedDeployments) == 0 {
		return nil, fmt.Errorf("no deployments found for environment, '%s'", p.env.Name())
	}

	mostRecentDeployment := completedDeployments[0]
	deploymentToDelete := scope.Deployment(mostRecentDeployment.Name)

	resourcesToDelete, err := deploymentToDelete.Resources(ctx)
	if err != nil {
		return nil, fmt.Errorf("getting resources to delete: %w", err)
	}

	groupedResources, err := azapi.GroupByResourceGroup(resourcesToDelete)
	if err != nil {
		return nil, fmt.Errorf("mapping resources to resource groups: %w", err)
	}

	if len(groupedResources) == 0 {
		return nil, fmt.Errorf("%w, '%s'", infra.ErrDeploymentResourcesNotFound, deploymentToDelete.Name())
	}

	keyVaults, err := p.getKeyVaultsToPurge(ctx, groupedResources)
	if err != nil {
		return nil, fmt.Errorf("getting key vaults to purge: %w", err)
	}

	managedHSMs, err := p.getManagedHSMsToPurge(ctx, groupedResources)
	if err != nil {
		return nil, fmt.Errorf("getting managed hsms to purge: %w", err)
	}

	appConfigs, err := p.getAppConfigsToPurge(ctx, groupedResources)
	if err != nil {
		return nil, fmt.Errorf("getting app configurations to purge: %w", err)
	}

	apiManagements, err := p.getApiManagementsToPurge(ctx, groupedResources)
	if err != nil {
		return nil, fmt.Errorf("getting API managements to purge: %w", err)
	}

	cognitiveAccounts, err := p.getCognitiveAccountsToPurge(ctx, groupedResources)
	if err != nil {
		return nil, fmt.Errorf("getting cognitive accounts to purge: %w", err)
	}

	p.console.StopSpinner(ctx, "", input.StepDone)
	if err := p.destroyDeploymentWithConfirmation(
		ctx,
		options,
		deploymentToDelete,
		groupedResources,
		len(resourcesToDelete),
	); err != nil {
		return nil, fmt.Errorf("deleting resource groups: %w", err)
	}

	keyVaultsPurge := itemToPurge{
		resourceType: "Key Vault",
		count:        len(keyVaults),
		purge: func(skipPurge bool, self *itemToPurge) error {
			return p.purgeKeyVaults(ctx, keyVaults, skipPurge)
		},
	}
	managedHSMsPurge := itemToPurge{
		resourceType: "Managed HSM",
		count:        len(managedHSMs),
		purge: func(skipPurge bool, self *itemToPurge) error {
			return p.purgeManagedHSMs(ctx, managedHSMs, skipPurge)
		},
	}
	appConfigsPurge := itemToPurge{
		resourceType: "App Configuration",
		count:        len(appConfigs),
		purge: func(skipPurge bool, self *itemToPurge) error {
			return p.purgeAppConfigs(ctx, appConfigs, skipPurge)
		},
	}
	aPIManagement := itemToPurge{
		resourceType: "API Management",
		count:        len(apiManagements),
		purge: func(skipPurge bool, self *itemToPurge) error {
			return p.purgeAPIManagement(ctx, apiManagements, skipPurge)
		},
	}

	var purgeItem []itemToPurge
	for _, item := range []itemToPurge{keyVaultsPurge, managedHSMsPurge, appConfigsPurge, aPIManagement} {
		if item.count > 0 {
			purgeItem = append(purgeItem, item)
		}
	}

	// cognitive services are grouped by resource group because the name of the resource group is required to purge
	groupByKind := cognitiveAccountsByKind(cognitiveAccounts)
	for name, cogAccounts := range groupByKind {
		addPurgeItem := itemToPurge{
			resourceType: name,
			count:        len(cogAccounts),
			purge: func(skipPurge bool, self *itemToPurge) error {
				return p.purgeCognitiveAccounts(ctx, self.cognitiveAccounts, skipPurge)
			},
			cognitiveAccounts: groupByKind[name],
		}
		purgeItem = append(purgeItem, addPurgeItem)
	}

	if err := p.purgeItems(ctx, purgeItem, options); err != nil {
		return nil, fmt.Errorf("purging resources: %w", err)
	}

	destroyResult := &provisioning.DestroyResult{
		InvalidatedEnvKeys: slices.Collect(maps.Keys(p.createOutputParameters(
			compileResult.Template.Outputs,
			azapi.CreateDeploymentOutput(mostRecentDeployment.Outputs),
		))),
	}

	// Since we have deleted the resource group, add AZURE_RESOURCE_GROUP to the list of invalidated env vars
	// so it will be removed from the .env file.
	if _, ok := scope.(*infra.ResourceGroupScope); ok {
		destroyResult.InvalidatedEnvKeys = append(
			destroyResult.InvalidatedEnvKeys, environment.ResourceGroupEnvVarName,
		)
	}

	return destroyResult, nil
}