I want to delete all images in Azure Container Registry except the last two. I was looking for an script for do so but I only find to delete images older than X days. This is not possible for my situation because some days there are a lot of images created and other days only one.
Somebody has any idea?
Modify the values for $skipLastTags & $registryName to your choice and run this script on powershell.
Note: Please verify that you have az cli installed on your local system.
$registryName = 'registryName'
$doNotDeleteTags = ''
$skipLastTags = 4
$repoArray = (az acr repository list --name $registryName --output json | ConvertFrom-Json)
foreach ($repo in $repoArray)
{
$tagsArray = (az acr repository show-tags --name $registryName --repository $repo --orderby time_asc --output json | ConvertFrom-Json ) | Select-Object -SkipLast $skipLastTags
foreach($tag in $tagsArray)
{
if ($donotdeletetags -contains $tag)
{
Write-Output ("This tag is not deleted $tag")
}
else
{
az acr repository delete --name $registryName --image $repo":"$tag --yes
}
}
}
If you need this in bash.
The variable delete_from is 1-index based, i.e. if you specify the value 1, all images will be deleted.
A value of 3 keeps the 2 latest images.
#!/bin/bash -e
acr='your_acr'
repos=('repo1' 'repo2' 'repoN')
delete_from=3
for repo in "${repos[#]}"; do
tags_to_delete=$(echo $(az acr repository show-tags -n ${acr} --repository ${repo} --orderby time_desc --output tsv) | cut -d ' ' -f${delete_from}-)
for tag_to_delete in ${tags_to_delete}; do
az acr repository delete --yes -n ${acr} --image ${repo}:${tag_to_delete}
done
done
I am unable to test it right now but this little PowerShell script should work:
$acrName = 'YourACRName'
$repo = az acr repository list --name $acrName
$repo | Convertfrom-json | Foreach-Object {
$imageName = $_
(az acr repository show-tags -n $acrName --repository $_ |
convertfrom-json )| Select-Object -SkipLast 2 | Foreach-Object {
az acr repository delete --yes -n $acrName --image "$imageName:$_"
}
}
It retrieves all tags for each repository, skips the last 2, then it iterates over each tag and deletes it.
Please test it in some kind of test environment first.
If with "the last two" you mean the newest two, then this should do the trick:
az acr repository show-manifests --name your_acr --repository your_repo --orderby time_desc -o tsv --query '[].digest' | sed -n '3,$ p' | xargs -I% az acr repository delete --name your_acr --image your_repo#% --yes
You can use the build in acr purge command:
Powershell
$subscription = "your-subscription-id"
$registry = "your-registry"
$PURGE_CMD = "acr purge --filter 'acs-weather-api:.*' --keep 2 --ago 0d --untagged"
az acr run --cmd $PURGE_CMD --registry $registry --subscription $subscription /dev/null
Bash
SUBSCRIPTION="your-subscription-id"
REGISTRY="your-registry"
PURGE_CMD="acr purge --filter 'acs-weather-api:.*' --keep 2 --ago 0d --untagged"
az acr run --cmd "$PURGE_CMD" --registry "$REGISTRY" --subscription "$SUBSCRIPTION" /dev/null
Docs
Based on the answer from #Christian Holm Jørgensen
Now you can have list to be saved (save_list).
#!/bin/bash -e
acr='MY_ACR_NAME'
repos=('MY_REPO') # 'repo2' 'repoN')
save_list="0.2.0-alpha.1 latest 1.0.0"
string_remove_pattern() {
echo "${1//$2}"
}
for repo in "${repos[#]}"; do
tags_available=$(echo $(az acr repository show-tags -n "${acr}" --repository "${repo}" --orderby time_desc --output tsv))
for to_save in $save_list; do
tags_available=$(string_remove_pattern "$tags_available" "$to_save")
done
tags_to_delete=$tags_available
echo -e "The follow image, from ACR $acr and repos $repos, will be deleted:\n$tags_to_delete"
read -rp "Is the list of image to delete correct? (Y/N)" answer
if [ "$answer" == "Y" ]; then
for tag_to_delete in ${tags_to_delete}; do
az acr repository delete --yes -n "${acr}" --image "${repo}":"${tag_to_delete}"
done
fi
done
Related
I need to list all resources in all RGRPs on all subscriptions.
all what is there basically.
I try to do it with regex but does not work.
Get all resources on all subscriptions:
#! /bin/bash
for sub in $(az account list --query [].name -o tsv); do
az resource list -o tsv --subscription $sub 2>/dev/null
done
Check if your resource exists and print subscription of it
#! /bin/bash
for sub in $(az account list --query [].name -o tsv); do
az resource list -o tsv --subscription $sub 2>/dev/null --query [].name -o tsv 2>/dev/null | grep -i $1 && echo "SUBSCRIPTION: $sub" && exit
done
Let me know if there is simpler way.
Cheers
You can use a resource graph query (kusto/kcl) for that
Resources
| project name, type, location
| order by name asc
See also here:
https://learn.microsoft.com/en-us/azure/governance/resource-graph/samples/starter?tabs=azure-cli#list-resources
PowerShell:
Search-AzGraph -Query "Resources | project name, type, location | order by name asc"
'''On ACR we have 1 repository with 2 different application versions—one is 2020.1.1 and the other one is 2021.1.1
An example is given below:
acr.azure.io/app1:2021.1.2
acr.azure.io/app1:2021.1.1
acr.azure.io/app1:2020.1.2
acr.azure.io/app1:2020.1.1
Is there any way I can query the build version using azure CLI
az acr repository show-tags -n acr.qzure.io --repository app1 --orderby time_desc --query "[0]"
The above command always gives acr.azure.io/app1:2021.1.2 as an output
Is there any other way? Does it always query the highest version of 2020 or 2021?
'''
You can specify --orderby parameter to order items by time ascending or descending order. Then you can query each item by the index of an array. You can check the time with --detail parameter. See az acr repository show-tags
For example,
az acr repository show-tags -n acr.qzure.io --repository app1 --orderby time_desc --detail
with query like this
--orderby time_desc --query "[0]"
--orderby time_desc --query "[1]"
--orderby time_desc --query "[2]"
--orderby time_desc --query "[3]"
For more reference, you could see this thread.
I found the below command very useful to query the specific version.
az acr repository show-tags -n acr.qzure.io --repository app1 --orderby time_desc --output tsv | grep -e "2020.1.1.*" | head -1
I need to store the output of an AZ cli commands that fetches my private IPs as a variable.
I am using the following in a bash script:
echo "Fetching Monitoring Server IP"
SERVER_IP=$(az vm show -n ${THIS_VM_NAME} -g ${RSC_GRP_NAME} --query privateIps -o tsv)
echo "$SERVER_IP
It would appear that this isnt working as when I echo the variable, it comes back empty.
+ THIS_VM_NAME=XXXX-XX-XX-XX-XX
+ echo 'Fetching Monitoring Server IP'
Fetching Monitoring Server IP
++ az vm show -n XXXX-XX-XX-XX-XX3 -g XXXX-XX-XX-XX-XX --query privateIps -o tsv
+ SERVER_IP=
+ echo ''
I will appreciate any pointers on this
Edit
The command you post lost a parameter to get the private IPs, you can use the command with the parameter -d or --show-details like this:
az vm show -g resourceGrouName -n vmName -d
But this command just gets all the IPs including the secondary IP.
You can get all the VM primary IPs of each interface through a shell script like this:
count=0
while : ; do
nic=$(az vm nic list -g resourceGroupName --vm-name vmName --query [$count].id -o tsv)
if [[ $nic == '' ]]; then
break
fi
privateIps[$count]=$(az vm nic show -g resourceGroupName --vm-name vmName --nic $nic --query ipConfigurations[0].privateIpAddress -o tsv)
let count++
done
echo ${privateIps[*]}
A solution to my similar problem in Azure Cloud Shell was putting a dollar sign before your SERVER_IP variable if Powershell in chosen.
$SERVER_IP=$(az vm show --name vmname --resource-group rgname --show-details --query [publicIps] --output tsv)
I deployed some infra using Terraform, including an application gateway. Unfortunately not all settings can be set/updated with terraform. SO I have a shell script that updates the application gateway.
#!/bin/bash
SP_ID=${1}
SP_SECRET=${2}
TENANT_ID=${3}
SUBSCRIPTION=${4}
RG=${5}
az login --service-principal -u ${SP_ID} -p ${SP_SECRET} -t ${TENANT_ID}
az account set --subscription ${SUBSCRIPTION}
az account list -o table
# Get the name of the AG
echo "RG = ${RG}"
AG=$(az network application-gateway list --resource-group ${RG} | tail -n 1 | awk '{ print $2 }')
echo "AG = ${AG}"
# Get the AG backend pool name
BP=$(az network application-gateway address-pool list --resource-group ${RG} --gateway-name ${AG} | tail -n 1 | awk '{ print $1 }')
echo "Backend pool = ${BP}"
# Get the frontendip of the load balancer
LB=$(az network lb list --resource-group ${RG} | tail -n 1 | awk '{ print $2 }')
LBFEIP=$(az network lb frontend-ip list --lb-name ${LB} --resource-group ${RG} | tail -n 1 | awk '{ print $2 }')
echo "Load balancer = ${LB}"
echo "Frontend ip LB = ${LBFEIP}"
# Update the backend pool of the AG with the frontend ip of the loadbalancer
echo "Updating Backend address pool of AG ${AG}"
az network application-gateway address-pool update --gateway-name $AG --resource-group $RG --name $BP --servers ${LBFEIP}
# Update http settings
echo "Updating HTTP settings of AG ${AG}"
AG_HTS=$(az network application-gateway http-settings list --resource-group ${RG} --gateway-name ${AG} | tail -n 1 | awk '{ print $2 }')
az network application-gateway http-settings update --resource-group ${RG} --gateway-name ${AG} --name ${AG_HTS} --host-name-from-backend-pool true
# Update health probe
echo "Updating Health probe of AG ${AG}"
AG_HP=$(az network application-gateway probe list --resource-group ${RG} --gateway-name ${AG} | tail -n 1 | awk '{ print $4 }')
az network application-gateway probe update --resource-group ${RG} --gateway-name ${AG} --name ${AG_HP} --host '' --host-name-from-http-settings true
This script works fine running locally from my laptop but via the azure devops release pipeline I get the error:
ERROR: az network application-gateway address-pool list: error: argument --gateway-name: expected one argument
Somehow it cannot get the application gateway name when the script is running through the release pipeline.
Again, when running this script locally it works fine. Anyoone an idea of what I maybe missing here or can try?
I created the script on WSL Ubuntu and used a ubuntu hosted agent to publish the artifacts and also use a hosted ubuntu agent to deploy the script.
The error shows the problem directly. Your parameter "AG" is empty. You can get the parameter "AG" with the CLI command:
az network application-gateway list -g nancyweb --query "[].name" -o tsv
Or as you want with the output format table:
az network application-gateway list -g nancyweb -o table | tail -n 1 | awk '{print $3}'
You can get more details about az network application-gateway list. But if you want to get the specific one there is a point you should pay attention to because the list command shows all the application gateways.
I am trying to write an Azure CLI script that logs me into the portal using service principal, selects the subscription and then tag VMs in that subscription per Resource group only.
az login -u $service_principal_ID -p $service_principal_password --service-principal --tenant $tenant_ID
az account set --subscription $subID
az resource tag --resource-group $rg \
--tags tags.project=$project tags.owner=$owner tags.environment=$env \
--resource-type "Microsoft.Compute/virtualMachines" \
--output tsv
Azure gives me error when running this saying --name is missing, but I don't want to tag the VMs one by one.
Any Ideas?
I haven't actually tried this (I don't need any resources tagging ;) )
but something like this should get you working.
Basically, you need to pass that named parameter, and the only way to do that is to parse through the VM list first.
sample=$(az vm list --resource-group $rg )
for row in $(echo "${sample}" | jq -r '.[] | #base64'); do
_jq() {
echo ${row} | base64 --decode | jq -r ${1}
}
VMName=$(_jq '.name')
az resource tag --resource-group $rg \
--tags tags.project=$project tags.owner=$owner tags.environment=$env \
--resource-type "Microsoft.Compute/virtualMachines" \
--name $VMName \
--output tsv
done
Entirely unrelated, and this should probably be edited out - but damn, I do miss how easy this stuff is in PowerShell.
Add desired tags to the resource group:
az group update -n $rg \
--set tags.project=$project tags.owner=$owner tags.environment=$env
Then apply all the tags from that resource group to each child resource:
do
jsontag=$(az group show -n $rg --query tags)
t=$(echo $jsontag | tr -d '"{},' | sed 's/: /=/g')
r=$(az resource list -g $rg --query [].id --output tsv)
for resid in $r
do
az resource tag --tags $t --id $resid
done
done