Deploy To Azure (Platform As A Service) Websites Using Kudu REST APIs

Introduction

Azure (Platform-as-a-Service) website provides limited control to developers to play with the underlying Virtual Machine File System like any other Platform as a Service offering. However developers at times need a greater control over the File System where they would like to copy their code to the PaaS environment for hosting. They would also like to read through the File System to verify if all the code files are deployed properly and are placed at the right place in the Azure Website File System. In most of the organizations, the developers are neither allowed to access Azure website on the portal nor read through the file system using website Console feature due to access controls and IT restrictions. For all such requirements they need to raise a ticket with centralized IT/Cloud team and get this done. Developers may not even have access to Azure portal. And many times they may need to do some custom modifications or installations on the website.

Microsoft Visual Studio Integrated Desktop Environment addresses these pain points of developers and facilitates seamless deployment to Azure (Platform as a Service) website. But not all code in the world are developed using Visual Studio IDE and Azure platform is not restricted to host only Microsoft technologies code. Azure ecosystem is large and supports an array of non-Microsoft technologies like Java, Python, and PHP to name a few. Developers would use non-Microsoft IDEs to develop non-Microsoft code and would like to host their code on Azure websites. They would love to use the IDE they have been using for ages to build the code and may not like to switch to Visual Studio. These IDEs may not be robust enough to support Azure website deployment like Visual Studio offers. Some may support but with limited functionalities.

A lot of third-party tools are available in the market to help with deployment but the good ones are not free. Also in larger organizations embracing a third-party tool would need to undergo a rigorous approval process and once the tool is approved by the concerned IT support team then only the developer can start using the tool.

Kudu REST APIs are a great help here and handle all scenarios listed above. They are simple REST endpoints and can be consumed by any programming language that supports REST calls. Kudu REST APIs bridge the gap between Azure websites and non-Microsoft applications and gets Azure PaaS closer to non-Microsoft applications.

Getting started

The best way to learn deployment using Kudu REST APIs is to build a use case and implement it. Let us build a PowerShell script that will invoke Kudu REST API zipdeploy and facilitate code deployment on Azure PaaS website. Once the code is deployed, the PowerShell script will invoke Kudu REST API vfs to list the files deployed so as to verify that all the files are successfully deployed. In the end PowerShell script will invoke Kudu REST API command that will create a log folder in the PaaS website file system and store temporary logs there.

An Azure Web App called ZipDeployGuide is already created. Steps to create this Azure Web App is not discussed here. Here we will deploy a simple ASP.net MVC application that is already created. The steps illustrated here can be used to deploy web applications built using any Azure Web App supported languages like Java, PHP, Python, etc.

Preparing the deployment package

Deployment artifacts are just to be zipped. Kudu REST API zipdeploy will unzip the zipped file to the publish root location on the Azure Web App. In our case, the publish root location on Azure Web App is:

D:\home\site\wwwroot

A default ASP.net MVC application is created using Visual Studio and the deployment artifacts are published to a local folder in the development system:

C:\KuduZipDeploy\DeploymentArtifacts

Steps for creating the ASP.net MVC application and publishing the deployment artifacts to the local folder is out of scope here as the article is focused on deploying the application and not developing the application. As a prerequisite, the deployment artifacts should be ready before trying out deployment using Kudu REST APIs.

Deployment artifacts are zipped and a zip file called as DeploymentArtifacts.zip is generated in the same location:

C:\KuduZipDeploy\DeploymentArtifacts.zip

Figure 1 below shows how the zipped folder looks.

 

Deployment artifacts can be zipped using any standard zip software like WinZip or 7 Zip or any other software per convenience. Kudu REST API zipdeploy expects simply zipped contents as deployment packages and hence this makes zipdeploy work on any programming platform or programming language.

Deploy zipped package to Azure Web App

Once the zipped deployment artifact DeploymentArtifacts.zip is ready, Kudu REST API zipdeploy can be invoked to unzip the zipped contents on the Azure Web App publish folder. Any programming language that is capable of invoking REST API calls can invoke zipdeploy. In this demonstration, PowerShell is used to invoke REST API.

Every Azure Web App is associated with a Kudu URL on which the Kudu REST APIs sit. This URL is needed to invoke zipdeploy API. If the Azure Web App URL is:

https://webappname.azurewebsites.net

Then the corresponding Kudu URL for the Azure Web App would be:

https://webappname.scm.azurewebsites.net

In the current context the Kudu URL for Azure Web App would be:

https://zipdeployguide.scm.azurewebsites.net

The zipdeploy API URL would be

https://zipdeployguide.scm.azurewebsites.net/api/zipdeploy

The username and Password required to deploy the zipped artifacts can be read from the Publish Profile file of the Azure Web App that can be downloaded from the Azure Portal.

Figure 2 below shows the downloaded publish profile from the Azure Web App. Refer userName and userPWD values in the publishProfile section with profileName as ZipDeployGuide – Web Deploy.

 

Once the Kudu REST API URL, Publish Profile User Name and Publish Profile Password is handy Kudu REST API zipdeploy can be invoked as below to deploy the zipped package. Below is the PowerShell code that invokes Kudu REST API zipdeploy to deploy the zipped artifacts. PowerShell exposes cmdlet

Invoke-RestMethod to make REST API calls. To do the deployment a POST call has to be made on REST API zipdeploy. It is highly essential to escape the $ character in the userName using backtick character (`) else PowerShell will treat this as variable instead of literal. See detailed comments (statement starting with #) in the code to get a detailed understanding of this code piece,

  1. # User name from WebDeploy Publish Profile. Use backtick while assigning variable content  
  2. $userName = "`$ZipDeployGuide"  
  3. # Password from WebDeploy Publish Profile  
  4. $password = "{Password}"  
  5. # Encode username and password to base64 string  
  6. $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $userName, $password)))  
  7. # Splat all parameters together in $param hash table  
  8. $param = @{  
  9.             # zipdeploy api url  
  10.             Uri = "https://zipdeployguide.scm.azurewebsites.net/api/zipdeploy"  
  11.             Headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}  
  12.             UserAgent = "powershell/1.0"  
  13.             Method = "POST"  
  14.             # Deployment Artifact Path  
  15.             InFile = "C:\KuduZipDeploy\DeploymentArtifacts.zip"  
  16.             ContentType = "multipart/form-data"  
  17. }  
  18. # Invoke REST call  
  19. Invoke-RestMethod @param  

Verify Package deployed on Azure Web App

Kudu REST API vfs can be used to read through the virtual file system of the Azure website. This REST API can be used in this scenario to list out all deployed artifacts in the Azure website virtual file system. To check artifacts deployed at location D:\home\site\wwwroot in the Azure Web App, the URL for the REST API would be as below where zipdeployguide in the URL is the name of the Azure Web App.

https://zipdeployguide.scm.azurewebsites.net/api/vfs/site/wwwroot

Below is the code snippet that makes a call to vfs api and get all contents deployed in the website wwwroot folder. This code can be extended further to read file contents in the sub folders as well recursively. User name and Password to read the website content can be retrieved from the publish profile of the Azure Web App as discussed earlier.

  1. # User name from WebDeploy Publish Profile. Back tick is needed in the   
  2. $userName = "`$ZipDeployGuide"  
  3. # Provide Password from WebDeploy Publish Profile  
  4. $password = "{Password}"  
  5. # Encode username and password to base64 string  
  6. $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $userName, $password)))  
  7. # Splat all parameters together in $param and invoke REST API  
  8. $param = @{  
  9.             # vfs REST API url  
  10.             Uri = "https://zipdeployguide.scm.azurewebsites.net/api/vfs/site/wwwroot/"  
  11.             Headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}  
  12.             UserAgent = "powershell/1.0"  
  13.             Method = "GET"  
  14.             ContentType = "application/json"  
  15. }  
  16. Invoke-RestMethod @param  

Figure 3 below shows a sample output of the execution in the PowerShell console. Files and Folder details are listed here. Not all the files are captured in the figure as the file list is long enough and needs scrolling in the console.

 

Creating a log folder in the Azure Website File System

Many times developers may have a need to run DOS commands on the Azure website file system. They may need to create a folder to store temporary files. Also, there might be a need to read across intermediate files while debugging the website and then clear off these intermediate temporary files. They may also need to install a custom package (maybe a Python package like Tensor Flow or some wheel files). To address all such scenarios Kudu REST API command can be used. This API helps in running any DOS command on Azure Web App virtual file system. Below is the URL for the command REST API in the current context.

https://zipdeployguide.scm.azurewebsites.net/api/command

To create a folder called TempLogsForDebugging below is the DOS command.

  1. md TempLogsForDebugging  

Below is code that will create a log folder in the Azure Website File System. The DOS command (see command parameter in the bodyToPOST parameter) and the directory where the command has to be executed (see dir in the bodyToPOST parameter) has to be passed in the body of the POST call.

  1. # User name from WebDeploy Publish Profile. Backtick is needed in the   
  2. $userName = "`$ZipDeployGuide"  
  3. # Provide Password from WebDeploy Publish Profile  
  4. $password = "{Password}"  
  5. # Encode username and password to base64 string  
  6. $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $userName, $password)))  
  7. # Construct command API Body. DOS command to create a folder called TempLogsForDebugging  
  8. $bodyToPOST = @{  
    • command = "md TempLogsForDebugging"
  9.                  dir = "D:\home\site\wwwroot"  
  10. }  
  11. # Splat all parameters together in $param  
  12. $param = @{  
  13.             # command REST API url  
  14.             Uri = "https://zipdeployguide.scm.azurewebsites.net/api/command"  
  15.             Headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}  
  16.             UserAgent = "powershell/1.0"  
  17.             Method = "POST"  
  18.             Body = (ConvertTo-Json $bodyToPOST)  
  19.             ContentType = "application/json"  
  20. }  
  21. # Invoke REST call  
  22. Invoke-RestMethod @param  

Many times, there is a need to clean the deployment folder just before redeploying the contents afresh. In this case commandAPI is an excellent way to get this done.@p

DOS command to clean all files inside wwwroot folder of Azure Web App is as below,

  1. del /S /F /Q .\\  

Below is code that will clear files in the Azure Website File System. The DOS command (see command parameter in the bodyToPOST parameter) and the directory where the command has to be executed (see dir in the bodyToPOST parameter) has to be passed in the body of the POST call. To clean up all sub folders corresponding DOS commands like rmdir can be used. The best way would be to have all commands needed to do a cleanup in a batch file and invoke the batch file using command API in the same way we are invoking the DOS commands.

  1. # User name from WebDeploy Publish Profile. Back tick is needed in the   
  2. $userName = "`$ZipDeployGuide"  
  3. # Provide Password from WebDeploy Publish Profile  
  4. $password = "{Password}"  
  5. # Encode username and password to base64 string  
  6. $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $userName, $password)))  
  7. # Construct command api Body. DOS command to clean up existing deployment  
  8. $bodyToPOST = @{  
  9.                   command = "del /S /F /Q .\\"  
  10.                   dir = "D:\home\site\wwwroot"  
  11. }  
  12. # Splat all parameters together in $param  
  13. $param = @{  
  14.             # command REST API url  
  15.             Uri = "https://zipdeployguide.scm.azurewebsites.net/api/command"  
  16.             Headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}  
  17.             UserAgent = "powershell/1.0"  
  18.             Method = "POST"  
  19.             Body = (ConvertTo-Json $bodyToPOST)  
  20.             ContentType = "application/json"  
  21. }  
  22. # Invoke REST call  
  23. Invoke-RestMethod @param  

Using zip API call to deploy a zipped package to Azure Website

Kudu REST API zip can also be used to deploy a zipped package to Azure Web App. However, this approach is not a recommended way to do the deployment as per Kudu REST APIs portal. But the GET call provided by this API is extremely useful. The GET call can be used to zip the deployed contents on Azure Web App and download it to local. This can be used as an excellent mechanism to go through the deployed contents and inspect the package that is deployed locally. The PUT call of this API can be used as an alternative to deploying the zipped package to the Azure Web App as an alternative to zipdeploy API.

Below is URL for Kudu REST API zip for our Azure website ZipDeployGuide.

https://zipdeployguide.scm.azurewebsites.net/api/zip/site/wwwroot

Zipped content will get deployed using PUT call in wwwroot folder of Azure Web App using above URL. Alternatively GET call can be used to zip and download the contents inside wwwroot folder. This can also be used to download contents in a subfolder in the deployment location or deploy zipped content inside a subfolder. For example, if we have a subfolder called scripts inside wwwroot below will be the URL for the zip API.

https://zipdeployguide.scm.azurewebsites.net/api/zip/site/wwwroot/scripts

Below code deploys zipped content in wwwroot folder of the Azure Web App. The same zip file used in zipdeploy is used here.

  1. # User name from WebDeploy Publish Profile. Use backtick while assigning variable content  
  2. $userName = "`$ZipDeployGuide"  
  3. # Password from WebDeploy Publish Profile  
  4. $password = "{Password}"  
  5. # Encode username and password to base64 string  
  6. $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $userName, $password)))  
  7. # Splat all parameters together in $param hash table  
  8. $param = @{  
  9.             # zipdeploy api url  
  10.             Uri = "https://zipdeployguide.scm.azurewebsites.net/api/zip/site/wwwroot"  
  11.             Headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}  
  12.             UserAgent = "powershell/1.0"  
  13.             Method = "PUT"  
  14.             # Deployment Artifact Path  
  15.             InFile = "C:\KuduZipDeploy\DeploymentArtifacts.zip"  
  16.             ContentType = "multipart/form-data"  
  17. }  
  18. # Invoke REST call  
  19. Invoke-RestMethod @param  

The below code does a GET call on wwwroot folder of Azure Web App to zip the contents in the Azure wwwroot folder and download in the local path C:\KuduZipDeploy\deploymentcontent

  1. # User name from WebDeploy Publish Profile. Back tick is needed in the   
  2. $userName = "`$ZipDeployGuide"  
  3. # Provide Password from WebDeploy Publish Profile  
  4. $password = "{Password}"  
  5. # Encode username and password to base64 string  
  6. $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $userName, $password)))  
  7. # Splat all parameters together in $param and invoke REST API  
  8. $param = @{  
  9.             # vfs REST API url  
  10.             Uri = "https://zipdeployguide.scm.azurewebsites.net/api/zip/site/wwwroot/"  
  11.             Headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}  
  12.             UserAgent = "powershell/1.0"  
  13.             Method = "GET"  
  14.             ContentType = "application/json"  
  15.             # Download the zip contents to this path  
  16.             OutFile = "C:\KuduZipDeploy\deploymentcontent\deployments.zip"  
  17. }  
  18. Invoke-RestMethod @param  

Wrap up

This article demonstrated how developers can use Kudu REST APIs and interact with Virtual File System of the Azure Web App to a great extent. Kudu REST APIs zipdeploy, vfs and command demonstrated in this article are not the only ones. There is a long list of APIs available that can be of great help to the developers. The complete list can be accessed at Project Kudu REST APIs on GitHub.

Below are listed the takeaways from this article,

  • Deploy to Azure PaaS website without using any IDE or expensive commercial tools
  • Learn Kudu REST APIs command, vfs, and zipdeploy
  • Kudu REST APIs can be invoked from any programming language/platform that is capable of making REST API call.
  • Kudu REST APIs bridge the gap between Azure websites and non-Microsoft applications and gets Azure PaaS closer to non-Microsoft applications.