Octopus.Script exported 2021-09-17 by harrisonmeister belongs to ‘Azure’ category.
This step template will take a provided app_offline file from a package and upload it to an Azure Web App to enable a way to safely bring down the app domain for a subsequent deployment.
It requires a set of deployment credentials for the Azure Web App.
Required:
- Credentials with access to the Kudu VFS API
Notes:
- Tested on Octopus
2021.2
. - Tested with both Windows PowerShell and PowerShell Core on Linux.
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
Azure Web App name
AzWebApp.EnableAppOffline.AzWebAppName =
Provide the Azure Web App name.
AppOffline package source
AzWebApp.EnableAppOffline.SourcePackage =
Provide the package to source the app_offline.htm
file from.
AppOffline file path
AzWebApp.EnableAppOffline.FilePath =
Provide the path (relative to the package) for the app offline file to be uploaded.
Note: If left blank or empty, the file will be sourced from the root of the package.
AppOffline file name
AzWebApp.EnableAppOffline.Filename = app_offline.htm
Optional: Choose the variation of the name of the app offline file. Default: app_offline.htm
Available options:
app_offline.htm
app_offline.html
Deployment username
AzWebApp.EnableAppOffline.Deployment.Username = $#{AzWebApp.EnableAppOffline.WebAppName}
Provide the user or application-scoped deployment username for the Azure Web App. Default: $#{AzWebApp.EnableAppOffline.WebAppName}
.
Deployment password
AzWebApp.EnableAppOffline.Deployment.Password =
Provide the user or application-scoped deployment password for the Azure Web App.
Deployment REST API Url
AzWebApp.EnableAppOffline.Deployment.KuduRestApiUrl = https://#{AzWebApp.EnableAppOffline.AzWebAppName}.scm.azurewebsites.net/api/vfs
Optional: Provide a custom deployment REST API URL. Default is: https://#{AzWebApp.EnableAppOffline.AzWebAppName}.scm.azurewebsites.net/api/vfs
.
Script body
Steps based on this template will execute the following PowerShell script.
$ErrorActionPreference = "Stop";
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Variables
$SourcePackage = "AzWebApp.EnableAppOffline.SourcePackage"
$AzWebAppName = $OctopusParameters["AzWebApp.EnableAppOffline.AzWebAppName"]
$FilePath = $OctopusParameters["AzWebApp.EnableAppOffline.FilePath"]
$Filename = $OctopusParameters["AzWebApp.EnableAppOffline.Filename"]
$DeployUsername = $OctopusParameters["AzWebApp.EnableAppOffline.Deployment.Username"]
$DeployPassword = $OctopusParameters["AzWebApp.EnableAppOffline.Deployment.Password"]
$DeploymentUrl = $OctopusParameters["AzWebApp.EnableAppOffline.Deployment.KuduRestApiUrl"]
# Validation
if ([string]::IsNullOrWhiteSpace($AzWebAppName)) {
throw "Required parameter AzWebApp.EnableAppOffline.AzWebAppName not specified"
}
if ([string]::IsNullOrWhiteSpace($Filename)) {
throw "Required parameter AzWebApp.EnableAppOffline.Filename not specified"
}
if ([string]::IsNullOrWhiteSpace($DeployUsername)) {
throw "Required parameter AzWebApp.EnableAppOffline.Deployment.Username not specified"
}
if ([string]::IsNullOrWhiteSpace($DeployPassword)) {
throw "Required parameter AzWebApp.EnableAppOffline.Deployment.Password not specified"
}
if ([string]::IsNullOrWhiteSpace($DeploymentUrl)) {
throw "Required parameter AzWebApp.EnableAppOffline.Deployment.KuduRestApiUrl not specified"
}
$DeploymentUrl = $DeploymentUrl.TrimEnd('/')
$ExtractPathKey = "Octopus.Action.Package[$($SourcePackage)].ExtractedPath"
$ExtractPath = $OctopusParameters[$ExtractPathKey]
$FilePath = Join-Path -Path $ExtractPath -ChildPath $FilePath
if (!(Test-Path $FilePath)) {
throw "Either the local or package extraction folder $FilePath does not exist or the Octopus Tentacle does not have permission to access it."
}
$sourceFilePath = Join-Path -Path $FilePath -ChildPath $Filename
if (!(Test-Path $sourceFilePath)) {
throw "The file located at '$sourceFilePath' does not exist or the Octopus Tentacle does not have permission to access it."
}
$destinationFilePathUri = "$DeploymentUrl/site/wwwroot/$filename"
# Local variables
$StepName = $OctopusParameters["Octopus.Step.Name"]
Write-Verbose "AzWebApp.EnableAppOffline.AzWebAppName: $AzWebAppName"
Write-Verbose "AzWebApp.EnableAppOffline.FilePath: $FilePath"
Write-Verbose "AzWebApp.EnableAppOffline.Filename: $FileName"
Write-Verbose "AzWebApp.EnableAppOffline.Deployment.Username: $DeployUsername"
Write-Verbose "AzWebApp.EnableAppOffline.Deployment.Password: ********"
Write-Verbose "AzWebApp.EnableAppOffline.Deployment.KuduRestApiUrl: $DeploymentUrl"
Write-Verbose "Step Name: $StepName"
try {
$credPair = "$($DeployUsername):$($DeployPassword)"
$encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair))
$headers = @{
Authorization = "Basic $encodedCredentials"
# Ignore E-Tag
"If-Match" = "*"
}
Write-Host "Invoking Put request for '$sourceFilePath' to '$destinationFilePathUri'"
$response = Invoke-RestMethod -Method Put -Infile $sourceFilePath -Uri $destinationFilePathUri -Headers $headers -UserAgent 'powershell/1.0' -ContentType 'application/json'
Write-Verbose "Response: $response"
}
catch {
$ExceptionMessage = $_.Exception.Message
$ErrorDetails = $_.ErrorDetails.Message
$Message = "An error occurred invoking the Azure Web App REST API: $ExceptionMessage"
if (![string]::IsNullOrWhiteSpace($ErrorDetails)) {
$Message += "`nDetail: $ErrorDetails"
}
Write-Error $Message -Category ConnectionError
}
Provided under the Apache License version 2.0.
To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.
{
"Id": "852b78ae-eb32-43c0-bf55-0a5bdd7bebc8",
"Name": "Azure Web App - Enable app_offline",
"Description": "This step template will take a provided app_offline file from a package and upload it to an Azure Web App to enable a way to safely bring down the app domain for a subsequent deployment.\n\nIt requires a set of [deployment credentials](https://docs.microsoft.com/en-gb/azure/app-service/deploy-configure-credentials) for the Azure Web App.\n\n**Required:** \n- Credentials with access to the [Kudu VFS API](https://github.com/projectkudu/kudu/wiki/REST-API#vfs)\n\nNotes:\n\n- Tested on Octopus `2021.2`.\n- Tested with both Windows PowerShell and PowerShell Core on Linux.",
"Version": 1,
"ExportedAt": "2021-09-17T17:45:50.539Z",
"ActionType": "Octopus.Script",
"Author": "harrisonmeister",
"Packages": [
{
"Id": "ff7d24cc-7288-428f-985a-155c467d63ff",
"Name": "AzWebApp.EnableAppOffline.SourcePackage",
"PackageId": null,
"FeedId": null,
"AcquisitionLocation": "Server",
"Properties": {
"Extract": "True",
"SelectionMode": "deferred",
"PackageParameterName": "AzWebApp.EnableAppOffline.SourcePackage"
}
}
],
"Parameters": [
{
"Id": "b847fd97-bc71-4c89-99fb-bd5c2327027a",
"Name": "AzWebApp.EnableAppOffline.AzWebAppName",
"Label": "Azure Web App name",
"HelpText": "Provide the Azure Web App name.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "e15156cc-1fbd-439f-bbea-5eb1f5da8f2f",
"Name": "AzWebApp.EnableAppOffline.SourcePackage",
"Label": "AppOffline package source",
"HelpText": "Provide the package to source the `app_offline.htm` file from. ",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Package"
}
},
{
"Id": "22fdf143-fd7b-48d8-ba52-eed69268b61c",
"Name": "AzWebApp.EnableAppOffline.FilePath",
"Label": "AppOffline file path",
"HelpText": "Provide the path (relative to the package) for the app offline file to be uploaded.\n\n*Note:* If left blank or empty, the file will be sourced from the root of the package.\n",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "0b2edf69-da0d-4750-882a-4036c67f0129",
"Name": "AzWebApp.EnableAppOffline.Filename",
"Label": "AppOffline file name",
"HelpText": "*Optional:* Choose the variation of the name of the app offline file. Default: `app_offline.htm`\n\nAvailable options:\n\n- `app_offline.htm`\n- `app_offline.html`",
"DefaultValue": "app_offline.htm",
"DisplaySettings": {
"Octopus.ControlType": "Select",
"Octopus.SelectOptions": "app_offline.htm|app_offline.htm\napp_offline.html|app_offline.html"
}
},
{
"Id": "c873f396-0ca1-4df9-b083-860541d24b61",
"Name": "AzWebApp.EnableAppOffline.Deployment.Username",
"Label": "Deployment username",
"HelpText": "Provide the user or application-scoped [deployment](https://docs.microsoft.com/en-gb/azure/app-service/deploy-configure-credentials) username for the Azure Web App. Default: `$#{AzWebApp.EnableAppOffline.WebAppName}`.",
"DefaultValue": "$#{AzWebApp.EnableAppOffline.WebAppName}",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "1c18f666-c91d-411c-a86b-b92d0bddc4ed",
"Name": "AzWebApp.EnableAppOffline.Deployment.Password",
"Label": "Deployment password",
"HelpText": "Provide the user or application-scoped [deployment](https://docs.microsoft.com/en-gb/azure/app-service/deploy-configure-credentials) password for the Azure Web App.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "023c4e13-2a25-4e29-916f-aaafea1d8284",
"Name": "AzWebApp.EnableAppOffline.Deployment.KuduRestApiUrl",
"Label": "Deployment REST API Url",
"HelpText": "*Optional:* Provide a custom deployment REST API URL. Default is: `https://#{AzWebApp.EnableAppOffline.AzWebAppName}.scm.azurewebsites.net/api/vfs`.",
"DefaultValue": "https://#{AzWebApp.EnableAppOffline.AzWebAppName}.scm.azurewebsites.net/api/vfs",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
}
],
"Properties": {
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.Script.Syntax": "PowerShell",
"Octopus.Action.Script.ScriptBody": "$ErrorActionPreference = \"Stop\";\n[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12\n\n# Variables\n$SourcePackage = \"AzWebApp.EnableAppOffline.SourcePackage\"\n$AzWebAppName = $OctopusParameters[\"AzWebApp.EnableAppOffline.AzWebAppName\"]\n$FilePath = $OctopusParameters[\"AzWebApp.EnableAppOffline.FilePath\"]\n$Filename = $OctopusParameters[\"AzWebApp.EnableAppOffline.Filename\"]\n$DeployUsername = $OctopusParameters[\"AzWebApp.EnableAppOffline.Deployment.Username\"]\n$DeployPassword = $OctopusParameters[\"AzWebApp.EnableAppOffline.Deployment.Password\"]\n$DeploymentUrl = $OctopusParameters[\"AzWebApp.EnableAppOffline.Deployment.KuduRestApiUrl\"]\n\n# Validation\nif ([string]::IsNullOrWhiteSpace($AzWebAppName)) {\n throw \"Required parameter AzWebApp.EnableAppOffline.AzWebAppName not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($Filename)) {\n throw \"Required parameter AzWebApp.EnableAppOffline.Filename not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($DeployUsername)) {\n throw \"Required parameter AzWebApp.EnableAppOffline.Deployment.Username not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($DeployPassword)) {\n throw \"Required parameter AzWebApp.EnableAppOffline.Deployment.Password not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($DeploymentUrl)) {\n throw \"Required parameter AzWebApp.EnableAppOffline.Deployment.KuduRestApiUrl not specified\"\n}\n\n$DeploymentUrl = $DeploymentUrl.TrimEnd('/')\n$ExtractPathKey = \"Octopus.Action.Package[$($SourcePackage)].ExtractedPath\"\n\n$ExtractPath = $OctopusParameters[$ExtractPathKey]\n$FilePath = Join-Path -Path $ExtractPath -ChildPath $FilePath\nif (!(Test-Path $FilePath)) {\n throw \"Either the local or package extraction folder $FilePath does not exist or the Octopus Tentacle does not have permission to access it.\"\n}\n\n$sourceFilePath = Join-Path -Path $FilePath -ChildPath $Filename\n\nif (!(Test-Path $sourceFilePath)) {\n throw \"The file located at '$sourceFilePath' does not exist or the Octopus Tentacle does not have permission to access it.\"\n}\n$destinationFilePathUri = \"$DeploymentUrl/site/wwwroot/$filename\"\n\n# Local variables\n$StepName = $OctopusParameters[\"Octopus.Step.Name\"]\n\nWrite-Verbose \"AzWebApp.EnableAppOffline.AzWebAppName: $AzWebAppName\"\nWrite-Verbose \"AzWebApp.EnableAppOffline.FilePath: $FilePath\"\nWrite-Verbose \"AzWebApp.EnableAppOffline.Filename: $FileName\"\nWrite-Verbose \"AzWebApp.EnableAppOffline.Deployment.Username: $DeployUsername\"\nWrite-Verbose \"AzWebApp.EnableAppOffline.Deployment.Password: ********\"\nWrite-Verbose \"AzWebApp.EnableAppOffline.Deployment.KuduRestApiUrl: $DeploymentUrl\"\n\nWrite-Verbose \"Step Name: $StepName\"\n\ntry {\n $credPair = \"$($DeployUsername):$($DeployPassword)\"\n $encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair))\n $headers = @{ \n Authorization = \"Basic $encodedCredentials\"\n # Ignore E-Tag\n \"If-Match\" = \"*\" \n }\n \n Write-Host \"Invoking Put request for '$sourceFilePath' to '$destinationFilePathUri'\"\n $response = Invoke-RestMethod -Method Put -Infile $sourceFilePath -Uri $destinationFilePathUri -Headers $headers -UserAgent 'powershell/1.0' -ContentType 'application/json'\n \n Write-Verbose \"Response: $response\"\n}\ncatch {\n $ExceptionMessage = $_.Exception.Message\n $ErrorDetails = $_.ErrorDetails.Message\n $Message = \"An error occurred invoking the Azure Web App REST API: $ExceptionMessage\"\n if (![string]::IsNullOrWhiteSpace($ErrorDetails)) {\n $Message += \"`nDetail: $ErrorDetails\"\n }\n\n Write-Error $Message -Category ConnectionError\n}"
},
"Category": "Azure",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/azure-web-app-enable-appoffline.json",
"Website": "/step-templates/852b78ae-eb32-43c0-bf55-0a5bdd7bebc8",
"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"
}
}
Page updated on Friday, September 17, 2021