use Invoke-AzVMRunCommand -Params - azure

I am trying to use the command like so:
a = 345
name = "myVM"
Invoke-AzVMRunCommand -ResourceGroupName $RGName -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath $FileName -Parameter #{"b" = "a"; "test" = "name"}
the script in the file isn't really important I am just trying to use params inside of it with values of params from the outside. If I put "b" = 345 it works but with the outside param (a), it doesn't so I wanted to know how to do it.
it does execute the script but ignores the commands using these params.
for reference the script is something like this:
New-Item -Path "." -Name "index.html" -ItemType "file" -Value $b
New-Item -Path "." -Name $test -ItemType "file" -Value "3333333"

We use Invoke-AzVMRunCommand to Invoke a run command on the VM. And the -Parameter is used to run the command parameter.
The the type for -Parameter is Hashtable, which maps keys to values. Any non-null object can be used as a key or as a value.
Invoke command is more like a batch script, so when we want to pass a pre-defined variable we have to use the $ symbol without any double quotes (""). So you can solve your problem by following the code snippet below.
#Example
a = 345
name = "myVM"
Invoke-AzVMRunCommand -ResourceGroupName $RGName -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath $FileName -Parameter #{"b" = $a; "test" = $name}
Read this Invoke-AzVMRunCommand document and about_Hash_Tables document for more information.

Invoke-AzVMRunCommand -ResourceGroupName $RGName -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath $FileName -Parameter #{"b" = $a; "test" = $name}
It don't work. The same problem.
I have the script which create VM in azure:
$password = ConvertTo-SecureString -String "Qwerty123456" -AsPlainText
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $password
$x = Get-Random 10000 -Minimum 10
$location = "East US"
$rgname = "testVM"+$x
$VMName = "vm1"
# Create Resource group
New-AzResourceGroup -name $rgname -Location $location
# Create VM, vnet, publicIP, port 3389
New-AzVM -ResourceGroupName $rgname `
-Location $location `
-Name "verdyshtest" `
-VirtualNetworkName "virtnet" `
-SubnetName 'verdyshnetwork' `
-PublicIpAddressName "verdyshpublicIP" `
-Image Win2019Datacenter `
-OpenPorts 3389 `
-Credential $cred
# Script only running after deploy
Invoke-AzVMRunCommand -ResourceGroupName $rgname -VMName $VMName -CommandId RunPowerShellScript -ScriptPath '.\2 Install app on VM.ps1'
In last count it can't to execute 'invoke-azvmruncommand', because of variable in parameters.
But in New-AzVM cmdlet variables works well.
Had a error:
error

Related

Azure ARM template script error when creating certificate for apex domain

Really scratching my head on this one, I keep getting the error below:
New-AzureRmResourceGroupDeployment : A parameter cannot be found that matches parameter name 'SubjectName'.
At azure_cli_-_create_cert.ps1:12 char:80
for the Azure ARM template script below:
$subscription = ""
$resourceGroupName = ""
$appServicePlanName = ""
$subjectName = ""
Set-AzureRmContext -SubscriptionId $subscription
$appServicePlan = Get-AzureRmResource `
| Where-Object {$_.ResourceGroupName -eq $resourceGroupName} `
| Where-Object {$_.Name -eq $appServicePlanName}
New-AzureRMResourceGroupDeployment -ResourceGroupName $resourceGroupName -SubjectName $subjectName -AppServicePlanName $appServicePlanName -Location $appServicePlan.Location -TemplateFile "CreateHttpFreeCert.json"
Does anyone know why this is?
I am running the script in a windows powershell script (i.e. .ps1 script).
It seems like you need to supply the parameters for your template in as a JSON file using -TemplateParameterFile or -TemplateParameterObject
https://learn.microsoft.com/en-us/powershell/module/azurerm.resources/new-azurermresourcegroupdeployment?view=azurermps-6.13.0#example-1--use-a-custom-template-and-parameter-file-to-create-a-deployment

AzCosmosDBSqlContainer : "Object reference not set to an instance of an object."

I am using AzCosmosDBSqlContainer to check details of a CosmosDB (SQL api) container in PowerShell; I am getting this error
Object reference not set to an instance of an object
However Get-AzCosmosDBAccount and Get-AzCosmosDBSqlDatabase commands are working fine.
Can someone help me with this?
Command used:
$ResourceGroup="MyResourceGroup"
$CDBAccountName="mycosmosaccount"
$dbname="myDatabase"
$containername="MyContainer"
$cosmosaccount=Get-AzCosmosDBAccount -ResourceGroupName $ResourceGroup -Name $CDBAccountName
$cosmosdbname=Get-AzCosmosDBSqlDatabase -AccountName $cosmosaccount.Name -ResourceGroupName $ResourceGroup -Name $dbname
Get-AzCosmosDBSqlContainer -ResourceGroupName $ResourceGroup -AccountName $cosmosaccount.Name -DatabaseName $cosmosdbname.Name -Name $containername
I found a workaround after getting an update from Microsoft team.
https://github.com/Azure/azure-powershell/issues/11381
This issue is going to be fixed in upcoming version of Az.CosmosDB 0.1.4
Workaround:
Replace "my***Name" with your own values
$resourceGroupName = "myResourceGroupName"
$accountName = "myAccountName"
$databaseName = "mYDatabaseName"
$containerName = "myContainerName"
$apiVersion = "2020-03-01"
$databaseResourceName = $accountName + "/" + $databaseName
$containerResourceName = $databaseResourceName + "/" + $containerName
$containerResourceType = "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
Write-Host "List containers in the database"
Get-AzResource -ResourceType $containerResourceType -ApiVersion $apiVersion
-ResourceGroupName $resourceGroupName -Name $databaseResourceName
Write-Host "Show specified container"
Get-AzResource -ResourceType $containerResourceType -ApiVersion $apiVersion
-ResourceGroupName $resourceGroupName -Name $containerResourceName

How to initialize a disk after I append a data disk to VM automatucally?

Based on this doc :
https://learn.microsoft.com/en-us/azure/virtual-machines/windows/attach-managed-disk-portal I can append a data disk to my windows Azure VMs and initialize the disk manually by login to the VM. Everything works for me.
BUT it is not enough as I want to make the whole process automatually by code. Could you please give me some code sample or guide about it ? Thanks!
#ShirazBhaiji provided a helpful doc that will meet your requirement, but there is a new feature that you can run commands on Azure VMs directly, no need to enable WinRM.
Just try the Powershell below :
This is the command to init a data disk in windows :
$disks = Get-Disk | Where partitionstyle -eq 'raw' | sort number
$letters = 70..89 | ForEach-Object { [char]$_ }
$count = 0
$labels = "data1","data2"
foreach ($disk in $disks) {
$driveLetter = $letters[$count].ToString()
$disk |
Initialize-Disk -PartitionStyle MBR -PassThru |
New-Partition -UseMaximumSize -DriveLetter $driveLetter |
Format-Volume -FileSystem NTFS -NewFileSystemLabel $labels[$count] -Confirm:$false -Force
$count++
}
Save it as a .ps1 file.
Use this command to append a disk and run the above command directly :
$vm = Get-AzVM -Name <your VM name> -ResourceGroupName <your vm resource group name>
$dataDiskName = $vm.Name + '_datadisk1'
$diskConfig = New-AzDiskConfig -SkuName 'Premium_LRS' -Location $vm.Location -CreateOption Empty -DiskSizeGB 128 -Zone 1
$dataDisk1 = New-AzDisk -DiskName $dataDiskName -Disk $diskConfig -ResourceGroupName $vm.ResourceGroupName
Add-AzVMDataDisk -VM $vm -Name $dataDiskName -CreateOption Attach -ManagedDiskId $dataDisk1.Id -Lun 1
Update-AzVM -VM $vm -ResourceGroupName $vm.ResourceGroupName
Invoke-AzVMRunCommand -VM $vm -CommandId 'RunPowerShellScript' -ScriptPath "<path of the previous .ps1 file>"
Result :
Hope it helps!
You can do this using powershell, you need to have windows remote management enabled on the VM.
Example scripts can be found here:
https://learn.microsoft.com/en-us/azure/virtual-machines/windows/attach-disk-ps

How do I translate a set of powershell commands into a script that I can run when I want?

I have a set of commands I can use in azure powershell. The commands create a resource group, app service, etc. I want to bundle them up so that I can just type one command into a terminal and run all of the deployment in one go.
# Ask user for work item id
$workItemId = Read-Host -Prompt "Enter the Work Item ID"
# Set Variables
$appdirectory="C:\Users\Charles\Desktop\Timesheet App\Discover\Client\build"
$webappname="discoverTest$workItemId"
$location="West Europe"
# Create a resource group.
New-AzResourceGroup -Name discoverTest$workItemId -Location $location
# Create an App Service plan in `Free` tier.
New-AzAppServicePlan -Name $webappname -Location $location `
-ResourceGroupName discoverTest$workItemId -Tier Free
# Create a web app.
New-AzWebApp -Name $webappname -Location $location -AppServicePlan $webappname `
-ResourceGroupName discoverTest$workItemId
# Get publishing profile for the web app
$xml = [xml](Get-AzWebAppPublishingProfile -Name $webappname `
-ResourceGroupName discoverTest$workItemId `
-OutputFile null)
# Extract connection information from publishing profile
$username = $xml.SelectNodes("//publishProfile[#publishMethod=`"FTP`"]/#userName").value
$password = $xml.SelectNodes("//publishProfile[#publishMethod=`"FTP`"]/#userPWD").value
$url = $xml.SelectNodes("//publishProfile[#publishMethod=`"FTP`"]/#publishUrl").value
# Upload files recursively
Set-Location $appdirectory
$webclient = New-Object -TypeName System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$files = Get-ChildItem -Path $appdirectory -Recurse #Removed IsContainer condition
foreach ($file in $files)
{
$relativepath = (Resolve-Path -Path $file.FullName -Relative).Replace(".\", "").Replace('\', '/')
$uri = New-Object System.Uri("$url/$relativepath")
if($file.PSIsContainer)
{
$uri.AbsolutePath + "is Directory"
$ftprequest = [System.Net.FtpWebRequest]::Create($uri);
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::MakeDirectory
$ftprequest.UseBinary = $true
$ftprequest.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$response = $ftprequest.GetResponse();
$response.StatusDescription
continue
}
"Uploading to " + $uri.AbsoluteUri + " from "+ $file.FullName
$webclient.UploadFile($uri, $file.FullName)
}
$webclient.Dispose()
$workItemId = Read-Host -Prompt "Enter the Work Item ID"
Remove-AzResourceGroup -Name "discoverTest$workItemId" -Force
# print variable
Write-Host $variable
I want to be able to run a single command and have the full deployment process executed.
There are two ways to realize your needs, as below.
Extract all parameters you used in these PowerShell command lines as the arguments for a PowerShell Script <your-script-name>.ps1 which includes all same commands as yours. Please refer to the existing SO thread How to handle command-line arguments in PowerShell to know how to do. Then, you just need to run <your-script-name>.ps1 with these arguments in a terminal which had pre-installed Azure PowerShell Module.
Follow the blog Four ways to package a non-GUI PowerShell script as an executable file to make an executable file with the current set of commands.
Normally, I think the first way is better and be recommended.

Create 2 publicIPs and assign to nics

I am trying to create 2 public ips and then assign one each to nics
for($i=1; $i -lt 3; $i++)
{
New-AzPublicIpAddress -Name "publicIP$i" -ResourceGroupName $resourceGroup.ResourceGroupName -Location $location -AllocationMethod Dynamic
New-AzNetworkInterface -Name "nic$i" -ResourceGroupName $resourcegroup.ResourceGroupName -Location $location -SubnetId $vnet.subnets[0].Id -PublicIpAddressId "publicIP$i.Id" -NetworkSecurityGroupId $nsg.Id
}
I want to assign the output of new-azPublicIpAddress to a variable and then use that variable's id to assign to -pulicIpAddressId.
like this $pip$i = New-AzPublicIpAddress -Name "publicIP$i" -ResourceGroupName $resourceGroup.ResourceGroupName -Location $location -AllocationMethod Dynamic but this does not work
You cannot set a variable with a '$' inside it.
The following is a correct sample.
$pip = New-AzPublicIpAddress -Name "publicIP$i" -ResourceGroupName $resourceGroup.ResourceGroupName -Location $location -AllocationMethod Dynamic
Considering your requirement, I suggest you use an array:
$pipArr = New-Object 'Object[]' 2;
$nicArr = New-Object 'Object[]' 2;
for($i=0; $i -lt 2; $i++)
{
$pipArr[$i] = New-AzPublicIpAddress -Name "publicIP$i" -ResourceGroupName $resourceGroup.ResourceGroupName -Location $location -AllocationMethod Dynamic
$nicArr[$i] = New-AzNetworkInterface -Name "nic$i" -ResourceGroupName $resourcegroup.ResourceGroupName -Location $location -SubnetId $vnet.subnets[0].Id -PublicIpAddressId $pipArr[$i].Id -NetworkSecurityGroupId $nsg.Id
}
In this way, you can get your first public IP with "$pipArr[0]". As it is an array, you can use index with it.
As Jack requested, here's another way of doing the same is the following:
Set-Variable "pip$i" -Value (New-AzPublicIpAddress -Name "publicIP$i" -ResourceGroupName $resourceGroup.ResourceGroupName -Location $location -AllocationMethod Dynamic)
then you can use Get-Variable to get data from the variable:
Get-Variable "pip$i" | Select -ExpandProperty Value
If you just want to have $ inside the variable you can do this:
${pip$i} = something
this will instanciate new variable with the name pip$i, and you could retrieve it similarly as well:
Do-something -Input ${pip$i}

Resources