Why I have added the below pic ?
Python is what I have been picking from the Dev world (currently) and PowerShell is what I have picked from the Ops world.
In Azure Resource Manager, one can add tags to the Resource Groups (check out the new Azure Portal to explore ResourceGroups ). Last week had to script a way to check that there is a Tag on the resource group with a valid set of values. Python Azure SDK doesn't yet support Azure Resource Manager operations so had to turn to the Ops side (PowerShell way).
Don't worry if you have no idea what a tag is, the validation code is pretty neat.
For Example - the Resource Group should have a tag named "Environment" on it with the valid values of "Dev","QA" & "Prod" .
There can be other tags on it but we are looking only for the existence of this tag & values.
Let's get started.
- Since Azure Resource Manager cmdlets doesn't support Certificate based authentication. We have to use Azure AD here. First step is to use below cmdlet to add your account using which you login to the Azure Portal.
- Once authenticated , Switch to using Azure resource manager cmdlets using the below cmdlet. So that we get the AzureResourceManager Module loaded.
- Now you can see in the PowerShell host that the AzureResourceManager Module is loaded:
- Use the cmdlet Get-AzureResourceGroup to get Resource Groups and store them in a variable for later processing.
- Now we can filter Resource Groups which have tags property like below :
PS>$ResourceGroups | where tags ResourceGroupName : DexterPOSHCloudService Location : southeastasia ProvisioningState : Succeeded Tags : Name Value =========== ========= Environment QA TestKey TestValue ResourceId : /subscriptions/4359ee69-61ce-430c-b885-4083b2656de7/resourceGroups/DexterPOSHCloudService ResourceGroupName : dexterseg Location : southeastasia ProvisioningState : Succeeded Tags : Name Value =========== ======= Environment Testing ResourceId : /subscriptions/4359ee69-61ce-430c-b885-4083b2656de7/resourceGroups/dexterseg
Maybe those who don't have the Tags property we can throw a warning but I leave the Scripting logic for you to build upon. - Now out of the 2 Resource groups above one has a valid Environment Tag of value "QA" (in green) but the other one has an invalid tag value of "Testing" (in yellow).
Before we start validating the Values we need to check if the Tag contains the desired Environment tag, for this we can use the contains() method.
But if you look closely you will find something strange with the tags property :
PS>$ResourceGroups[0].tags Name Value ---- ----- Value LAB Name Environment Value TestValue Name TestKey
Tags property is a hashtable but the keys are "Name" & "Value" literal. Not very intuitive as I thought I would be getting the Environment as one of the key for the hashtable returned, submitted a issue at the GitHub repo for this.
Until it is fixed we can check if at all our Environment tag is present by using the ContainsValue method on the Hashtable, like below :
PS>$ResourceGroups[0].tags[0].ContainsValue('Environment') True
Now if the tag has the Environment as the value for 'Name' key then evidently the value for 'Value' key will be the one we are seeking.
PS>$ResourceGroups[0].tags[0]['Name'] Environment PS>$ResourceGroups[0].tags[0]['Value'] QA
Wow ! so much work am already dozing off :P - It appears validating the value is one of our permitted values ('Dev','QA','Prod') is relatively easy using the validateset() parameter attribute, see the below:
PS>[Validateset('DEV','QA','PROD')]$testme = $ResourceGroups[0].tags[0]['Value'] PS>[Validateset('DEV','QA','PROD')]$testme = $ResourceGroups[1].tags[0]['Value'] The attribute cannot be added because variable testme with value LAB would no longer be valid. At line:1 char:1 + [Validateset('DEV','QA','PROD')]$testme = $ResourceGroups[0].tags[0]['Value'] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : MetadataError: (:) [], ValidationMetadataException + FullyQualifiedErrorId : ValidateSetFailure
When we decorate the $testme variable with the ValidateSet() attribute and perform the assignment it will throw an exception if the value is not in the set (note that the second resource group in step 5 doesn't have a valid Environment tag), which we can catch later and display a message saying that the Environment tag doesn't have a valid value.
Add-AzureAccount
Switch-AzureMode -Name AzureResourceManager
PS>Get-Module
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Manifest 0.9.1 AzureResourceManager {Add-AlertRule, Add-AutoscaleSetting, Add-AzureAccount, Ad...
PS>$ResourceGroups = Get-AzureResourceGroup
Below is the sample code for one to build upon :
001
002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 |
Add-AzureAccount
Switch-AzureMode -Name AzureResourceManager $ResourceGroups = Get-AzureResourceGroup | where Tags foreach ($ResourceGroup in $ResourceGroups) { if ($ResourceGroup.tags.values.Contains('Environment')) { Write-Verbose -Message "$($ResourceGroup.ResourceGroupName) Environment tag not found" -Verbose foreach ($Tag in $ResourceGroup.Tags) { if ($Tag.ContainsValue('Environment')) { TRY { [validateset('DEV','QA','PROD')]$testme = $Tag['Value'] } CATCH [System.Management.Automation.ValidationMetadataException] { Write-Error -Message "Environment tag doesn't contain a valid value -->('DEV','QA','PROD')" } } } } else { Write-Warning -Message "$($ResourceGroup.ResourceGroupName) Environment tag not found" } } |
Thanks for reading and that is it for today's post.
~Dex~