Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed issue "Remove-FinOpsHub fails when there's only one resource" #983

Merged
merged 6 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 17 additions & 16 deletions src/powershell/Private/Get-HubIdentifier.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,34 @@

Returns the string '123456hyfpqje'.
#>
function Get-HubIdentifier
function Get-HubIdentifier
{
param
(
param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$Collection
)

$idPattern = '[a-z0-9]{13}' # Matches exactly 13 alphanumeric characters
$substrings = @()
foreach ($string in $Collection)
{
for ($startIndex = 0; $startIndex -lt $string.Length; $startIndex++)
{
for ($endIndex = 1; $endIndex -le ($string.Length - $startIndex); $endIndex++)
{

foreach ($string in $Collection) {
# Use regex to find valid 13-character matches
$match = [regex]::Matches($string, $idPattern)
if ($match.Count -gt 0) {
$substrings += $match | ForEach-Object { $_.Value }
}

# Generate all possible substrings
for ($startIndex = 0; $startIndex -lt $string.Length; $startIndex++) {
for ($endIndex = 1; $endIndex -le ($string.Length - $startIndex); $endIndex++) {
$substrings += $string.Substring($startIndex, $endIndex).ToLower()
}
}
}

$id = $substrings | Group-Object | Where-Object -FilterScript {$_.count -eq $Collection.length -and $_.Name.Length -eq 13} | Select-Object -Expand 'Name'
if ($id -notcontains '-' -and $id -notcontains '_')
{
return $id
}

return $null
# Filter out matches that have hyphens or underscores and return the first valid match
$validMatches = $substrings | Group-Object | Where-Object { $_.Count -eq $Collection.Length -and $_.Name.Length -eq 13 -and $_.Name -notmatch '[-_]' } | Select-Object -ExpandProperty Name
return $validMatches | Select-Object -First 1
}
97 changes: 52 additions & 45 deletions src/powershell/Public/Remove-FinOpsHub.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
.DESCRIPTION
The Remove-FinOpsHub command deletes a FinOps Hub instance and optionally deletes the storage account hosting cost data.

The comamnd returns a boolean value indicating whether all resources were successfully deleted.
The command returns a boolean value indicating whether all resources were successfully deleted.

.PARAMETER Name
Required when specifying Name. Name of the FinOps Hub.
Expand All @@ -25,84 +25,91 @@
.EXAMPLE
Remove-FinOpsHub -Name MyHub -ResourceGroupName MyRG -KeepStorageAccount

Deletes a FinOps Hub named MyHub and deletes all associated resource except the storagea ccount.
Deletes a FinOps Hub named MyHub and deletes all associated resources except the storage account.
#>

function Remove-FinOpsHub
{
function Remove-FinOpsHub {
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
param
(
param (
[Parameter(Mandatory = $true, ParameterSetName = 'Name')]
[ValidateNotNullOrEmpty ()]
[string]
$Name,
[ValidateNotNullOrEmpty()]
[string]$Name,

[Parameter(ParameterSetName = 'Name')]
[string]
$ResourceGroupName,
[string]$ResourceGroupName,

[Parameter(Mandatory = $true, ParameterSetName = 'Object')]
[ValidateNotNullOrEmpty ()]
[psobject]
$InputObject,
[ValidateNotNullOrEmpty()]
[psobject]$InputObject,

[Parameter(ParameterSetName = 'Name')]
[Parameter(ParameterSetName = 'Object')]
[switch]
$KeepStorageAccount,
[switch]$KeepStorageAccount,

[Parameter(ParameterSetName = 'Name')]
[Parameter(ParameterSetName = 'Object')]
[switch]
$Force
[switch]$Force
)

$context = Get-AzContext
if (-not $context)
{
if (-not $context) {
throw $script:LocalizedData.Common_ContextNotFound
}

try
{

if ($PSCmdlet.ParameterSetName -eq 'Name')
{
if (-not [string]::IsNullOrEmpty($ResourceGroupName))
{
try {
if ($PSCmdlet.ParameterSetName -eq 'Name') {
if (-not [string]::IsNullOrEmpty($ResourceGroupName)) {
$hub = Get-FinOpsHub -Name $Name -ResourceGroupName $ResourceGroupName
}
else
{
} else {
$hub = Get-FinOpsHub -Name $Name
$ResourceGroupName = $hub.Resources[0].ResourceGroupName
}
}
else
{
} else {
$hub = $InputObject
$Name = $hub.Name
$ResourceGroupName = $hub.Resources[0].ResourceGroupName
}

if (-not $hub)
{
if (-not $hub) {
throw $script:LocalizedData.Hub_Remove_NotFound -f $Name
}

Write-Verbose -Message "Found FinOps Hub: $Name in resource group $ResourceGroupName"

$uniqueId = Get-HubIdentifier -Collection $hub.Resources.Name
Write-Verbose -Message "Unique identifier: $uniqueId"

$resources = Get-AzResource -ResourceGroupName $ResourceGroupName |
Where-Object -FilterScript { $_.Name -like "*$uniqueId*" -and ((-not $KeepStorageAccount) -or $_.ResourceType -ne "Microsoft.Storage/storageAccounts") }
Write-Verbose -Message "Filtered Resources: $($resources | ForEach-Object { $_.Name })"

if ($null -eq $resources) {
Write-Warning "No resources found to delete."
return $false
}

$resources = Get-AzResource -ResourceGroupName $ResourceGroupName | Where-Object -FilterScript { $_.Name -like "*$uniqueId*" -and ((-not $KeepStorageAccount) -or $_.ResourceType -ne "Microsoft.Storage/storageAccounts") }
Write-Verbose -Message "Resources to be deleted: $($resources | ForEach-Object { $_.Name })"

if ($PSCmdlet.ShouldProcess($Name, 'DeleteFinOpsHub')) {
$success = $true
foreach ($resource in $resources) {
try {
Write-Verbose -Message "Deleting resource: $($resource.Name)"
Remove-AzResource -ResourceId $resource.ResourceId -Force:$Force -ErrorAction Stop
} catch {
Write-Error -Message "Failed to delete resource: $($resource.Name). Error: $_"
$success = $false
}
}

if ($PSCmdlet.ShouldProcess($Name, 'DeleteFinOpsHub'))
{
return ($resources | Remove-AzResource -Force:$Force).Reduce({ $args[0] -and $args[1] }, $true)
return $success
}
} catch {
Write-Error -Message "Failed to remove FinOps hub. Error: $_"
if ($_.Exception.InnerException) {
throw "Detailed Error: $($_.Exception.InnerException.Message)"
} else {
throw "Detailed Error: $($_.Exception.Message)"
}
}
catch
{
throw ($script:LocalizedData.Hub_Remove_Failed -f $_)
}
}

}
Loading