Azure Publish Web App with Resource Manager in Powershell - azure

I am trying to publish a Web App package on an App Service on Azure.
I need to crate a Powershell script to run from the Cloud Shell, in order to publish the package.
I wrote the following code
Import-AzurePublishSettingsFile - $WebApp.PublishProfilePath
Publish-AzureWebsiteProject -Package $WebApp.ZipPath -Name $WebApp.WebAppName
This code works on my local machine, but not in the Cloud Shell where I get the following errors:
Import-AzurePublishSettingsFile : The term 'Import-AzurePublishSettingsFile'
is not recognized as the name of a cmdlet, function, script file, or
operable program.
Publish-AzureWebsiteProject : The term 'Publish-AzureWebsiteProject' is not
recognized as the name of a cmdlet, function, script file, or operable
program.
I guess these errors are caused by the fact that these cmdlets comes from the old Classic Manager, which is not available in the Cloud Shell.
Basically I need to publish a Web App package from the Cloud Shell with a script. How can I achieve that? Do I have other options?

Steps and commands you are following are for ASM (classic) Website deployment.
Could Shell only have ARM modules and does not have modules that have those command.
Check link below out to see if that works for you.
https://learn.microsoft.com/en-us/azure/app-service/app-service-deploy-zip
Hope this helps.

Starting from the documentation link suggested by Hannel, I finally solved by invoking REST API with Powershell. With Azure CLI is much easier, but I have a more complex script already written with Powershell.
Final code is this:
# Getting credentials
$creds = Invoke-AzureRmResourceAction -ResourceGroupName $resourceGroupName `
-ResourceType Microsoft.Web/sites/config `
-ResourceName "$($WebApp.WebAppName)/publishingcredentials" `
-Action list `
-ApiVersion 2015-08-01 `
-Force
$username = $creds.Properties.PublishingUserName
$password = $creds.Properties.PublishingPassword
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username, $password)))
# Deploy Web App
Invoke-RestMethod -Uri "https://$($WebApp.WebAppName).scm.azurewebsites.net/api/zipdeploy" `
-Headers #{Authorization = ("Basic {0}" -f $base64AuthInfo)} `
-Method POST `
-InFile $WebApp.ZipPath `
-ContentType "multipart/form-data" `
-UseBasicParsing `
-ErrorAction Stop | Out-Null

Related

Accessing Azure Storage Table from Azure Function App (PowerShell)

I want to use the following code in a Azure Function powershell app:
Add-AzTableRow `
-table outputTable`
-partitionKey $partitionKey `
-rowKey ($record.id) -property #{"userId" = "001";}
I'm using this documentation as a guide. However, this guide uses Install-Module AzTable. Since I am using a Function App to run this code on a timer, I can't install the module on run time. I've followed this question/answer. I've added this to `requirements.psd1':
#{
# For latest supported version, go to 'https://www.powershellgallery.com/packages/Az'.
# To use the Az module in your function app, please uncomment the line below.
#'Az' = '8.*'
AzTable = '2.*'
}
When I run the code I get the following error:
[Error] ERROR: The 'Add-AzTableRow' command was found in the module 'AzTable', but the module could not be loaded. For more information, run 'Import-Module AzTable'.
Could someone please give me some insight on what I'm doing wrong? I want to be able to update and query the table from the Function App without any user input.
Edit:
I have added 'Az' = '8.*' and 'AzTable' = '2.*'. I let the function install the resource by running and waiting. I'm now getting the error:
[Error] ERROR: The term 'Add-AzTableRow' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
I'm not sure why I'm getting this error because Add-AzTableRow is apart if the AzTable module.
The AzTable module requires the Az Module:
It requires latest PowerShell Az module installed
https://www.powershellgallery.com/packages/AzTable/2.0.1
But currently the install of the Az module is disabled in your requirements.psd1:
Remove # from #'Az' = '8.*' = 'Az' = '8.*'
After that the machine behind the function will install the required module and the code will be able to load it/acces the functions.
Note if you "activate" a module the first time, run your code and maybe you still get the error messge -> script got started before module install completed... so simply wait some minutes and retry.
Run VS Code as an Administrator. Open the Azure PowerShell Functions Project in the VS Code.
In the VS Code Terminal of project Workspace/Path, run the below cmdlets one by one:
Install-Module Az
Import-Module Az
Install-Module AzTable -Force
Import-Module AzTable
Created Azure Functions PowerShell HTTP Trigger Function and written the code with the reference of this MS Doc:
run.ps1
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
# Interact with query parameters or the body of the request.
Connect-AzAccount -Tenant '<Tenant-Id>' -SubscriptionId '<Subscription-Id>'
Set-AzContext -Subscription "<Subscription-Id>"
$resourceGroup = "HariTestRG"
$storageAccountName ="store365rvi7b3lmoq"
$storageAccount=Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $storageAccountName
$ctx = $storageAccount.Context
Write-Host $ctx.ConnectionString
$tableName = "pshkrishtesttable"
$cloudTable = (Get-AzStorageTable –Name $tableName –Context $ctx).CloudTable
Write-Host $cloudTable.Name
$partitionKey1 = "partition2"
Write-Host "Partition Key"
# add a row
Add-AzTableRow `
-table $cloudTable `
-partitionKey $partitionKey1 `
-rowKey ("India") -property #{"username"="Jashu";"userid"=598}
Write-Host "Table Row Added"
$TableRows = Get-AzTableRow -table $cloudTable
Write-Host $TableRows | Format-Table
$body = "Hello Krishna, This HTTP triggered function executed successfully."
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = [HttpStatusCode]::OK
Body = $body
})
requirements.psd1:
#{
'Az' = '8.*'
'Az.Storage' = '4.10.0'
'AzTable' = '2.1.0'
}
Result:
Note: If you are running the PowerShell Function with these modules for the first time, it will take some time during the runtime/execution.

How do you configuring Azure VMs with .NET 5.0 from the command line?

I'm setting up some virtual machines to run my service. There may be several, so I'm trying to automate the process. I've got a PowerShell script that successfully build the virtual machine, but now I want to install the dependent software that my .NET Core Web Application requires in the same script.
The first dependency I want to install is .NET 5.0 Runtime. I've done this many times from the browser, but now I want to commit this to a script that runs after the VM has been built.
Test locally or on a test VM by installing using the dotnet-install-script and finalize the parameters. Then use Set-AzVMExtension to install that script using custom script extension. The code would look like this (not tested)
$Command = "&powershell -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) <additional install-script args>"
$Settings = #{"commandToExecute" = "Powershell $Command";};
Set-AzVMExtension `
-ResourceGroupName "ResourceGroupName" `
-Location "Location" `
-VMName "VirtualMachineName" `
-Name "ExtensionName" `
-Publisher "Contoso.Compute" `
-Type "CustomScriptExtension" `
-TypeHandlerVersion "1.1" `
-Settings $Settings
Full details and schema of settings custom-script-windows
You can also use Set-AzureVMCustomScriptExtension for running custom scripts.
As #amit_g recommended, you can use Azure VM run command functionality to run install .net with scripts by PowerShell directly to meet your requirement.
This seems to work pretty well:
Invoke-AzureRmVMRunCommand -ResourceGroupName "$resourceGroupName" -Name "$machineName" -CommandId "RunPowerShellScript" -ScriptPath "configureMachine.ps1" -Parameter #{"machineName" = "$machineName"}
The contents of the Powershell script look something like this:
# The name of the VM is passed in as the first parameter.
param ($machineName)
if ($machineName -eq $null)
{
Write-Host "Usage: configureMachine -machineName <machineName>";
Exit;
}
# Download the agent installation files.
$agentZip="agent.zip";
Invoke-WebRequest -Uri "https://vstsagentpackage.azureedge.net/agent/2.181.1/vsts-agent-win-x64-2.181.1.zip" -OutFile $agentZip
# Unpack them.
$agentDirectory="$env:SystemDrive\azagent";
Add-Type -AssemblyName System.IO.Compression.FileSystem;
[System.IO.Compression.ZipFile]::ExtractToDirectory($agentZip, $agentDirectory);
# Configure the machine to work as a DevOps Agent.
&"$agentDirectory\config.cmd" --unattended --deploymentgroup --deploymentgroupname "Production" --agent "$machineName" --runasservice --work "_work" --url "https://dev.azure.com/theta-rex/" --projectname "openbook" --auth PAT --token te64yuv36tina2rvc2lsvwcsvctpwomiewz5fxihcubbdzaasoka
# Remove the Agent Zip files when installation is complete.
Remove-Item $agentZip;
# Download and install .NET 5.0
Invoke-WebRequest -Uri "https://dot.net/v1/dotnet-install.ps1" -OutFile "dotnet-install.ps1"
&"./dotnet-install.ps1" -Channel 5.0 -Runtime aspnetcore -InstallDir "C:\Program Files\dotnet"
The end result is a machine configured to participate in Azure DevOps and ASP.NET 5.0.

How do I deploy to Azure App Service with PowerShell (az module)?

I want to deploy app services from Powershell.
I would like to use only publish profile (no password for azure account).
I tried FTP service, but sometimes files are blocked by running users.
I think I have to stop app service.
There is powershell command like:
Publish-AzWebApp
However first I need login with:
Connect-AzAccount
and pass credentials what I want to avoid.
There is any way to call Publish-AzWebApp based on only publish profile (no login by account)?
Connect-AzAccount has other options to login (token or certificate).
Unfortunately I don't know how to generate it.
BTW There was a topic about it:
How do I deploy to Azure App Service with PowerShell?
But it is old and now module "az" is recommended.
There is any way to call Publish-AzWebApp based on only publish profile (no login by account)?
No, you can't. If you want to use the Publish-AzWebApp , you always need to login with Connect-AzAccount, whatever the parameters you use, examples here.
If you want to use powershell to deploy the web app based on only publish profile, the workaround is to use Kudu API via powershell.
$username = "`$webappname"
$password = "xxxxxxx"
# Note that the $username here should look like `SomeUserName`, and **not** `SomeSite\SomeUserName`
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username, $password)))
$userAgent = "powershell/1.0"
$apiUrl = "https://joywebapp.scm.azurewebsites.net/api/zipdeploy"
$filePath = "C:\Users\joyw\Desktop\testdep.zip"
Invoke-RestMethod -Uri $apiUrl -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method POST -InFile $filePath -ContentType "multipart/form-data"
You may refer to this tutorial: https://learn.microsoft.com/en-us/powershell/azure/authenticate-azureps?view=azps-2.5.0#sign-in-with-a-service-principal-
Here is the step by step process of deploying and publishing an Azure app service with PowerShell (PS) using newly recommended Az module. You'll have to install Azure CLI before running the scripts:
$subscription = 'Visual Studio Enterprise – MPN' #Change it as per your Azure subscription
$location = 'Central US' #Change it according to the location where you want to host your web app
$resourceGroup = 'MyWebAppResourceGroup'
$ErrorActionPreference = "Stop" #this ensures that script stops executing at first error in the script.
Write-host "Installing nuget package provider"
Install-PackageProvider -Name NuGet -Scope CurrentUser -MinimumVersion 2.8.5.201 -Force
Write-Host "Setting Power Shell gallery"
Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted
Write-Host "Installing missing PowerShell modules required for running this script.."
if ((Get-InstalledModule -Name "Az.Accounts" -ErrorAction SilentlyContinue) -eq $null) {
Write-Host "Az.Accounts module missing. Now installing..."
Install-Module -Name Az.Accounts -Scope CurrentUser
}
if ((Get-InstalledModule -Name "Az.Websites" -ErrorAction SilentlyContinue) -eq $null) {
Write-Host "Az.Websites module missing. Now installing .."
Install-Module -Name Az.Websites -Scope CurrentUser
}
Write-Host "Installing PowerShell modules completed."
Write-Host "Staring to import PowerShell modules in current session...."
Import-Module Az.websites
Write-Host "Importing PowerShell modules completed."
#This is required due to an issue due to which PowerShell fails to connect with online resources. This issue is machine specific. So you can comment it if not required.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Write-Host "Connecting to Azure account..."
Connect-AzAccount
Write-Host "Setting subscription for current session..."
az account set --subscription $subscription
Write-Host "Creating resource group..."
az group create --name $resourceGroup --location $location
$webAppName="WelcomeCloudApp"
$appServicePlan="WelcomeCloudAppServicePlan"
Write-Host "Creating WebApp Service plan..."
New-AzAppServicePlan -Name $appServicePlan -ResourceGroupName $resourceGroup -Location $location -Tier 'Free' #-Debug
Write-Host "Creating WebApp..."
New-AzWebApp -Name $webAppName -Location $location -AppServicePlan $appServicePlan -ResourceGroupName $resourceGroup
Write-Host "Publishing WebApp..."
Publish-AzWebApp -ResourceGroupName $resourceGroup -Name $webAppName -ArchivePath WelcomeCloudAppService.zip
Write-Host "Finished installing your web app. Bye!"

Azure's New-AzureRmHDInsightCluster command does not accept documented ComponentVersion option

According to MS's docs for New-AzureRmHDInsightCluster,
it should accept -ComponentVersion as an option:
$httpCredential = New-Object System.Management.Automation.PSCredential ($httpUserName, $clusterpassword)
$sparkConfig = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"
$sparkConfig.Add("spark", "2.1")
New-AzureRmHDInsightCluster `
-ClusterName mycluster `
-ComponentVersion $sparkConfig `
-ClusterSizeInNodes 4 `
-HttpCredential $httpCredential `
-Location "Central US" `
-OSType Linux `
-ResourceGroupName tstcluster
However, this command results in:
##[error]A parameter cannot be found that matches parameter name 'ComponentVersion'.
Is there a way to select the Spark version required? We used to use:
Add-AzureRmHDInsightComponentVersion -Config $config -ComponentName "Spark" -ComponentVersion "2.1"
But that's now rejected:
##[error]The term 'Add-AzureRmHDInsightComponentVersion' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
EDIT:
A couple of factors that were key to solving this: First, this script is run by an Azure PowerShell Script task in an Azure Dev Ops pipeline. Second, the PowerShell version used to run this script was 1.*.
Try the command below, it works fine on my side. Make sure you have installed the AzureRM.HDInsight powershell module, you could check it with Get-Module AzureRM.HDInsight.
Sample command:
$httpUserName = "joyhd"
$clusterpassword = ConvertTo-SecureString "<password>" -AsPlainText -Force
$httpCredential = New-Object System.Management.Automation.PSCredential($httpUserName, $clusterpassword)
$SshCredential = New-Object System.Management.Automation.PSCredential($httpUserName, $clusterpassword)
$storageAccountName = "<storageAccountName>"
$storageAccountKey = "xxxxxxx"
$storageContainer = "testhd"
New-AzureRmHDInsightClusterConfig `
| Add-AzureRmHDInsightComponentVersion `
-ComponentName "Spark" `
-ComponentVersion "2.1" `
| New-AzureRmHDInsightCluster `
-ClusterName joytesthd `
-ClusterType "Spark" `
-ClusterSizeInNodes 4 `
-HttpCredential $httpCredential `
-Location "eastus" `
-OSType Linux `
-ResourceGroupName joywebapp `
-DefaultStorageAccountName "$storageAccountName.blob.core.windows.net" `
-DefaultStorageAccountKey $storageAccountKey `
-DefaultStorageContainer $storageContainer `
-SshCredential $SshCredential
Result:
MS was not able to explain why a script that worked in Azure Dev Ops (then VSTS) stopped working. That is, why Add-AzureRmHDInsightComponentVersion was supported in January 2018 but not in September of that same year.
Their solution was to select the latest version of PowerShell available in a pipeline (3.*) and set the Preferred Azure PowerShell Version to 3.8.0.
Making those changes made the existing script workable again.

Deploy to azure functions using powershell

Is there any way, I can deploy to azure functions using powershell scripts? CI will not work for us because we use octopus deploy to deploy to all of our production services. So it would be beneficial if there is a way to deploy using powershell scripts.
Thanks!
You can deploy functions to Azure using the Kudu REST API. You can also see some code/samples of doing this in our templates repository. In this code sample, you can see how our test script calls out to the Kudu Rest apis to deploy a zip to the Function App.
The folder structure for functions is a function per folder. You need to deploy your Function folders to ./site/wwwroot on the Function App. You also need to add any app settings which might contain your secrets if you add any new bindings between updates.
The PowerShell code would look something along the lines of:
$apiUrl = $config.scmEndpoint + "/api/zip/"
if ($destinationPath)
{
$apiUrl = $apiUrl + $destinationPath
}
$response = Invoke-RestMethod -Uri $apiUrl -Headers #{Authorization=("Basic {0}" -f $config.authInfo)} -Method PUT -InFile $zipFilePath -ContentType "multipart/form-data"
Just in case there are people like me who need step by step solutions. Here is the procedure to deploy azure functions using powershell (non ARM way)
Create an azure function with the following structure
myFunctionName(Folder)
|
|_ function.json (contains info on input, output, trigger)
|_ run.csx (contains code)
|_ [OPTIONAL] project.json (for nuget packages)
|_ [OPTIONAL] bin(Folder)
|_ all custom DLLs go in this folder
Create a zip of the myFunctionName folder - let's name it my.zip. Make sure that after zipping my.zip contains the myFunctionName folder and all its contents
Find your publish profile username and password as described here, namely
$creds = Invoke-AzureRmResourceAction -ResourceGroupName YourResourceGroup -ResourceType Microsoft.Web/sites/config -ResourceName YourWebApp/publishingcredentials -Action list -ApiVersion 2015-08-01 -Force
$username = $creds.Properties.PublishingUserName
$password = $creds.Properties.PublishingPassword
and then invoke the Kudu REST API using powershell as follows
$username = '<publish username>' #IMPORTANT: use single quotes as username may contain $
$password = "<publish password>"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$password)))
$apiUrl = "https://<yourFunctionApp>.scm.azurewebsites.net/api/zip/site/wwwroot"
$filePath = "<yourFunctionName>.zip"
Invoke-RestMethod -Uri $apiUrl -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Method PUT -InFile $filePath -ContentType "multipart/form-data"
Go to <yourFunctionApp>.scm.azurewebsites.net -> Debug menu at the top -> CMD. In the page that appears, navigate to site -> wwwroot. You should see the contents of your zip file extracted there and you can also verify that your azure function is available in the azure portal.
REFERENCES
https://github.com/projectkudu/kudu/wiki/REST-API#sample-of-using-rest-api-with-powershell
http://markheath.net/post/deploy-azure-functions-kudu-powershell
In addition to what Chris describes, there is a first class ARM API you can use to deploy functions. Here is what it looks like in PowerShell:
Function DeployHttpTriggerFunction($ResourceGroupName, $SiteName, $FunctionName, $CodeFile, $TestData)
{
$FileContent = "$(Get-Content -Path $CodeFile -Raw)"
$props = #{
config = #{
bindings = #(
#{
type = "httpTrigger"
direction = "in"
webHookType = ""
name = "req"
}
#{
type = "http"
direction = "out"
name = "res"
}
)
}
files = #{
"index.js" = $FileContent
}
test_data = $TestData
}
New-AzureRmResource -ResourceGroupName $ResourceGroupName -ResourceType Microsoft.Web/sites/functions -ResourceName $SiteName/$FunctionName -PropertyObject $props -ApiVersion 2015-08-01 -Force
}
See https://github.com/projectkudu/kudu/wiki/Functions-API for information about the underlying API.
You can also use Azure CLI 2.0 + Azure Function CLI to deploy Azure functions form commandline/powershell
Azure CLI API can be used to provision a function app, using command
az functionapp create --name $functionappName --resource-group $resourceGroup --storage-account $storageAccountName --consumption-plan-location $consumptionPlanLocation
And apply application setting
az functionapp config appsettings set --name $functionappName --resource-group $resourceGroup --settings "test=value"
And Azure Function CLI api can be used to deploy the functions you have
func azure functionapp publish <azurefunctionapp>
Handy tools!
In addition to all of the above, we have released a Preview module for Azure Functions (https://www.powershellgallery.com/packages/Az.Functions/0.0.1-preview).
Currently, this module contains cmdlets to manged function apps and function app plans. I have opened an issue to request creating a cmdlet to deploy a function app. If you are interested in this feature, please vote up at https://github.com/Azure/azure-powershell/issues/10966.
To install the Azure Functions (Az.Functions) module, run the following command from the latest version of psws which can be downloaded at https://github.com/PowerShell/PowerShell/releases.
Install-Module -Name Az.Functions -AllowPrerelease
Please give it a try and send us feedback at https://github.com/Azure/azure-powershell/issues. When opening an issue, please make sure [Az.Functions] is included in the title.
Cheers,
Francisco

Resources