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
flanakin marked this conversation as resolved.
Show resolved Hide resolved
{
param
(
param (
flanakin marked this conversation as resolved.
Show resolved Hide resolved
[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) {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
# Use regex to find valid 13-character matches
$match = [regex]::Matches($string, $idPattern)
if ($match.Count -gt 0) {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
$substrings += $match | ForEach-Object { $_.Value }
}

# Generate all possible substrings
for ($startIndex = 0; $startIndex -lt $string.Length; $startIndex++) {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
for ($endIndex = 1; $endIndex -le ($string.Length - $startIndex); $endIndex++) {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
$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 {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
param
(
param (
flanakin marked this conversation as resolved.
Show resolved Hide resolved
[Parameter(Mandatory = $true, ParameterSetName = 'Name')]
[ValidateNotNullOrEmpty ()]
[string]
$Name,
[ValidateNotNullOrEmpty()]
[string]$Name,
flanakin marked this conversation as resolved.
Show resolved Hide resolved

[Parameter(ParameterSetName = 'Name')]
[string]
$ResourceGroupName,
[string]$ResourceGroupName,
flanakin marked this conversation as resolved.
Show resolved Hide resolved

[Parameter(Mandatory = $true, ParameterSetName = 'Object')]
[ValidateNotNullOrEmpty ()]
[psobject]
$InputObject,
[ValidateNotNullOrEmpty()]
[psobject]$InputObject,
flanakin marked this conversation as resolved.
Show resolved Hide resolved

[Parameter(ParameterSetName = 'Name')]
[Parameter(ParameterSetName = 'Object')]
[switch]
$KeepStorageAccount,
[switch]$KeepStorageAccount,
flanakin marked this conversation as resolved.
Show resolved Hide resolved

[Parameter(ParameterSetName = 'Name')]
[Parameter(ParameterSetName = 'Object')]
[switch]
$Force
[switch]$Force
flanakin marked this conversation as resolved.
Show resolved Hide resolved
)

$context = Get-AzContext
if (-not $context)
{
if (-not $context) {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
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)) {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
$hub = Get-FinOpsHub -Name $Name -ResourceGroupName $ResourceGroupName
}
else
{
} else {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
$hub = Get-FinOpsHub -Name $Name
$ResourceGroupName = $hub.Resources[0].ResourceGroupName
}
}
else
{
} else {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
$hub = $InputObject
$Name = $hub.Name
$ResourceGroupName = $hub.Resources[0].ResourceGroupName
}

if (-not $hub)
{
if (-not $hub) {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
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) {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
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')) {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
$success = $true
foreach ($resource in $resources) {
try {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
Write-Verbose -Message "Deleting resource: $($resource.Name)"
Remove-AzResource -ResourceId $resource.ResourceId -Force:$Force -ErrorAction Stop
} catch {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
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 {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
Write-Error -Message "Failed to remove FinOps hub. Error: $_"
if ($_.Exception.InnerException) {
throw "Detailed Error: $($_.Exception.InnerException.Message)"
} else {
flanakin marked this conversation as resolved.
Show resolved Hide resolved
throw "Detailed Error: $($_.Exception.Message)"
}
}
catch
{
throw ($script:LocalizedData.Hub_Remove_Failed -f $_)
}
}

}
Loading