How to read txt/csv line by line using PowerShell - azure

I have a couple of txt/csv files, I am trying to feed the each line in the file into my API commands in a loop.
eg: server.txt - first file contains servers and resource groups server1, rg1
server2, rg2
server3, rg3 etc.
ips.txt - another file contains rules & ips rule1, startip1, endip1
rule2, startip2, endip2
rule3, startip3, endip3 etc.
The issue is how to I set up powershell to each line in server.txt and also ips.txt within the same loop?
I had something like this before, but It doesnt seem to work well. Any thoughts?
$list=Get-Content "servers.txt"
foreach ($data in $list) {
$server_name, $rg = $data -split ',' -replace '^\s*|\s*$'
Write-Host "Checking if SQL server belongs in subscription"
$check=$(az sql server list -g $rg --query "[?name == '$server_name'].name" -o tsv)
Write-Host $check
# Get current rules and redirect output to file
az sql server firewall-rule list --resource-group "$rg" --server "$server_name" --output table | Export-Csv -NoTypeInformation current-natrules.csv
$new_rules=Get-Content "ips.txt"
foreach ($data in $new_rules) {
$rule_name, $start_ip, $end_ip = $data -split ',' -replace '^\s*|\s*$'
# Create rule with new configs
Write-Host "Assigning new firewall rules..."
az sql server firewall-rule create --name "$rule_name" --server "$server_name" --resource-group "$rg" --start-ip-address "$start_ip" --end-ip-address "$end_ip" --output table
}
# Validating
Write-Host "Printing new NAT rules to file..."
az sql server firewall-rule list --resource-group "$rg" --server "$server_name" --output table | Export-Csv -NoTypeInformation new-natrules.csv
}

Related

Adding tags to azure VMs via CSV

trying to add tags to VMs via CSV data, right now I have the below code:
if ($context.Account -eq $null) {
# Login-AzureAccount
Connect-AzAccount
}
# Select Azure Subscription
$subscriptionId = (Get-AzSubscription | Out-GridView -Title "Select an Azure Subscription ..." -PassThru).SubscriptionId
#Select specified subscription ID
Select-AzSubscription -SubscriptionId $subscriptionId
$InputCSVFilePath = "test.csv"
$csvItems = Import-Csv $InputCSVFilePath
################
foreach ($item in $csvItems){
Clear-Variable r
#$r = Get-AzResource -ResourceGroupName $item.ResourceGroup -Name $item.VM -ErrorAction Continue
$r = Get-AzResource -Name $item.VM
################
if ($r -ne $null){
if ($r.Tags){
# Tag - Client DL
if ($r.Tags.ContainsKey("Client_DL")){
$r.Tags["Client_DL"] = $item.ClientDL
}else{
$r.Tags.Add("Client_DL", $item.ClientDL)
}
# Tag - Priority
if ($r.Tags.ContainsKey("Priority")){
$r.Tags["Priority"] = $item.Priority
}else{
$r.Tags.Add("Priority", $item.Priority)
}
}
}else{
Write-Host "No VM found named $($item.VMName)!"
}
}
I verified that my code does indeed go through the functions but for some reason the tags are not being set on my VM's. I ran the commands manually in powershell and I was able to set a tag by doing:
$r = Get-AzResource -Name TestVM
$r.Tags.Add("Client_DL", "TEST-DL")
Am I missing something? i'm running a Set-PSDebug -Trace 2 when running my code and it seems to check out just fine, but the tags aren't getting set/written.
So you're adding the tags in memory but you're not calling any of the Az cmdlets to set the tags back on the resource.
You can see in the example in the docs here they return the VM with Get-AzResource, append their new tag to the existing tags and then use Set-AzResource to write the newly added tag back.
Just be careful of that
When updating tags through PowerShell, tags are updated as a whole. If you are adding one tag to a resource that already has tags, you will need to include all the tags that you want to be placed on the resource
Alternatively you could use Update-AzTag which has an -Operation parameter and lets you choose whether you want to merge, replace or delete the existing tags.
https://learn.microsoft.com/en-us/powershell/module/az.resources/update-aztag?view=azps-6.0.0
Ultimately you'd need to set back your $r.Tags value to your resource as the last operation within your if statement.

Recursively list all resource tags within Azure Resource Groups

We have a large number of Azure Subscriptions which currently run into the hundreds.
I'm looking to generate a report (ideally using Azure Powershell or Azure CLI) to recursively extract a list of all tags assigned to every single resource within every resource group, for between 40-50 of the subscriptions.
Currently, I can list all tags assigned at Resource Group level, but I simply can't find a way to list the tags assigned to the individual resources within each Resource Group. The list of subscriptions and resource groups on which I'd like to extract this report, are saved in a CSV file which includes two columns displaying the Subscription name and Resource Group respectively.
Any tips on how to achieve the above would be fantastic and most appreciated.
Not detailed code but the idea here.
1.You should write a loop, in the loop, change the subscription each time by using this cmdlet:
Set-AzContext -Subscription $subscription_name.
2.Then get all the resource group in the specified subscription by using this cmdlet:
$resource_groups = Get-AzResourceGroup
3.Then write a nested loop(loop for each resource group), in this nested loop, use this cmdlet to get all azure resources within a resource group:
foreach($rg in $resource_groups){
$azure_resources = Get-AzResource -ResourceGroupName $rg.ResourceGroupName
}
4.Write another nested loop in step 3, this loop is used to go though all the azure resources within the specified resource group. Then use the code below to fetch tags for each azure resource within the resource group:
foreach($r in $azure_resources){
#the following code can get all the tags for one resource
$r.tags
}
Based on Ivan Yang's logic. I have built the PowerShell Script;
#---------DECLARE VARIABLES------------------------------------#
$bnsSubscription = Get-AzSubscription
$day = Get-Date -Format " ddMMMyyyy"
$tagPath = "C:\mytempfolder\"+"$day-Tag-Details.csv"
$tagFolderPath = "C:\mytempfolder\"
#---------DECLARE VARIABLES------------------------------------#
function Get-ResourceTag {
foreach ($subs in $bnsSubscription) {
Select-AzSubscription -SubscriptionName $subs.Name | Out-Null
Write-Host 'The selected Subscription is' ($subs).Name
New-Item -ItemType file -Path "$tagFolderPath\$($subs.Name).csv" -Force
$resource_groups = Get-AzResourceGroup
$resource_groups_details = Get-AzResourceGroup | Sort-Location ResourceGroupName | Format-Table -GroupBy Location ResourceGroupName,ProvisioningState,Tags
Write-Host 'The selected Resource Group is' ($resource_groups).Name 'and the tag information as follows'
#$resource_groups_details
$resource_groups | Select-Object ResourceGroupName,Tags | Export-CSV -Path "$tagFolderPath\$($subs.Name).csv" -Append
$OutputFile = #()
foreach($rg in $resource_groups){
$azure_resources = Get-AzResource -ResourceGroupName $rg.ResourceGroupName
$TestTags = $Resource.Tags.GetEnumerator()
foreach($r in $azure_resources){
Write-Host 'The selected resource is' ($r).Name 'and the information as follows'
$RGHT = New-Object "System.Collections.Generic.List[System.Object]"
$RGHT.Add("RGName",$r.ResourceGroupName)
$RGHT.Add("ResourceName",$r.name)
$RGHT.Add("Location",$r.Location)
$RGHT.Add("Id",$r.ResourceId)
$RGHT.Add("ResourceType",$r.ResourceType)
$RGHT.Add("ResourceTags",$r.Tags)
$OutputFile += New-Object psobject -Property $RGHT
$OutputFile | Export-Csv -Path "C:\mytempfolder\test22.csv" -append -NoClobber -NoTypeInformation -Encoding UTF8 -Force
}
}
}
}
#---------CALL FUNCTION------------------------------------#
Get-ResourceTag

Unable to update Azure Network Security Group using az cli

I am attempting to update a Network Security Group (SourceAddressPrefixes) via the cli. To begin, it appears that the az cmdlet Set-AzNetworkSecurityRuleConfig is broke; the output from the command states that it's succeeded but no change actually occurs to the NSG. Others have complained about this but no fix from MSFT yet.
With that said, I have tried a workaround method which saves the NSG in a variable, sets the SourceAddressPrefixes, and updates the NSG after:
$SaContext = (Get-AzStorageAccount -ResourceGroupName $RGName -Name $SAName).Context
$table = (Get-AzStorageTable -Name $TableName -Context $SaContext).CloudTable
$IPs = (Get-AzTableRow -Table $table).IP
$IPs = '"{0}"' -f ($IPs -join '","') # Updates the IPs to be double-quoted and separated by commas
$NSG = Get-AzNetworkSecurityGroup -ResourceGroupName $MyResourceGroup -Name $NSGName
($nsg.SecurityRules | Where-Object {$_.Name -eq 'HTTPS'}).SourceAddressPrefix = $IPList
$NSG | Set-AzNetworkSecurityGroup | Get-AzNetworkSecurityRuleConfig -Name $RuleName | Format-Table -AutoSize
The issue with the code above is that the cmdlet Set-AzNetworkSecurityGroup will not except value type system.string. It will only accept System.Collections.Generic.List[System.String]. Due to that I perform the following:
$IPList = New-Object System.Collections.Generic.List[string]
$IPList.Add($IPs)
Now, the previous Set-AzNetworkSecurityGroup accepts the array but now the command fails because the array values aren't double-quoted with a comma to separate them. Not sure what to do at this point.
Actual error messages below:
Cannot convert the (ip addresses here) value of type [system.string] to type "Systems.Collections.Generic.IList[System.String]
And once I convert my variable(array) to match that requirement the error is:
nsgRule has invalid Address Prefix. Value Provided (ip addresses here) statuscode:400 which i'm sure is because converting the array removes the double-quotes & commas.
If you want to update the Source Address Prefix of one Network Security Group rule, its value should be like
192.162.0.1
192.162.1.1
...
For example
$nsg= Get-AzNetworkSecurityGroup -Name $NSGName -ResourceGroupName $MyResourceGroup
$IPList = New-Object System.Collections.Generic.List[string]
$IPList.Add("192.162.0.1")
$IPList.Add("192.162.1.1")
($nsg.SecurityRules | Where-Object {$_.Name -eq 'Port_8080'}).SourceAddressPrefix =$IPList
$nsg|Set-AzNetworkSecurityGroup | Get-AzNetworkSecurityRuleConfig -Name "Port_8080" | Format-Table -AutoSize

ACR - delete only old images - variable reference not vald

Im trying to cleanup old images in my ACR. It has 8 repositories so first I want it to test it in only one of them... The complicated thing about it that I need to keep last 4 images created. So I have this script:
$acrName = ACRttestt
$repo = az acr repository list --name $acrName --top 1
$repo | Convertfrom-json | Foreach-Object {
$imageName = $_
(az acr repository show-tags -n $acrName --repository $_ |
convertfrom-json |) Select-Object -SkipLast 4 | Foreach-Object {
az acr repository delete -n $acrName --image "$imageName:$_"
}
}
But Im receiving the following error:
Failed At line:9 char:58 + ... az acr repository delete -n $acrName
--image "$imageName:$_" + ~~~~~~~~~~~ Variable reference is not valid. ':' was not followed by a valid variable name character. Consider
using ${} to delimit the name.
Any ideas?
Thanks in advance
You need to change the "$imageName:$_" into "${imageName}:$_". Then the script will like below:
$acrName = "ACRttestt"
$repo = az acr repository list --name $acrName --top 1
$repo | Convertfrom-json | Foreach-Object {
$imageName = $_
(az acr repository show-tags -n $acrName --repository $_ |
convertfrom-json |) Select-Object -SkipLast 4 | Foreach-Object {
az acr repository delete -n $acrName --image "${imageName}:$_"
}
}

Azure Powershell Script

I have written a PowerShell script to print VM names with unmanaged disks however it's giving me an error. Appreciate any help on this -
$location=Read-Host -Prompt 'Input location for VMs'
$azuresubscription=Read-Host -Prompt 'Input Subscription Id'
$rmvms=Get-AzurermVM
# Add info about VM's from the Resource Manager to the array
foreach ($vm in $rmvms)
{
# Get status (does not seem to be a property of $vm, so need to call Get-AzurevmVM for each rmVM)
$vmstatus = Get-AzurermVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Status | where Location -like $location
# Add values to the array:
$vmarray += New-Object PSObject -Property #{`
# Subscription=$Subscription.SubscriptionName; `
Subscription=$azuresubscription.SubscriptionName; `
AzureMode="Resource_Manager"; `
Name=$vm.Name; PowerState=(get-culture).TextInfo.ToTitleCase(($vmstatus.statuses)[1].code.split("/")[1]); `
Size=$vm.HardwareProfile.VirtualMachineSize}
}
foreach ($vm in $vmarray)
{
$vmdiskstatus = (Get-AzurermVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName).StorageProfile.OsDisk.ManagedDisk
if (!$vmdiskstatus) {Write-Host $vm.Name}
}
Error Message:
($vmarray is resulting in Null array) -
Cannot index into a null array.
Expected Output - $vmarray should have one VM as there is a running
instance in eastus (that's what I am using as value for $location)
As requested by Victor Silva to add my comment as answer, here goes:
You need to define the $vmarray as array before entering the loop to add objects to it.
Then, after that loop, the foreach ($vm in $vmarray) does have an array to index into, even if empty:
$location=Read-Host -Prompt 'Input location for VMs'
$azuresubscription=Read-Host -Prompt 'Input Subscription Id'
$rmvms=Get-AzurermVM
###################################################
# create an array variable to collect the result(s)
###################################################
$vmarray = #()
# Add info about VM's from the Resource Manager to the array
foreach ($vm in $rmvms)
{
# rest of your code
}

Resources