How to re-use the parameters as variables in multi commands - azure

I want to save the typing and define the variables in powershell, then re-use it with other commands, i got error.
Import-Module Az.Cdn -Force
$cdnProfile = "abc_test"
$resourceGroupName = "test_dev"
$cdnProfileParameters = "-ProfileName $cdnProfile -ResourceGroupName $resourceGroupName"
$cdnProfile = Get-AzCdnProfile $cdnProfileParameters
$endpoint = Get-AzCdnEndpoint $cdnProfileParameters
$azCustomDomain = Get-AzCdnCustomDomain $cdnProfileParameters -CustomDomainName "www.example.com" -EndpointName $endpoint.Name -ErrorAction stop
it failed at first command Get-AzCdnProfile with error
Get-AzCdnProfile: A positional parameter cannot be found that accepts argument '-ProfileName abc_test -ResourceGroupName test_dev'.

As mentioned in the comments by mclayton, you can make use of below PowerShell script to achieve your scenario.
I tried to reproduce the same in my environment and got the results successfully like below:
I created an Azure CDN profile:
I used the below PowerShell script to retrieve the CDN profile:
$cdnProfileParameters = #{ "ProfileName" = "testcdn"; "ResourceGroupName" = "RG" };
$cdnProfile = Get-AzCdnProfile #cdnProfileParameters

Related

Why are write-host statements are not appearing when calling a script with an azure commandlet in it?

I have a very simplistic 2 scripts and I'm trying to call the powershell script from another powershell run script
run script (run.ps1)
.\NewRG.ps1 -rgName "singleVM12" -location "Canada Central" -tags #{dept="Marketing"}
called script (newRG.ps1)
[CmdletBinding()]
param (
[string]$rgName = "Test1-rg",
[string]$location = "Canada Central",
[Parameter(Mandatory)]
[hashtable]$tags)
$newRG = New-AzResourceGroup -name $rgName -location $location -tags #{dept="marketing"}
write-output "test"
I would expect that I should get test in the console but I get the properties of the Resource group
ResourceGroupName : singleVM12
Location : canadacentral
ProvisioningState : Succeeded
The issue is I have more complex scripts with multiple write-host entries that I want shown but none of it appears when I run the "run.ps1" file, it works fine if I just call the called script by itself. I tried using write-output and same thing happens. I noticed that hello world works, so I'm guessing something about the Azure commandlets are maybe causing this. Any way around this?
I am using Write-Output to print the values in prompt. I have followed the same way you did.
Follow the workaround:
testout.ps1
# I am getting resource information
[CmdletBinding()]
param (
[string]$rgName = "test")
#$newRG = New-AzResourceGroup -name $rgName -location $location -tags #{dept="marketing"}
$getResource = Get-AzResource -ResourceGroupName $rgName
write-output "azure resoure get successfully- " $rgName
$getResource = Get-AzResource -ResourceGroupName $rgName
write-output "test2- " $rgName
$getResource = Get-AzResource -ResourceGroupName $rgName
write-output "test3 - " $rgName
$getResource = Get-AzResource
write-output "test4- " $rgName
# you can use return to send the the required data to promt as well. But you can use end of your script otherwise it will skip after the return statement.
return $getResource.ResourceGroupName
test2.ps1
Calling testout.ps1 in test2.ps1 script.
# Connect Azure Account using specific Subscription Id if you are using more subscription in single account
Connect-AzAccount -SubscriptionId '<Your subscription Id>'
# calling test.ps1 script
.\testout.ps1 -rgName "<Your Resourcegroup Name>"
Result

Azure: create a new API Management service without a service URL

My intent is to configure an API (e.g. an Azure Function) into an API Manegement service using only policies. I don't want to specify a Service URL.
This is possible using Portal UI:
but not using PowerShell Az module.
Following code:
New-AzApiManagementApi -Context $context -Name $fullName -Protocols #('https') `
-Path $path -ProductIds #($product) `
-ApiVersionSetId $apiMgmtVersion.ApiVersionSetId
raises this exception:
Error : Unable to create 'news' managed API version 1.
Cannot validate argument on parameter 'ServiceUrl'. The argument is null or empty. Provide an argument that is not null or empty, and then try the
command again.
At C:\Projects\Intranet.ai\component_tools\Install-ApiMgmt.ps1:105 char:76
+ ... able to create '$fullName' managed API version $version.`n$_" | Error
+ ~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Error
Is there a way to define an API without a service URL? Maybe using directly New-AzResource?
Thanks to anyone who will help!
Is there a way to define an API without a service URL? Maybe using directly New-AzResource?
The New-AzApiManagementApi seems not support that, you could use the New-AzResource directly, please try the sample below, it works on my side.
$PropertiesObject = #{
"name" = "test22"
"serviceUrl" = $null
"path" = "testaaa"
"protocols" = #("https")
}
New-AzResource -PropertyObject $PropertiesObject -ResourceGroupName <Group-name> -ResourceType Microsoft.ApiManagement/service/apis -ResourceName "<API-management-servie-name>/test22" -ApiVersion 2018-01-01 -Force
Check in the portal:
Update:
If you want to include the apiVersionSetId, please try the one below.
$versionSet = Get-AzApiManagementApiVersionSet -Context $context -ApiVersionSetId "d41e7f92-9cf8-48fb-8552-d9ae5d4690d3"
$Id = $versionSet.Id -replace "apiVersionSets","api-version-sets"
$PropertiesObject = #{
"name" = "test22"
"serviceUrl" = $null
"path" = "testaaa"
"protocols" = #("https")
"apiVersionSetId" = $Id
}
New-AzResource -PropertyObject $PropertiesObject -ResourceGroupName <Group-name> -ResourceType Microsoft.ApiManagement/service/apis -ResourceName "<API-management-servie-name>/test22" -ApiVersion 2018-01-01 -Force

Replace Find-AzureRmResource with Get-AzureRmResource in AzureRM for Tagging Resources

I have a script that will apply all tags in a resource group to the child resources in the group. The script uses Find-AzureRmResource which has been depricated and removed from the newest modules. It says it has been replaced with Get-AzureRmResource, however I am unable to get it working properly with replacing with that. I get the error:
"Get-AzureRmResource : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the
input and its properties do not match any of the parameters that take pipeline input."
Here is the original script that used to work:
$rgname = "rg123"
$group = Get-AzureRmResourceGroup $rgname
if ($group.Tags -ne $null) {
$resources = $group | Find-AzureRmResource
foreach ($r in $resources)
{
$resourcetags = (Get-AzureRmResource -ResourceId $r.ResourceId).Tags
foreach ($key in $group.Tags.Keys)
{
if (($resourcetags) -AND ($resourcetags.ContainsKey($key))) { $resourcetags.Remove($key) }
}
$resourcetags += $group.Tags
Set-AzureRmResource -Tag $resourcetags -ResourceId $r.ResourceId -Force
}
}
here is the find-azurermresource I am trying to replace with:
$resources = $group | Get-AzureRmResource -ResourceGroupName $rgname
I have tried variations with -ResourceType as well, but still get the same error that it cannot take pipeline inputs. Is there away to get get this line working again with the replaced cmdlet Get-AzureRmResource?
You can immediatly use the following, no need to use Get-AzureRmResourceGroup:
$resources = Get-AzureRmResource -ResourceGroupName $rgname
This will get all resources from that specific group.

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.

How to pass multiple parameters in a function in Powershell?

I am trying to run a Powershell script for a runbook in an automation account in Azure. I am using a function to pass multiple parameters. The runbook is for restoring disks of VM. However from the code structure that I am using it doesn't seem like I can pass in more than 1 Resource Name. How do I restructure this code or how do I frame my function or anyone of the lines in the script in order to pass more than one Resource Name (VM names in this case) ?
Currently I can pass only one Resource Name in the function but I need to pass two VM names.
function DiskRestore($ResourceName, $storageAccount)
{
try
{
.....
.....
.....
$resources = Get-AzureRmResource -ResourceGroupName"samplerg" -ResourceName $ResourceName
.....
.....
.....
$restorejob = Restore-AzureRmRecoveryServicesBackupItem -RecoveryPoint $rp[0] -StorageAccountName $storageAccount -StorageAccountResourceGroupName "samplerg"
.....
.....
.....
}
}
DiskRestore -ResourceName "samplevm01" -storageAccount "samplesa01"
So in the above function how can I pass one more VM name apart from samplevm01. How can I pass samplevm02 ? The storage account remains the same. Thanks in advance.
As commented by Vesper, change the parameter definition to receive a string array and loop through that array with foreach{..}.
Personally I would extend this a little by putting the parameters in a Param() block to create an 'advanced function'. By doing so, the function automatically gains extra common PowerShell parameters like ErrorAction, Verbose etc.
Also, I would rename the function so it complies with the Verb-Noun naming convention for PowerShell functions.
Something like this:
function Restore-Disk {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true, Position = 0)]
[string[]]$ResourceName,
[string]$ResourceGroupName = 'samplerg', # add a default name for this parameter
[string]$StorageAccount = 'samplesa01', # add a default name for this parameter
[Parameter(Mandatory = $true)]
$RecoveryPoint
)
foreach ($resource in $ResourceName) {
try {
# .....
# This will only print to the console is the -Verbose parameter is used on the function
Write-Verbose "Retrieve resource '$resource' in group '$ResourceGroupName'"
$resources = Get-AzureRmResource -ResourceGroupName $ResourceGroupName -ResourceName $resource
# .....
Write-Verbose "Restoring data and configuration for group '$ResourceGroupName'"
$restorejob = Restore-AzureRmRecoveryServicesBackupItem -RecoveryPoint $RecoveryPoint -StorageAccountName $StorageAccount -StorageAccountResourceGroupName $ResourceGroupName
# .....
}
catch {}
}
}
# Because the parameters ResourceGroupName and StorageAccount have default values, you do not have to specify them
# in the call to the function unless the are different than the default values.
Restore-Disk -ResourceName "samplevm01","samplevm02" -RecoveryPoint $rp[0] -Verbose
If you want to run the powershell in powershell runbook, you can just pass the vm names in a string type and separated by a comma, like "vm1,vm2,vm3". Then in your runbook code, split the string to array, then in the foreach loop, operates with each vm.
A simple test in powershell runbook:
param([string]$ResourceName,[string]$StorageAccount)
#parse the string to an array
$vms = $ResourceName.split(',')
#implement your logic here
foreach($r in $vms)
{
#output the vm name
$r
}
#output the storage account
$StorageAccount
Pass the parameters and run:
For your code, you can follow the above steps, your code in runbook should look like below:
param([string]$ResourceName,[string]$StorageAccount)
$vms = $ResourceName.split(',')
foreach ($resource in $vms) {
try {
#.....
$resources = Get-AzureRmResource -ResourceGroupName "samplerg" -ResourceName $resource
$restorejob = Restore-AzureRmRecoveryServicesBackupItem -RecoveryPoint $rp[0] -StorageAccountName $StorageAccount -StorageAccountResourceGroupName "samplerg"
#....
}
catch {}
}

Resources