Automate deployment of JSON map - azure

I have a Logic App in Azure which use a Liquid map, to transform JSON content. I am trying to deploy the map using New-AzureRmIntegrationAccountMap commandlet and the Set-AzureRmIntegrationAccountMap commandlet.
I get the following error when calling the Set-AzureRmIntegrationAccountMap commandlet:
Set-AzureRmIntegrationAccountMap : Unable to deserialize the response.
With this script:
Try
{
Write-Host -ForegroundColor Green "Creating $baseName..."
$mapContent = Get-Content -Path $fullName | Out-String
Write-Host -ForegroundColor Cyan "$mapContent"
New-AzureRmIntegrationAccountMap -ResourceGroupName $resourceGroupName -Name $iacName -MapName $baseName -MapDefinition $mapContent -ErrorAction Stop
Write-Host -ForegroundColor Green "Successfully created $baseName"
}
Catch
{
Write-Host -ForegroundColor Red "Error creating $baseName, trying update..."
Set-AzureRmIntegrationAccountMap -ResourceGroupName $resourceGroupName -Name $iacName -MapName $baseName -MapDefinition $mapContent -Force
if ($?) {
Write-Host -ForegroundColor Green "Successfully updated $baseName"
} else {
Write-Host -ForegroundColor Red "Error updating $baseName"
exit 1
}
}
After some searches, the two commandlets accept the MapType parameter, but only one value is allowed (XSLT).
Is there a way to automate the deployment of Liquid maps in an integration account in Azure (powershell, ARM template...) ?

Is there a way to automate the deployment of Liquid maps in an integration account in Azure (powershell, ARM template...) ?
Yes, I could create Liquid map with PowerShell on my side with the following code.
Login-AzureRmAccount
$IntegrationAccountName = "Integration Account name"
$ResouceGroupname = "ResourcegroupName"
$ResourceLocation = "West US" # location
$ResourceName = "liquid name"
$Content = Get-Content -Path "C:\Tom\simple.liquid" | Out-String
Write-Host $Content
$PropertiesObject = #{
mapType = "liquid"
content = "$Content"
contentType = "text/plain"
}
New-AzureRmResource -Location $ResourceLocation -PropertyObject $PropertiesObject -ResourceGroupName $ResouceGroupname -ResourceType Microsoft.Logic/integrationAccounts/maps -ResourceName " $IntegrationAccountName/$ResourceName" -ApiVersion 2016-06-01 -Force
Check it from azure portal.

Related

How to set the ComputeModel property to Serverless on an Azure SQL Database using PowerShell?

I'm restoring an Azure SQL Database (Serverless) from a deleted database backup using Get-AzSqlDeletedDatabaseBackup and Restore-AzSqlDatabase PowerShell commandlets. The restore works, but the tags and ComputeModel are not restored with the database.
I've tried using Set-AzSqlDatabase:
Set-AzSqlDatabase -ResourceGroupName $resourcegroupname -DatabaseName $databasename -ServerName $servername -ComputeModel "Serverless" -AutoPauseDelayInMinutes 45
Update: I tried the following code and the Kind is set prior to using the Set-AzResource cmdlet, but it doesn't stick
$resource = Get-AzResource -ResourceGroupName $resourcegroupname -ResourceType "Microsoft.Sql/servers/databases" -Name "$servername/$databasename"
Write-Host "Setting ComputeModel to Serverless..."
$resource.Kind = "v12.0,user,vcore,serverless"
$resource
# resource.Kind is successfully set on the $resource object
Write-Host "Set-AzResource..."
$resource | Set-AzResource -Force
Anyone have any ideas?
Thank you.
Cheers,
Andy
The Get-AzSqlDeletedDatabaseBackup and Restore-AzSqlDatabase PowerShell cmdlets are doesn't contain a property to get the ComputeModel.
While Restore and Delete Backup database we don't require the ComputeModel properties. while setting database we need to require the ComputeModel.
If you want to get the compute model for the Azure SQL Database you can use, Get-AzResource command to fetch the specific information.
Thanks #joy wang SO Solution we can get the serverless Azure SQL Database.
Thanks to #holger and #Delliganesh Sevanesan for the help, I was able implement a solution that restores the most recent deleted database (SQL Database), adds some resource tags, and sets the ComputeModel to serverless.
Here's the code:
<#
Purpose: Restore the most recently deleted Azure Sql Database
Dependencies:
Az.Sql PowerShell module
#>
# Set variables first
$resourcegroupname = 'myresourcegroup'
$servername = 'myservername'
$databasename = 'mydatabasename'
[hashtable]$tags = #{
application = "testing"
}
try {
$deleteddatabases = Get-AzSqlDeletedDatabaseBackup -ResourceGroupName $resourcegroupname -ServerName $servername -DatabaseName $databasename
} catch {
Write-Error "Error getting database backups [Get-AzSqlDeletedDatabaseBackup]: " + $_.Exception.Message
exit(1)
}
# Get most recent backup in case there are multiple copies
# Assumes index and order in foreach is the same - proven in test
Write-Host "Database backups:"
$index = 0
$MostRecentBackupIndex = 0
$MostRecentBackupDate = (Get-date).AddDays(-2) # initialize variable with date from two days ago
foreach ($db in $deleteddatabases) {
if ($db.CreationDate -ge $MostRecentBackupDate) {
$MostRecentBackupIndex = $index
$MostRecentBackupDate = $db.CreationDate
Write-Host "Most Recent Database: $($db.DatabaseName) : Created: $($db.CreationDate) : DeleteDate: $($db.DeletionDate)"
}
$index++
}
$deleteddatabase = $deleteddatabases[$MostRecentBackupIndex]
Write-Host "----------------------------------------------------------------------------------"
Write-Host "Restoring: $($deleteddatabase.DatabaseName) from: $($deleteddatabase.CreationDate) backup"
Write-Host "----------------------------------------------------------------------------------"
Write-Host "Deleted database info ResourceId: "
Write-Host $deleteddatabase.ResourceId
try {
Restore-AzSqlDatabase -FromDeletedDatabaseBackup `
-DeletionDate $deleteddatabase.DeletionDate `
-ResourceGroupName $resourcegroupname `
-ServerName $servername `
-TargetDatabaseName $databasename `
-ResourceId $deleteddatabase.ResourceID `
-Edition $deleteddatabase.Edition `
-Vcore 2 `
-ComputeGeneration "Gen5"
} catch {
Write-Error "Error restoring database [Restore-AzSqlDatabase]: " + $_.Exception.Message
exit(1)
}
# Wait a few minutes to allow restore to complete before applying the tags
Start-Sleep -Seconds 180
Write-Host "Applying tags to database..."
try {
$resource = Get-AzResource -ResourceGroupName $resourcegroupname -ResourceType "Microsoft.Sql/servers/databases" -Name "$servername/$databasename"
New-AzTag -ResourceId $resource.Id -Tag $tags
} catch {
Write-Error "Error adding tags to database [Get-AzResource, New-AzTag]: " + $_.Exception.Message
exit(1)
}
Write-Host "Setting ComputeModel to Serverless..."
try {
# Important - must include -AutoPauseDelayInMinutes 60, -MinVcore, and MaxVcore parameters (thanks holger)
Set-AzSqlDatabase -ResourceGroupName $resourcegroupname -DatabaseName $databasename -ServerName $servername -ComputeModel Serverless -AutoPauseDelayInMinutes 60 -MinVcore 1 -MaxVcore 2
} catch {
Write-Error "Error setting serverless mode [Set-AzSqlDatabase]: " + $_.Exception.Message
exit(1)
}
Write-Host "Database restore complete."

Lock azure resource with PowerShell

I've been trying to run a script to create a lock on azure resource to prevent resources being deleted inadvertently.
I get an error message and I can't figure out why it's showing me this error message.
Script:
#Sign in to Azure account
Login-AzAccount
#Select the subscription you want to work on
Select-AzSubscription -Subscription "test.subscription"
#Get All Resources in a resource group
$Resources = Get-AzResource -ResourceGroupName dummy_rg | Format-Table
# Create lock "delete" on each Resource if it doesn't exist
foreach($Resource in $Resources) {
$ResourceName = $Resource.Name
$lck = Get-AzResourceLock -ResourceGroupName $Resource.ResourceGroupName -ResourceName $ResourceName -ResourceType $Resource.ResourceType
if ($null -eq $lck)
{
Write-Host "$ResourceName has no lock"
New-AzResourceLock -resourceGroupName $rg -ResourceName $ResourceName -ResourceType $Resource.ResourceType -LockName "$ResourceName-lck" -LockLevel CanNotDelete -Force
Write-Host "$ResourceName has been locked"
}
else
{
Write-host "$ResourceName already locked"
}
}
Error message:
Gaurav request result:
#Start logging
Start-Transcript -Path "C:\Windows\Logs\Lock - $(((get-date).ToUniversalTime()).ToString("yyyy-MM-dd_hh-mm-ss")).log" -Force
#Connect to Azure account
Login-AzAccount
#Select Azure subscription
Set-AzContext -Subscription "subscription_id_numbers"
#Deny rule on Azure Data Factory and Azure Machine Learning
$Resources = Get-AzResource | Where-Object {$_.Name -NotLike '*adf*' -and $_.Name -NotLike '*aml*'}
# Create lock "delete" on each Resource if it doesn't exist
foreach($Resource in $Resources) {
$ResourceName = $Resource.Name
$lck = Get-AzResourceLock -ResourceGroupName $Resource.ResourceGroupName -ResourceName $ResourceName -ResourceType $Resource.ResourceType
if ($lck -eq $null)
{
Write-Host "$ResourceName has no lock"
Set-AzResourceLock -ResourceGroupName $Resource.ResourceGroupName -ResourceName $ResourceName -ResourceType $Resource.ResourceType -LockName "$ResourceName-lck" -LockLevel CanNotDelete -Force
Write-Host "$ResourceName has been locked"
}
else
{
Write-host "$ResourceName already locked"
}
}
#Stop Logging
Stop-Transcript
This will loop on every ressources except azure data factory in the tenant and create a "delete" type lock to make sure resources aren't deleted inadvertently.
Read comments in each section to understand the code.

Azure Automation Runbook missing mandatory parameters

I'm trying to set a Tag on all virtual machines in my subscription but I keep getting errors when running the Runbook.
The error is the following:
Get-AzureRmVM : Cannot process command because of one or more missing mandatory parameters: ResourceGroupName. At line:30
Here is my Runbook:
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Add-AzureRmAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzureRmVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzureRmVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzureRmResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzureRmResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"
I tried importing the right modules but this doesn't seem to affect the outcome.
Running the same commands in Cloud Shell does work correctly.
I can reproduce your issue, the error was caused by this part Get-AzureRmVM -Name $azurevm, when running this command, the -ResourceGroupName is needed.
You need to use the Az command Get-AzVM -Name $azurevm, it will work.
Running the same commands in Cloud Shell does work correctly.
In Cloud shell, azure essentially uses the new Az module to run your command, you can understand it runs the Enable-AzureRmAlias before the command, you could check that via debug mode.
Get-AzureRmVM -Name joyWindowsVM -debug
To solve your issue completely, I recommend you to use the new Az module, because the AzureRM module was deprecated and will not be updated.
Please follow the steps below.
1.Navigate to your automation account in the portal -> Modules, check if you have imported the modules Az.Accounts, Az.Compute, Az.Resources, if not, go to Browse Gallery -> search and import them.
2.After import successfully, change your script to the one like below, then it should work fine.
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Connect-AzAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"

Check if Azure VM name exists before deploying arm template

I am trying to use Azure powershell to get VM name (Eg: demovm01, where the VM name is demovm and the suffix is 01.
I want to get the output and automatically append a new suffix of 02 if 01 already exists.
Sample script to get vm name:
$getvm = Get-AzVM -Name "$vmname" -ResourceGroupName "eodemofunction" -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent) {
Write-Output "VM not found. Creating now"
}
else {
Write-Output "VM exists."
return $true
}
I want to be able to inject this new vm name to an arm deploy to deploy
This should do it. Will increment until no VM is found and use a simple -replace to inject to your json file. Will also return all thr VM values that are already present in Azure
$i=1
$vmname_base = "vmserver"
$VMexists = #()
do {
#invert int value to double digit string
$int = $i.tostring('00')
$getvm = Get-AzVM -Name "$vmname_base$int" -ResourceGroupName "eodemofunction" -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent) {
Write-Output "VM not found. Creating now"
Write-Output "VM created name is $vmname_base$int"
#Set condition to end do while loop
VMcreated = "true"
#commands to inject to json here. I always find replace method the easiest
$JSON = Get-Content azuredeploy.parameters.json
$JSON = $JSON -replace ("Servername","$vmname_base$int")
$JSON | Out-File azuredeploy.parameters.json -Force
}
else {
Write-Output "VMexists."
# Add existing VM to array
$VMexists += "$vmname_base$int"
# Increment version, ie. 01 to 02 to 03 etc
$i++
}
} while ($VMcreated -ne "true")
return $VMexists
Your command could be like below, the $newvmname is that you want.
$vmname = "demovm01"
$getvm = Get-AzVM -Name "$vmname" -ResourceGroupName "<group name>" -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent) {
Write-Output "VM not found. Creating now"
}
else {
Write-Output "VM exists."
if($getvm.Name -like '*01'){
$newvmname = $vmname.TrimEnd('01')+"02"
}
Write-Output $newvmname
return $true
}

Passing multiple Parameters in single Azure Storage Script for various environments

I have a powershell script that creates the storage and blob account for a given subscription that works fine . Subscription Name, resource group keeps changing for different environments like DEV,UAT,PROD
STRUCTURE OF MY TEMPLATE / CODE :
param(
[string] $subscriptionName ="ABC",
[string] $resourceGroupName = "XYZ",
[string] $resourceGroupLocation ="westus",
[string] $templateFilePath = "template.json",
[string] $parametersFilePath = "parameters.json"
)
Function RegisterRP {
Param(
[string]$ResourceProviderNamespace
)
Write-Host "Registering resource provider '$ResourceProviderNamespace'";
Register-AzureRmResourceProvider -ProviderNamespace $ResourceProviderNamespace;
}
$ErrorActionPreference = "Stop"
$confirmExecution = Read-Host -Prompt "Hit Enter to continue."
if($confirmExecution -ne '') {
Write-Host "Script was stopped by user." -ForegroundColor Yellow
exit
}
# sign in
Write-Host "Logging in...";
Login-AzureRmAccount;
# select subscription
Write-Host "Selecting subscription '$subscriptionName'";
Select-AzureRmSubscription -SubscriptionName $subscriptionName;
# Register RPs
$resourceProviders = #("microsoft.storage");
if($resourceProviders.length) {
Write-Host "Registering resource providers"
foreach($resourceProvider in $resourceProviders) {
RegisterRP($resourceProvider);
}
}
#Create or check for existing resource group
$resourceGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
if(!$resourceGroup)
{
Write-Host "Resource group '$resourceGroupName' does not exist. To create a new resource group, please enter a location.";
if(!$resourceGroupLocation) {
$resourceGroupLocation = Read-Host "resourceGroupLocation";
}
Write-Host "Creating resource group '$resourceGroupName' in location '$resourceGroupLocation'";
New-AzureRmResourceGroup -Name $resourceGroupName -Location $resourceGroupLocation
}
else{
Write-Host "Using existing resource group '$resourceGroupName'";
}
# Start the deployment
Write-Host "Starting deployment...";
if(Test-Path $parametersFilePath) {
New-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -Name $deploymentName -TemplateFile $templateFilePath -TemplateParameterFile $parametersFilePath -storageAccounts_name $storageAccountName
} else {
New-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -Name $deploymentName -TemplateFile $templateFilePath; -storageAccounts_name $storageAccountName
}
Approach 1 :
Created multiple powershell scripts for each denvironment
Created 1 Menu Based powershell script that calls the other script and executes like : Select 1 for Dev , 2 for UAt , 3 for PROD , this approach works but is not effective .
Approach 2 :
I would like to combine all scripts and just have one script for all environments and based on select should allow me to create the storage accounts. Only Subscription and resource group change rest all structure of the powershell remains same .
I tried using GET function commandlets and it selects but still throws the error
[string] $subscriptionName = Get-AzureSubscription,
[string] $resourceGroupName = Get-AzureRmLocation,
If i try to use it using an array based approach like passing the values as below im unable to understand how do i pass these array based values to the code and get it to work .
$environment=#('DEV','TEST','QA','PROD')
$resourcegroupname = #('test','test1','test2','test3')
$subscriptionName = #('devsub1','devsub2','test3','prod4')
I'm trying to call the functions using :
$environment[0]
$subscriptionName[0]
It returns the value as below if i execute it seperately but how do i pass these values to my script to create storage account ?
DEV
devsub1
Requesting expert help if anyone has come across such scenarios earlier and if you can help in changing the above code and provide a tested code that would be of great help.
APPROACH 3:
$subscription = #(Get-AzureRmSubscription)
$resourcegroup = #(Get-AzureRmResourceGroup)
$Environment = #('DEV','TEST','QA','PROD')
$resourceGroupName = $resourcegroup | Out-GridView -PassThru -Title 'Pick the environment'
$subscriptionName = $subscription | Out-GridView -PassThru -Title 'Pick the subscription'
Write-Host "Subscription:" $subscriptionName
Write-Host "ResourceGroup:" $resourcegroup
OUTPUT :
If you look at resource group it fails to give the selection option for resource group .
Subscription: < it returns the subscription name >
ResourceGroup: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.PSResourceGroup Microsoft.Azure.Commands.ResourceManager.Cmd
lets.SdkModels.PSResourceGroup Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.PSResourceGroup Microsoft.Azure.Commands.Res
ourceManager.Cmdlets.SdkModels.PSResourceGroup
What you are proposing is an interesting approach. I would likely an input parameter that defines which environment the work will be done in, and then have a conditional block that sets the dynamic variables for that environment. There would be some duplication of initialization code for each environment, but the main code block would still be unified.

Resources