Search code examples
powershellacrazure-acr

Powershell is not excluding the right values to delete the images from the azure repository


I'm having powershell script as below but it is not working as expected trying to retrieve images and delete the non running images from the acr .

I was able to pull the images but not able to delete them as per my requirement

it should exclude the tags from $tagsToExclude in $tagsToDelete

$alltags = foreach ($env in $environment) {
    # Get the list of images from k8s cluster
    $tags = az aks command invoke --resource-group test-$env --name test-$env --command "kubectl get pods --all-namespaces -o jsonpath='{.items[*].spec.containers[*].image}' | tr -s '[[:space:]]' '\n' | sort | uniq -c"
    # Skip the first line comments from PowerShell
    $deletefirstline = $tags | Select-Object -Skip 1
    # Remove the count of the images
    $removecount = $deletefirstline -replace '^\S*\s+'
    # Filter the image tags with "/i;" in the name and extract the tags
    $removecount | Where-Object { $_ -like "*/ip-*" } | ForEach-Object {
        # Extract the image name and version
        $nameVersion = $_ -split '[:/]'
        # Output the image name and version
        "$($nameVersion[2]), $($nameVersion[3])"
    }
}

$groupedData = $alltags | ForEach-Object {
    $parts = $_ -split ', '
    [PSCustomObject]@{ Key = $parts[0]; Value = $parts[1] }
} | Group-Object -Property Key

# Store the output in a variable
$sortedtags = $groupedData | ForEach-Object {
    $key = $_.Name
    $values = $_.Group | ForEach-Object { $_.Value }
    "$key = " + ($values -join "`n")
}

# Extract only the values for ip-id
$ipIdOutput = $sortedtags | Where-Object { $_ -like "ip-id*" } | ForEach-Object {
    $_ -replace "ip-id = ", ""
}

# Extract only the values for ip-data
$ipDataOutput = $sortedtags | Where-Object { $_ -like "ip-data*" } | ForEach-Object {
    $_ -replace "ip-data = ", ""
}

# Extract only the values for ip-hardwave
$ipHardwaveOutput = $sortedtags | Where-Object { $_ -like "ip-hardwave*" } | ForEach-Object {
    $_ -replace "ip-hardwave = ", ""
}

# Extract only the values for ip-tube
$ipTubeOutput = $sortedtags | Where-Object { $_ -like "ip-tube*" } | ForEach-Object {
    $_ -replace "ip-tube = ", ""
}

# Print the ip-id values
$ipIdOutput = $ipIdOutput | ForEach-Object { "latest`n" + ($_ -replace '","', "`n" -replace '"', "") }
$ipDataOutput = $ipDataOutput | ForEach-Object { "latest`n" + ($_ -replace '","', "`n" -replace '"', "") }
$ipHardwaveOutput = $ipHardwaveOutput | ForEach-Object { "latest`n" + ($_ -replace '","', "`n" -replace '"', "") }
$ipTubeOutput = $ipTubeOutput | ForEach-Object { "latest`n" + ($_ -replace '","', "`n" -replace '"', "") }


$registryName = "testcontainers001"
$repositoryName = "org/ip-hardwave"
$tagsToExclude = $ipHardwaveOutput


# List the tags in the repository
$tagslist = az acr repository show-tags --name $registryName --repository $repositoryName --output table


$ipHardwaveOutput.GetType()
$tagsToExclude.GetType()

# Convert $tagslist to an array of strings
$tagsArray = $tagslist -split "`n"

$ipHardwaveOutput.GetType()
$tagsToExclude.GetType()

# Ensure both $tagsArray and $tagsToExclude are trimmed and formatted correctly
$tagsArray = $tagsArray | ForEach-Object { $_.Trim() }
$tagsToExclude = $tagsToExclude | ForEach-Object { $_.Trim() }

# Debugging output to check the contents of $tagsArray and $tagsToExclude
Write-Output "Tags Array:"
Write-Output $tagsArray
Write-Output "Tags to Exclude:"
Write-Output $tagsToExclude

# Filter tags to exclude the specified ones
$tagsToDelete = $tagsArray | Where-Object { $tagsToExclude -notcontains $_ }

# Debugging output to check the contents of $tagsToDelete
Write-Output "Tags to Delete:"
Write-Output $tagsToDelete

# Delete the remaining tags
foreach ($tag in $tagsToDelete) {
    $imageToDelete = "$($repositoryName):$($tag)"
    Write-Output $imageToDelete
    #az acr repository delete --name $registryName --image $imageToDelete --yes --dry-run
}

Having output as below

Tags to Exclude:

latest
develop-20210911.1
20210904.1
20210904.1

Tags to Delete:

20210605.1
20210605.3
20210828.5
20210828.8
20210828.9
20210829.1
20210829.2
20210829.3
20210829.5
20210830.1
20210830.2
20210904.1
20210904.2
20210905.1
20210905.2
20210905.3
20210906.1
20210906.2
20210909.1
20210910.1
20210910.2
develop-20210911.1
latest



org/ip-hardwave:20210605.1
org/ip-hardwave:20210605.3
org/ip-hardwave:20210828.5
org/ip-hardwave:20210828.8
org/ip-hardwave:20210828.9
org/ip-hardwave:20210829.1
org/ip-hardwave:20210829.2
org/ip-hardwave:20210829.3
org/ip-hardwave:20210829.5
org/ip-hardwave:20210830.1
org/ip-hardwave:20210830.2
org/ip-hardwave:20210904.1
org/ip-hardwave:20210904.2
org/ip-hardwave:20210905.1
org/ip-hardwave:20210905.2
org/ip-hardwave:20210905.3
org/ip-hardwave:20210906.1
org/ip-hardwave:20210906.2
org/ip-hardwave:20210909.1
org/ip-hardwave:20210910.1
org/ip-hardwave:20210910.2
org/ip-hardwave:develop-20210911.1
org/ip-hardwave:latest

expecting output as below

org/ip-hardwave:20210605.1
org/ip-hardwave:20210605.3
org/ip-hardwave:20210828.5
org/ip-hardwave:20210828.8
org/ip-hardwave:20210828.9
org/ip-hardwave:20210829.1
org/ip-hardwave:20210829.2
org/ip-hardwave:20210829.3
org/ip-hardwave:20210829.5
org/ip-hardwave:20210830.1
org/ip-hardwave:20210830.2
org/ip-hardwave:20210904.2
org/ip-hardwave:20210905.1
org/ip-hardwave:20210905.2
org/ip-hardwave:20210905.3
org/ip-hardwave:20210906.1
org/ip-hardwave:20210906.2
org/ip-hardwave:20210909.1
org/ip-hardwave:20210910.1
org/ip-hardwave:20210910.2

Solution

  • Rather than replacing item delimiters with literal newline characters, split the input data into arrays instead.

    For example, change:

    $ipIdOutput = $sortedtags | Where-Object { $_ -like "ip-id*" } | ForEach-Object {
        $_ -replace "ip-id = ", ""
    }
    

    to:

    $ipIdOutput = @($sortedtags | Where-Object { $_ -like "ip-id*" } | ForEach-Object {
        # remove key and split on comma
        $values = $_ -replace "ip-id = ", "" -split ','
        # trim leading/trailing whitespace, then remove leading/trailing quotes from each value
        $values |ForEach-Object {$_.Trim() -replace '^"(.*)"$','$1'}
    })
    

    and then replace the following:

    $ipIdOutput = $ipIdOutput | ForEach-Object { "latest`n" + ($_ -replace '","', "`n" -replace '"', "") }
    

    with:

    # insert "latest" tag on top
    $ipIdOutput = @('latest';$ipIdOutput)
    

    Repeat for $ipDataOutput, $ipHardwaveOutput and $ipTubeOutput, and you're done.

    $tagsToExclude gets its value from $ipHardwaveOutput, so by turning that into a proper array containing individual values as separate strings you'll incidentally also solve the filtering problem.