Clear an App Service instance and upload new content from a zip file - azure

On App Service, what's the best way of deploying new content from a zip file, such that it replaces any existing content?
Please note:
I am running on linux
I cannot use msdeploy
I cannot use git
I cannot use VSTS
It needs to be simple
It cant be prone to timing out
It has to be supported by all subscription levels of App Service
Commands should only return after their respective operation(s) have completed
I have access to ARM templates
Provided it isn't as difficult, I'm sure I could upload files to storage blobs
For more information, see this discussion here: https://github.com/projectkudu/kudu/issues/2367

There is a solution that consists in calling the ARM msdeploy provider to deploy a cloud hosted zip package. This requires no msdeploy on your client, so the fact that msdeploy technology is involved is mostly an implementation detail you can ignore.
There are a couple gotchas that I will call out at the end.
The steps are:
First, get your zip hosted in the cloud. e.g. I have a test one here you can play around with: https://davidebbostorage.blob.core.windows.net/arm/FunctionMsDeploy.zip (note that this zip uses special msdeploy packaging, but you can also use a plain old zip with just your files).
Then run the following command using cli 2.0, replacing your resource group, app name and zip url:
az resource update --resource-group MyRG --namespace Microsoft.Web --parent sites/MySite --resource-type Extensions --name MSDeploy --set properties.packageUri=https://davidebbostorage.blob.core.windows.net/arm/FunctionMsDeploy.zip --api-version 2015-08-01
This will result in the package getting deployed to your wwwroot, and any existing content that's not in the zip getting deleted. It's efficient as it won't touch any files that already exist and are identical to what's in the zip. So it's far faster than trying to clean out everything and unzipping clean (but results are identical).
Now a couple gotchas:
Due to what seems like a bug in CLI 2.0, I wasn't able to pass a URL that contains an equal sign, which rules out SAS URLs. I'll report that to them. For now, test the process with a public zip, like my test package above.
The command line is more complex than it should be. I will also ask the CLI team about this.

Related

az managedapp definition create: DownloadItemFromBlobFailed due to a failed connection

I want to create an Azure "Managed App" definition, in preparation for making an Azure Marketplace offering. I am following these MS instructions, and I had specifically been using this MS example managed app. There were was an error(s) in the documentation, which I posted to the MS team (along with my proposed fixes). Nevertheless, I did get the MS example working!
My next step was to replace the original MS sample deployment bundle...
https://raw.githubusercontent.com/Azure/azure-managedapp-samples/master/Managed%20Application%20Sample%20Packages/201-managed-storage-account/managedstorage.zip
...with my own deployment bundle...
https://github.com/brentarias/azureStaticEmpty/raw/master/baselinepocapp.zip
This didn't work. When issuing the az managedapp definition create command, I received the following error:
(DownloadItemFromBlobFailed) Download of the item from blob at 'https://github.com/brentarias/azureStaticEmpty/raw/master/baselinepocapp.zip' failed due to a failed connection.
Code: DownloadItemFromBlobFailed
Message: Download of the item from blob at 'https://github.com/brentarias/azureStaticEmpty/raw/master/baselinepocapp.zip' failed due to a failed connection.
It makes no sense to have a "connection" error, so I assumed that the REAL error was something inside of my deployment bundle. To test that theory, I copied the original MS sample bundle to a variety of places that I control, including Azure BLOB storage. One example location I placed the copied MS deployment file was here:
https://github.com/brentarias/azureStaticEmpty/raw/master/managedstorage.zip
When using this latter URL, I still received the same "connection" error.
In short, the only way for me to bypass the "connection" error is if I use the original sample MS deployment, from the original path that MS supplied. Incidentally, I also tried a variant URL of the original MS sample:
https://github.com/Azure/azure-managedapp-samples/raw/master/Managed%20Application%20Sample%20Packages/201-managed-storage-account/managedstorage.zip
Suddenly the deployment works! However, that location is still the original MS-owned repo "azure-managedapp-samples". This simply seems to confirm that if the deployment does not come from a MS-owned repo, I am then unable to make the deployment.
What am I doing wrong?
Update 2/3/2023
I finally found a way to make this work! When using an Azure storage account, simply having a publicly visible URL for the deployment bundle is insufficient. I need to have a "shared access signature" URL for that deployment bundle...and then the az managedapp definition create command works!
However, my overall question still is unanswered:
What are the valid file-share platforms that the az managedapp definition create supports? Besides github and Azure BLOB, what else?
What exact configuration do I need to make with a github raw link, before it is considered "kosher" by the managedapp definition create?

deploy each function in a separate Azure function app

my project has 3 Service bus and 2 HTTP triggers. (5 functions)
How to deploy each function in a separate Azure function app?
The easiest way is to copy the code of the trigger you created before and create a new function app with a single trigger, then put the code into it(Deploy function app must be based on function app, and the function app should correspond to the project on local.).
The more complicated method is, first make sure the structure of your function app(this needs to check the language. function app has two types, one type is a scripting language and another type needs to be compiled.) For this, you can have a check of this official doc:
https://learn.microsoft.com/en-us/azure/azure-functions/supported-languages
Go to the language you are using and search the folder structure(your deployment structure should like the 'folder structure' in the doc. What needs to pay attention to is for the language like C# and java, you need to deploy the compiled files. Azure can't identify the source files.) Then you just need to imitate the structure and deploy based on this structure.
'Deploy' operation is just a upload operation, so you just needs to upload the files in specific structure, then azure can identify it.
Finally, you can use zip deploy to deploy your function app(Or to say deploy a project, a structure that azure can run must first run success on local.).
az webapp deployment source config-zip --resource-group <group-name> --name <app-name> --src clouddrive/<filename>.zip
(Above command is been used by some Integrated Development Environment, such as Visual Studio.)
I suggest you to use the first way, because it is simpler.

How to automatically deploy a web job to Azure portal using Power shell

I have been checking for ways to deploy a web job to azure automatically using PowerShell. I saw some blogs that depict the steps and the following summarizes what I have tried
I build my application (ASP.NET Console Application) in release mode and Zipped the contents of bin/Release to a folder.
In PowerShell, I logged in with az login
Then I tried the following commmand
Invoke-WebRequest -Uri https://$applicationName.scm.azurewebsites.net/site/wwwroot/app_data/jobs/triggered/$webJobName ` -InFile $ZipFile -ContentType "application/zip" -Method Put
$ZipFile has the path to the folder I created on step 1.
The output I get is the following
Invoke-WebRequest : The page was not displayed because the request entity is too large
Please let me know if you know what the issue is or If you have any reference that would help.
Thanks in advance!
Thanks for pitching in everyone! Your input was helpful, however I would like to update the answer with the solution I found that was so easy and saved me so much time. I will like to update you on how I could successfully deploy the app service and web job in a single go. Its very easy and since it deploys web app and corresponding web jobs in a single go, this was the perfect solution for my scenario. Thanks to my colleague who helped me with this solution.
The following depicts the steps I had to go through.
Lets suppose that my app service in Azure is "appService1" and I want to create a triggered web job under appService1 that goes by the name "webJob1".
I followed zip-deployment with azure cli.
Publish your web application (For the app service) solution in release mode to get the files you will have to deploy. Let this folder be WebAppBuild.
Build your application (a console application in my case) that would serve as the web job for the app service in release mode.
Inside the published folder for the web application (for app service ie WebAppBuild in our example), add a folder with the following path
app_data\jobs\triggered\webJob1
(If you need more than one web jobs deployed, you can create more than one folders like webJob2, webJob3 etc)
Add the files you have in step 2 to this folder. This is basically the files needed for your web job
Zip the contents in a single folder that acts as your deployment folder for web app and web job
Go to powershell and run az login (works if you have installed azure cli, otherwise you will have to install it as well)
Log into your respective account with the prompt window
Run the following commands that sets run from package property to true for your web app and the second command is the actual deployment command
az webapp config appsettings set --resource-group <<resourceGroupName>> --name <<appServiceName>> --settings WEBSITE_RUN_FROM_PACKAGE="1" ;
az webapp deployment source config-zip --resource-group <<resourceGroupName>> --name <<appServiceName>> --src <<zipFilePath>>
Now login to your azure portal and navigate to your web app. Check under web jobs option and you will see that the web job has been created with the files you deployed.
For more help on starting, stopping, deleting the web job with azure cli, go through the following document.
Check here

download files in azure vm using fileuri

"fileUris": [
"https://files.blob.core.windows.net/extensions/test.sh"]
In an Azure scale set, does this part of extension download the file test.sh to the VM or call it directly from blob storage?
I'm assuming you are talking about the custom script extension for Azure virtual machines.
On its documentation page it reads:
The Custom Script Extension downloads and executes scripts on Azure
virtual machines. This extension is useful for post deployment
configuration, software installation, or any other configuration /
management task. Scripts can be downloaded from Azure storage or
GitHub, or provided to the Azure portal at extension run time. The
Custom Script extension integrates with Azure Resource Manager
templates, and can also be run using the Azure CLI, PowerShell, Azure
portal, or the Azure Virtual Machine REST API.
Highlighted are the relevant parts.
The extension work so that it first downloads and then executes the scripts you provide for it.
Edit: If you need to deploy some external resources you can upload them to your GitHub account or an Azure Storage Blob and download/read them from there.
See for example this answer for more details on how to download a file from a blob.
Invoke-WebRequest -Uri https://jasondisk2.blob.core.windows.net/msi/01.PNG -outfile 'C:\'
If you simply want to read the json file, then you can do as described here in this other answer.
$response = Invoke-RestMethod -Uri "https://yadayada:8080/bla"
$response.flag
Note: Invoke-RestMethod automatically converts the json response to a psobject.
As for the working directory. The extension downloads its files into the following directory
C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.*\Downloads\<n>
where <n> is a decimal integer which may change between executions of the extension. The 1.* value matches the actual, current typeHandlerVersion value of the extension.
For example, the actual directory could be
C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.8\Downloads\2
See the troubleshooting section in the Azure documentation for more information.
Alternatively, for a Linux based system the path is similar to
/var/lib/waagent/custom-script/download/0/
see this page for more information.

In Azure, how do I deploy functionapp code without using git?

I created a Resource Manager template which has the Resources to run a function app basically using the default template for this purpose and I can manually copy files to my File Storage under sites\wwwroot and when I curl the functionapp it works.
But what I'm wondering is, what is the right way to deploy a bunch of files to update the actual functionapp, but not using git. I can see some examples of how to use git but my problem is that I want to have all my functions in a single repo not a bunch of smaller repos (I want a monorepo).
In Azure you just upload your code in a .gz file to S3 then when creating the lambda you give it a path to the zip. And then later there is a simple API that you can call to push up a new zip and presto.
What is the equivalent API in azure to just give it a zip and have it unpack the files in the right directory?
EDIT:
I managed to figure it out finally, the top answer was essentially right but there were a few extra steps I had to figure out so I'll put those here.
The specific doc on curl is here. My issue thread with the team is here.
The actual curl call I used is this:
$ curl -XPUT --data-binary #index.js.zip "https://abc:xyz#ugh.scm.azurewebsites.net/api/zip/site/wwwroot/hello"
Notes on this:
You must use --data-binary, -d results in a bad payload
To create the zip in bash I used: $ zip index.js.zip index.js
abc:xyz is the deployment username and password
The right path to send is site/wwwroot/hello where hello is the name of the function.
You can set the username and password in the azure portal UI (documented here) but you can also set it with the azure-cli like so:
$ az login
$ az webapp deployment user set --user-name abc --password xyz
And that was the trick, once you've setup the deployment credentials you can use them in basic auth to call the kudu api.
Using Rest API to deploy Function App is also allowed in Azure. We could use the following Rest API to do that. We could get more detail info from Kudu REST API. We could get the ftp use and password from publish file, about how to publish file, please refer to another SO thread.
PUT https://{user}:{password}#{FunctionAppname}.scm.azurewebsites.net/api/zip/{path} # example path:site/wwwroot

Resources