Azure Web App - Delete Files

Octopus.AzurePowerShell exported 08/17/2018 by matt-byrne belongs to 'Azure' category.

Provides the ability to delete files and folders from an Azure Web App through the kudu API.

Parameters

When steps based on the template are included in a project's deployment process, the parameters below can be set.

List of Files & Folders to Delete

FilesList

List each file/folder on a new line.

Azure Account

AzureAccount

Must exactly match the name of a configured Azure account.

Resource Group Name

ResourceGroupName

Web App Name

WebAppName

Slot Name

SlotName

Optional. If you want to target a specific slot, enter it's name.

Retry Attempts

RetryAttempts = 3

Number of delete attempts before failing. This should be set higher than 1, as the Azure Kudu API often fails on the first request.

Script body

Steps based on this template will execute the following script.
Show script
Write-Host "Resource Group Name: $($ResourceGroupName)"
Write-Host "Web App Name: $($WebAppName)"
Write-Host "Slot Name: $($SlotName)"

function Get-AzureRmWebAppPublishingCredentials($ResourceGroupName, $WebAppName, $SlotName = $null){	
	
	if ([string]::IsNullOrWhiteSpace($SlotName)) {
		$resourceType = "Microsoft.Web/sites/config"
		$resourceName = "$WebAppName/publishingcredentials"
	} else {
		$resourceType = "Microsoft.Web/sites/slots/config"
		$resourceName = "$WebAppName/$SlotName/publishingcredentials"
	}

	$publishingCredentials = Invoke-AzureRmResourceAction -ResourceGroupName $ResourceGroupName -ResourceType $resourceType -ResourceName $resourceName -Action list -ApiVersion 2015-08-01 -Force
    
    return $publishingCredentials

}

function Get-KuduApiAuthorisationHeaderValue($ResourceGroupName, $WebAppName, $SlotName = $null) {

    $publishingCredentials = Get-AzureRmWebAppPublishingCredentials $ResourceGroupName $WebAppName $SlotName

    return ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword))))

}

function Delete-PathFromWebApp($ResourceGroupName, $WebAppName, $SlotName = $null, $kuduPath) {
	
    $kuduApiAuthorisationToken = Get-KuduApiAuthorisationHeaderValue $ResourceGroupName $WebAppName $SlotName
    
    Write-Host "Kudu Auth Token":
    Write-Host $kuduApiAuthorisationToken
    
    if ([string]::IsNullOrWhiteSpace($SlotName)) {
        $kuduApiUrl = "https://$WebAppName.scm.azurewebsites.net/api/vfs"
    } else {
        $kuduApiUrl = "https://$WebAppName`-$SlotName.scm.azurewebsites.net/api/vfs"
    }
    
    Write-Host "API Url: $($kuduApiUrl)"
    Write-Host "File Path: $($kuduPath)"
    
    Invoke-RestMethod -Uri "$kuduApiUrl/site/wwwroot/$kuduPath" `
                      -Headers @{"Authorization"=$kuduApiAuthorisationToken;"If-Match"="*"} `
                      -Method DELETE 
}

function Delete-FilesAndFoldersFromWebApp($ResourceGroupName, $WebAppName, $SlotName, $FilesList, $RetryAttempts = 3) {

    $list = $FilesList.Split([Environment]::NewLine)

    foreach($item in $list) {
        if(![string]::IsNullOrWhiteSpace($item)) {

            $retryCount = $RetryAttempts
            $retry = $true

            while ($retryCount -gt 0 -and $retry) {
                try {
                    $retryCount = $retryCount -1

                    Delete-PathFromWebApp $ResourceGroupName $WebAppName $SlotName $item

                    $retry = $false
                } catch {
                    $retry = $true
                    if($retryCount -eq 0) {
                        throw ("Exceeded retry attempts " + $RetryAttempts + " for " + $item)
                    }
                }
            }
        }
    }
}

Delete-FilesAndFoldersFromWebApp $ResourceGroupName $WebAppName $SlotName $FilesList $RetryAttempts

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

Show JSON
{
  "Id": "7a3caa63-8312-4e6e-aeb9-674022e5da2f",
  "Name": "Azure Web App - Delete Files",
  "Description": "Provides the ability to delete files and folders from an Azure Web App through the kudu API.",
  "Version": 1,
  "ExportedAt": "2018-08-17T02:46:48.536Z",
  "ActionType": "Octopus.AzurePowerShell",
  "Author": "matt-byrne",
  "Parameters": [
    {
      "Id": "a575296c-babf-4c73-9023-d5a4c9cc84bf",
      "Name": "FilesList",
      "Label": "List of Files & Folders to Delete",
      "HelpText": "List each file/folder on a new line.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    },
    {
      "Id": "7643ed88-ed04-46d2-ae74-1d65b94f03f9",
      "Name": "AzureAccount",
      "Label": "Azure Account",
      "HelpText": "Must exactly match the name of a configured Azure account.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "ac5e4147-8b41-4aa5-82d0-ad5cf5e23499",
      "Name": "ResourceGroupName",
      "Label": "Resource Group Name",
      "HelpText": null,
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "6a833494-e3e6-4b8d-8639-c03f37d6d347",
      "Name": "WebAppName",
      "Label": "Web App Name",
      "HelpText": null,
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "0186edda-110a-4cb7-a270-bdc92e55ea1e",
      "Name": "SlotName",
      "Label": "Slot Name",
      "HelpText": "Optional. If you want to target a specific slot, enter it's name.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "ffeb3047-63d5-4ce7-9c90-81f117106a93",
      "Name": "RetryAttempts",
      "Label": "Retry Attempts",
      "HelpText": "Number of delete attempts before failing. This should be set higher than 1, as the Azure Kudu API often fails on the first request.",
      "DefaultValue": "3",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.ScriptBody": "Write-Host \"Resource Group Name: $($ResourceGroupName)\"\nWrite-Host \"Web App Name: $($WebAppName)\"\nWrite-Host \"Slot Name: $($SlotName)\"\n\nfunction Get-AzureRmWebAppPublishingCredentials($ResourceGroupName, $WebAppName, $SlotName = $null){\t\n\t\n\tif ([string]::IsNullOrWhiteSpace($SlotName)) {\n\t\t$resourceType = \"Microsoft.Web/sites/config\"\n\t\t$resourceName = \"$WebAppName/publishingcredentials\"\n\t} else {\n\t\t$resourceType = \"Microsoft.Web/sites/slots/config\"\n\t\t$resourceName = \"$WebAppName/$SlotName/publishingcredentials\"\n\t}\n\n\t$publishingCredentials = Invoke-AzureRmResourceAction -ResourceGroupName $ResourceGroupName -ResourceType $resourceType -ResourceName $resourceName -Action list -ApiVersion 2015-08-01 -Force\n    \n    return $publishingCredentials\n\n}\n\nfunction Get-KuduApiAuthorisationHeaderValue($ResourceGroupName, $WebAppName, $SlotName = $null) {\n\n    $publishingCredentials = Get-AzureRmWebAppPublishingCredentials $ResourceGroupName $WebAppName $SlotName\n\n    return (\"Basic {0}\" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes((\"{0}:{1}\" -f $publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword))))\n\n}\n\nfunction Delete-PathFromWebApp($ResourceGroupName, $WebAppName, $SlotName = $null, $kuduPath) {\n\t\n    $kuduApiAuthorisationToken = Get-KuduApiAuthorisationHeaderValue $ResourceGroupName $WebAppName $SlotName\n    \n    Write-Host \"Kudu Auth Token\":\n    Write-Host $kuduApiAuthorisationToken\n    \n    if ([string]::IsNullOrWhiteSpace($SlotName)) {\n        $kuduApiUrl = \"https://$WebAppName.scm.azurewebsites.net/api/vfs\"\n    } else {\n        $kuduApiUrl = \"https://$WebAppName`-$SlotName.scm.azurewebsites.net/api/vfs\"\n    }\n    \n    Write-Host \"API Url: $($kuduApiUrl)\"\n    Write-Host \"File Path: $($kuduPath)\"\n    \n    Invoke-RestMethod -Uri \"$kuduApiUrl/site/wwwroot/$kuduPath\" `\n                      -Headers @{\"Authorization\"=$kuduApiAuthorisationToken;\"If-Match\"=\"*\"} `\n                      -Method DELETE \n}\n\nfunction Delete-FilesAndFoldersFromWebApp($ResourceGroupName, $WebAppName, $SlotName, $FilesList, $RetryAttempts = 3) {\n\n    $list = $FilesList.Split([Environment]::NewLine)\n\n    foreach($item in $list) {\n        if(![string]::IsNullOrWhiteSpace($item)) {\n\n            $retryCount = $RetryAttempts\n            $retry = $true\n\n            while ($retryCount -gt 0 -and $retry) {\n                try {\n                    $retryCount = $retryCount -1\n\n                    Delete-PathFromWebApp $ResourceGroupName $WebAppName $SlotName $item\n\n                    $retry = $false\n                } catch {\n                    $retry = $true\n                    if($retryCount -eq 0) {\n                        throw (\"Exceeded retry attempts \" + $RetryAttempts + \" for \" + $item)\n                    }\n                }\n            }\n        }\n    }\n}\n\nDelete-FilesAndFoldersFromWebApp $ResourceGroupName $WebAppName $SlotName $FilesList $RetryAttempts",
    "Octopus.Action.Azure.AccountId": "#{AzureAccount}"
  },
  "Category": "Azure",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-delete-from-webapp.json",
  "Website": "/step-templates/7a3caa63-8312-4e6e-aeb9-674022e5da2f",
  "Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////AHjXf7vrv931QJrh7/f8EIDaIIncMJHfYKvmz+b3n8zw3+76j8Ttr9XycLPpUKLkkKvYFAAABGZJREFUeNrsnNmCqjoQRc1MEiD8/9cer7Yt2KBJZQC8ez07sKlKTQlcLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzoUSnt8YxXlFuGHSbIaxvj+fip4btkLn1blkWLaF5v03yLhLOYlVuGYfMOMZzNGxCOzhjTJqFkXnjq3Dr1yyvPI3hGl3Ih3zzHHNKudRstRhX5O58vIcShY67Gq6EPIESlzUWvazaGAOGbvU7ArDu/g8M4o8opDZWvbvPzlL/MMBE8jT9T9W7PbAJlHPTBFRf9yVTEcs63msXz2UHLSgf650G/d5t+wjbxxB2UCMqGrk8/LFSD7uJMeNt5bcJCyQZyAe5Fo9KYfWS2flQrr4b4tpuzaeWjYs49rt9LHf9uZD7+VbyVi9EBNrjYjuq2sxQOrl+p+HuBVu45qvqfq691ttYFQ5KyKbyJgaIY/NGxrlWZwlwGvmvu1oY3PuAv0niTq6tZ78jk//9uc1r1r4lQki7y7sp2Tu4V1y2iLoqFTqi1lIGcpFiebrZNZ1dOkF0cCIlO8jQ47nCkam9Lilz9GhDF1I6XGLzfnhwDIIZVfI7+8SSgfHsijqXENOGJF5QorG4EcW0OrScqX/dDrXpr70Ut/BII+1OfECPuYz/NWxYmgrCsUskxPvyhgmrw+WGZ6lGTuOlIyCYWTFyWjpM5KIZRUIOwjRNYRQ6tZF9BXtk8hWAHPtLNJ727Fq0JSkC1FDRRF0Jalj0d5qVh2KEpM2TuSsCYTCT6ZkdmFYI9LrYp5QayWbo6NXlZwcRD/61pth5Fq5EX423QQxNjhqWvvklkljOLkYjrmphXPZOJOk6Pg7HKMsrtQKcowzZoK3rx1ZUelGMdQA/HaKkjAt2RgqpZeYqbNbH7Hp2ct4nqfSPOfe0ftiSTZJydOV6rG5bQbyLK+nRuCC0343PzDgiOXyQA5c14BTZi98uR/5KJ1SnatLdoO50WWBQZPTq0VgsklU3h932actuo17ayrHrb/3ykiegd3KbqF2wbV6RrlsJ07yLcpsWFTul9RyK6ZScr+tk7oNrFj0o7HQUlj4EiEvJ6rPLKSmlMZCrksl1OnLaRkxc+/HB1naMhNtT/6yM2bDs6azCRHrM3aVPN7aW8irD/10B8njpAMcsl8okXcdKrl4sPsLmQVy/Sj90ucPRc/d/Bxxj+dXSpCayen32D+hLi16MsIV8gfCXrYp6ySsiJKRUF0XXiLpVbFU+fNv4r7mOwhFsX4ZdwpSi1DYs2jb6ebZ9788cblTzMrYhu7sf/17IFdtuviJ2ioHA6pMHkoH4CLUeMBU7iGkxuM/YgcdderF9ibRdc7O982F1HpYhjfWUe+x5a6pjop9iNLfoePvlsdZdTSMwfxSmTY20Q0eHnUNzga1edeNmmqbg18aMVR1L9vwSXHF9TfIWBxpKLs2hj3eQeBC0USvp2HHF3eIkRdhFOd6ER8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/I/4J8AAo/80BciBec4AAAAASUVORK5CYII=",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History »