0

I am trying to access Kudu through power shell script. Link looks like: https://adc-dev.scm.azurewebsites.net. I need to copy war file located in D:\home\site\wwwroot\bin\apache-tomcat-8.0.33\webapps location in above link.

Currently I am deploying the war file using VSTS by adding FTP task. But before deploying the latest war I would like to take backup of the old war in some location in Azure Kudu location say like: D:\home\site\wwwroot\bin\apache-tomcat-8.0.33 (root folder to the war location). So after that I can remove the war and deploy the latest war file in Kudu.

How to do this? I mean how to access kudu using power shell script. Please suggest me.

Peter Tretyakov
  • 3,380
  • 6
  • 38
  • 54
PDBR PRAVEEN
  • 93
  • 1
  • 10
  • Thats a before DevOps era practice. Use a deployment slot instead, publish to staging, test and swap staging to Prod. If stuff no longer looks right just swap back. – evilSnobu Oct 23 '17 at 15:31
  • Hi Peter, Could you please explain with the task names in VSTS as I am not understanding the above answer which you have given.Kindly,share me the steps how to access kudu through VSTS and take war backup (copy into another folder in kudu).Please explain. – PDBR PRAVEEN Oct 24 '17 at 07:01

3 Answers3

2

To access Kudu API, get your WebApp:

$app = Get-AzWebApp -ResourceGroupName "your RG" -Name "your App"

Then get publishing credentials for the app:

$resourceName = "$($app.Name)/publishingcredentials";
$resourceType = "Microsoft.Web/sites/config";
$publishingCredentials = Invoke-AzResourceAction `
        -ResourceGroupName $app.ResourceGroup `
        -ResourceType $resourceType `
        -ResourceName $resourceName `
        -Action list `
        -ApiVersion $apiVersion `
        -Force;

Format the username/password suitable for a HTTP-request:

$user = $publishingCredentials.Properties.PublishingUserName;
$pass = $publishingCredentials.Properties.PublishingPassword;
$creds = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("${user}:${pass}")));

Finally, you can access the Kudu API:

$header = @{
    Authorization = "Basic $creds"
};
$kuduApiBaseUrl = "https://$($app.Name).scm.azurewebsites.net";

Example, check if extension is installed:

$extensionName = "Microsoft.AspNetCore.AzureAppServices.SiteExtension";
$kuduApiUrl = "$kuduApiBaseUrl/api/siteextensions/$extensionName";
$response = Invoke-RestMethod -Method 'Get' -Uri $kuduApiUrl -Headers $header;

Example, get list of available extensions:

$kuduApiUrl = "$kuduApiBaseUrl/api/extensionfeed";
$response = Invoke-RestMethod -Method 'Get' -Uri $kuduApiUrl -Headers $header;

Example, install an extension:

$kuduApiUrl = "$kuduApiBaseUrl/api/siteextensions";
$response = Invoke-RestMethod -Method 'Put' -Uri $kuduApiUrl -Headers $header;

API-details are at https://github.com/projectkudu/kudu/wiki/REST-API

Also deployment slots can be accessed. App config needs to be retrieved for the slot and a minor modification of the base URL is needed.

Jari Turkia
  • 1,184
  • 1
  • 21
  • 37
1

You can refer to this thread below to know how to call Kudu API through Azure PowerShell in VSTS build/release:

Remove files and foldes on Azure before a new deploy from VSTS

Regarding copy file through Kudu, you can use Command Kudu API (Post /api/command):

Kudu REST API

Update:

Simple sample to call Command through Kudu API:

  function RunCommand($dir,$command,$resourceGroupName, $webAppName, $slotName = $null){
        $kuduApiAuthorisationToken = Get-KuduApiAuthorisationHeaderValue $resourceGroupName $webAppName $slotName
        $kuduApiUrl="https://$webAppName.scm.azurewebsites.net/api/command"
        $Body = 
          @{
          "command"=$command;
           "dir"=$dir
           } 
        $bodyContent=@($Body) | ConvertTo-Json
        Write-Host $bodyContent
         Invoke-RestMethod -Uri $kuduApiUrl `
                            -Headers @{"Authorization"=$kuduApiAuthorisationToken;"If-Match"="*"} `
                            -Method POST -ContentType "application/json" -Body $bodyContent
    }


RunCommand "site\wwwroot\bin\apache-tomcat-8.0.33\webapps" "copy xx.war ..\xx.war /y" "[resource group]" "[web app]"
starian chen-MSFT
  • 33,174
  • 2
  • 29
  • 53
  • Thanks MSFT.But can you please provide the exact script so that I can implement in my project.Just I need to copy war file from located in kudu ( https://adc-dev.scm.azurewebsites.net) under D:\home\site\wwwroot\bin\apache-tomcat-8.0.33\webapps location into D:\home\site\wwwroot\bin\apache-tomcat-8.0.33 this location and remove the war file from D:\home\site\wwwroot\bin\apache-tomcat-8.0.33\webapps this location.After that I can deploy new war from VSTS using ftp.so how to write the script.Kindly provide the exact script as I am not understanding your links to my level. – PDBR PRAVEEN Oct 24 '17 at 07:11
  • @PDBRPRAVEEN I updated my answer, for other code, just refer to the thread that I provide. – starian chen-MSFT Oct 24 '17 at 07:43
  • @PDBRPRAVEEN I solved this issue with Kudu api [What is the best way to stop triggered web jobs](https://stackoverflow.com/questions/47027845/what-is-the-best-way-to-stop-triggered-web-jobs), do you solve this issue with Kudu API too? – starian chen-MSFT Nov 01 '17 at 07:39
  • I didn't use this as I have found other way.I will let you know in future if I need any change or issues in this if I use this script.By the way I am accepting your answer.Thanks a lot again. – PDBR PRAVEEN Nov 01 '17 at 07:47
0

You can use below code to access kudu apis from powershell -

 //function to Get webapp's publishing credentials    
    function Get-AzWebAppPublishingCredentials($resourceGroupName, $webAppName, $slotName = $null) {
            if ([string]::IsNullOrWhiteSpace($slotName) -or $slotName.ToLower() -eq "production") {
                $resourceType = "Microsoft.Web/sites/config"
                $resourceName = "$webAppName/publishingcredentials"
            }
            else {
                $resourceType = "Microsoft.Web/sites/slots/config"
                $resourceName = "$webAppName/$slotName/publishingcredentials"
            }
            $publishingCredentials = Invoke-AzResourceAction -ResourceGroupName $resourceGroupName -ResourceType $resourceType -ResourceName $resourceName -Action list -ApiVersion 2015-08-01 -Force
            return $publishingCredentials
    }

 //function to get authorization header from publishing credentials
     function Get-KuduApiAuthorisationHeaderValue($resourceGroupName, $webAppName, $slotName = $null) {
            $publishingCredentials = Get-AzWebAppPublishingCredentials $resourceGroupName $webAppName $slotName
            $ret = @{ }
            $ret.header = ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword))))
            $ret.url = $publishingCredentials.Properties.scmUri
            return $ret
        }

 //function to call kudu api e.g. to get a file from webapp
    function Get-FileFromWebApp($resourceGroupName, $webAppName, $slotName = "", $kuduPath) {
        $KuduAuth = Get-KuduApiAuthorisationHeaderValue $resourceGroupName $webAppName $slotName
        $kuduApiAuthorisationToken = $KuduAuth.header
        $kuduApiUrl = $KuduAuth.url + "/api/vfs/$kuduPath"

        Write-Host " Downloading File from WebApp. Source: '$kuduApiUrl'." -ForegroundColor DarkGray
        $tmpPath = "$($env:TEMP)\$([guid]::NewGuid()).json"
        $null = Invoke-RestMethod -Uri $kuduApiUrl `
            -Headers @{"Authorization" = $kuduApiAuthorisationToken; "If-Match" = "*" } `
            -Method GET `
            -ContentType "application/json" `
            -OutFile $tmpPath
        $ret = (Get-Content $tmpPath) | Out-String | ConvertFrom-Json
        Remove-Item $tmpPath -Force
        return $ret
    }
Ghanendra
  • 341
  • 2
  • 13