\n*Note: Expects the AWS CLI and Powershell to be installed on the worker running this task*
\n*Note: Firewall ports will not be opened on the remote machine*\n*Note: Target machines must be added to your AWS System Manager (SSM)*","Version":3,"ExportedAt":"2021-08-23T12:40:10.975Z","ActionType":"Octopus.AwsRunScript","Author":"benjimac93","Packages":[],"Parameters":[{"Id":"dea51842-271f-48fa-901e-243488049f97","Name":"awsInstallLinuxTentacle.AWSAccount","Label":"AWS Account","HelpText":"AWS account with permissions to the virtual machine in which to install the tentacle on","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AmazonWebServicesAccount"}},{"Id":"6a97548c-3b97-4a19-8b9a-45aa58ac62d9","Name":"awsInstallLinuxTentacle.awsRegion","Label":"AWS Region","HelpText":"The name of the aws region. I.E. `us-east-1`","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"d9efb017-65c0-4010-b09f-0a6a34fc009f","Name":"awsInstallLinuxTentacle.awsSGName","Label":"Security Group Name","HelpText":"The name of the AWS security group to create an exception in","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"e4358aec-2798-412a-bcd2-1c7e41a0728d","Name":"awsInstallLinuxTentacle.awsVmInstanceId","Label":"VM Instance ID","HelpText":"The instance ID of the virtual machine to target when ","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"8dbe0a29-4e0f-43f8-8ef2-ae23a2884e85","Name":"awsInstallLinuxTentacle.octoServerThumb","Label":"Server Thumbprint","HelpText":"The Thumbprint of the octopus server","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"a0859551-6c84-45d1-af2b-c57becb4e8ef","Name":"awsInstallLinuxTentacle.octoApiKey","Label":"Octo User API Key","HelpText":"The API key used to configure the tentacle.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"dd07815d-bfb7-43b9-90f8-21ec5a2d2953","Name":"awsInstallLinuxTentacle.octopusRoles","Label":"Roles","HelpText":"Roles to assign to this tentacle installation.
\n*Note: Each role should be on it's own line*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"d3ffb38e-7fcf-4547-be9a-6cd8e46f8e5e","Name":"awsInstallLinuxTentacle.octopusEnvironments","Label":"Environments","HelpText":"Environments to assign this tentacle installation to.
\n*Note: Each environment should be on its own line*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"15150827-7bd3-4146-a798-66344851f602","Name":"instrallTentacle.octoServerUrl","Label":"Octo Server Url","HelpText":"The server url to register the tentacle with. Defaults to the base url","DefaultValue":"#{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"9bcd6bb5-2db3-453f-b4f6-6a78f3c39b59","Name":"awsInstallLinuxTentacle.tentacleType","Label":"Tentacle Type","HelpText":"Select between a listing or polling tentacle","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"TentaclePassive|Listening\nTentacleActive|Polling"}},{"Id":"6bb98570-fe3e-4ab7-adfb-79ef7ce5c2ce","Name":"awsInstallLinuxTentacle.tentacleHostName","Label":"Tentacle Host Name","HelpText":"The host name to register the listening tentacles with. Octopus deploy server uses this value to reach out to the vm.
\n*Note: Leave blank to automatically use assigned public IP address.*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"386d9f39-9e90-4215-b739-53a1af5bd105","Name":"awsInstallLinuxTentacle.tentacleName","Label":"Tentacle Name","HelpText":"The name of the tentacle to use in the infrastructure area of octopus deploy. Will use the host name if not provided","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"50621684-c2a5-47c0-9bfe-12f004022e60","Name":"awsInstallLinuxTentacle.portNumber","Label":"Port Number","HelpText":"Port number used when installing and registered tentacle. This is also the port opened on the firewall","DefaultValue":"10933","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Azure.AccountId":"#{awsInstallLinuxTentacle.AWSAccount}","Octopus.Action.Script.ScriptBody":"$sgName = $OctopusParameters[\"awsInstallLinuxTentacle.awsSGName\"]\n$instanceId = $OctopusParameters[\"awsInstallLinuxTentacle.awsVmInstanceId\"]\n$serverUri = $OctopusParameters[\"instrallTentacle.octoServerUrl\"]\n$apiKey = $OctopusParameters[\"awsInstallLinuxTentacle.octoApiKey\"]\n$rolesRaw = $OctopusParameters[\"awsInstallLinuxTentacle.octopusRoles\"]\n$enviroRaw = $OctopusParameters[\"awsInstallLinuxTentacle.octopusEnvironments\"]\n$octoThumb = $OctopusParameters[\"awsInstallLinuxTentacle.octoServerThumb\"]\n$comStyle = $OctopusParameters[\"awsInstallLinuxTentacle.tentacleType\"]\n$hostname = $OctopusParameters[\"awsInstallLinuxTentacle.tentacleHostName\"]\n$tentacleName = $OctopusParameters[\"awsInstallLinuxTentacle.tentacleName\"]\n$portNumber = $OctopusParameters[\"awsInstallLinuxTentacle.portNumber\"]\n\nWrite-Host \"Parsing Parameters\"\n\nif([string]::IsNullOrEmpty($sgName))\n{\n\tthrow \"Security Group name must be provided\"\n}\n\nif([string]::IsNullOrEmpty($instanceId))\n{\n\tthrow \"Instance Id must be provided\"\n}\n\nif([string]::IsNullOrEmpty($apiKey))\n{\n\tthrow \"apiKey must be provided\"\n}\n\nif([string]::IsNullOrEmpty($rolesRaw))\n{\n\tthrow \"At least one role must be defined\"\n}\n\nif([string]::IsNullOrEmpty($enviroRaw))\n{\n\tthrow \"At least one environment must be defined\"\n}\n\nif([string]::IsNullOrEmpty($octoThumb))\n{\n\tthrow \"octo thumbprint must be provided\"\n}\n\n$roles = \"\"\n$rolesRaw -split \"`n\" | ForEach-Object { $roles += \"--role $_ \"}\n$roles = $roles.TrimEnd(' ')\n\n$environments = \"\"\n$enviroRaw -split \"`n\" | ForEach-Object { $environments += \"--env $_ \"}\n$environments = $environments.TrimEnd(' ')\n\nif($comStyle -eq \"TentaclePassive\")\n{\n\tif([string]::IsNullOrEmpty($hostname))\n {\n \t$hostname = aws ec2 describe-instances --filters \"Name=instance-id,Values=$instanceId\" --query \"Reservations[].Instances[].NetworkInterfaces[].Association.PublicIp\" --output=text\n $hostname = $hostname.Trim(\"`n\")\n }\n \n $noListen = \"--port $portNumber --noListen `\"false`\"\"\n $comStyle += \" --publicHostName='$hostname'\"\n $openFirewall = 'true'\n}\nelse\n{\n\t$noListen = \"--noListen `\"true`\"\"\n $openFirewall = 'false'\n}\n\nif([string]::IsNullOrEmpty($tentacleName))\n{\n\t$tentacleName = $hostname\n}\n\nif($openFirewall -eq 'true')\n{\n\tWrite-Host \"Checking SG...\" -NoNewline\n $sgCheck = aws ec2 describe-security-groups --group-names $sgName --output json --filters Name=ip-permission.from-port,Values=$portNumber Name=ip-permission.cidr,Values='0.0.0.0/0' | convertfrom-json\n \n if($sgCheck.SecurityGroups.count -eq 0)\n {\n\t\tWrite-Host \"Creating SG Rule\"\n \taws ec2 authorize-security-group-ingress --group-name $sgName --ip-permissions IpProtocol=tcp,ToPort=$portNumber,FromPort=$portNumber,IpRanges='[{CidrIp=0.0.0.0/0,Description=\"OctopusListeningTentacle\"}]'\n\t}\n else\n {\n \tWrite-Host \"Found Existing SG Rule\"\n }\n}\n\nWrite-Verbose \"hostname: $hostname`nnoListen: $noListen\"\n\n$remoteScript = @\"\n{\n\t\"commands\": [\n \t\"#!/bin/bash\",\n\t\t\"curl -L https://octopus.com/downloads/latest/Linux_x64TarGz/OctopusTentacle -o /tmp/tentacle-linux_x64.tar.gz -fsS\",\n\t\t\"if [ ! -d \\\"/opt/octopus\\\" ]; then sudo mkdir /opt/octopus; fi\",\n\t\t\"tar xvzf /tmp/tentacle-linux_x64.tar.gz -C /opt/octopus\",\n\t\t\"rm /tmp/tentacle-linux_x64.tar.gz\",\n\t\t\"cd /opt/octopus/tentacle\",\n\t\t\"sudo /opt/octopus/tentacle/Tentacle create-instance --config '/etc/octopus/default/tentacle-default.config'\",\n\t\t\"sudo chmod a+rwx /etc/octopus/default/tentacle-default.config\",\n\t\t\"/opt/octopus/tentacle/Tentacle new-certificate --if-blank\",\n\t\t\"/opt/octopus/tentacle/Tentacle configure --port $portNumber --noListen False --reset-trust --app '/home/Octopus/Applications'\",\n\t\t\"/opt/octopus/tentacle/Tentacle configure --trust $octoThumb\",\n\t\t\"echo 'Registering the Tentacle $name with server $serverUri in environment $environments with role $roles'\",\n\t\t\"/opt/octopus/tentacle/Tentacle register-with --server '$serverUri' --apiKey '$apikey' $environments $roles --comms-style $comStyle --name '$tentacleName' --force\",\n\t\t\"sudo /opt/octopus/tentacle/Tentacle service --install --start\"\n\t]\n}\n\"@\n\nWrite-Host \"Installing tentacle on remote machine\"\n$guid = (new-guid).guid\nSet-Content -Value $remoteScript -Path \"$env:Temp/$guid.json\"\n\nwrite-verbose $remoteScript\n\nwrite-verbose \"aws ssm send-command --document-name `\"AWS-RunShellScript`\" --instance-ids `\"$instanceId`\" --parameters `\"file://$env:Temp/$guid.json`\"\"\ntry {\n\t$cmdResponse = aws ssm send-command --document-name \"AWS-RunShellScript\" --instance-ids \"$instanceId\" --parameters \"file://$env:Temp/$guid.json\" --query \"Command\" --output json | convertfrom-json\n $cmdId = $cmdResponse.CommandId\n $errorResponse = aws ssm get-command-invocation --command-id \"$cmdId\" --instance-id \"$instanceId\" --output json | convertfrom-json\n \n while($errorResponse.Status -eq 'InProgress')\n {\n \twrite-verbose \"`nStatus: $($errorResponse.Status)\"\n \t$errorResponse = aws ssm get-command-invocation --command-id \"$cmdId\" --instance-id \"$instanceId\" --output json | convertfrom-json\n }\n \n write-verbose \"`nErrorResponse: $errorResponse`n\"\n \n if(![string]::IsNullOrEmpty($errorResponse.StandardErrorContent))\n {\n \tthrow $errorResponse.StandardErrorContent\n }\n}\nfinally {\n\tremove-item \"$env:Temp\\$guid.json\"\n}\n","Octopus.Action.Aws.AssumeRole":"False","Octopus.Action.AwsAccount.UseInstanceRole":"False","Octopus.Action.AwsAccount.Variable":"#{awsInstallLinuxTentacle.AWSAccount}","Octopus.Action.Aws.Region":"#{awsInstallLinuxTentacle.awsRegion}"},"Category":"AWS","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/aws-linux-install-tentacle.json","Website":"/step-templates/43354ae1-c301-42f8-971d-6e659e4807b3","Logo":"iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////9o0R/eLD/Nu0/erS95Qg+bhr95sv/vHh+r96/vjw+bFc/NSl+KI++82W+saI+KpNeDqM1wAAA41JREFUeNrsnG2XazAURiuo0Cr//9feliIvR3DvXJFZe3+a6XpW5+xWEpyY2w0AAAAAAAAAAAAAAAAAAADgf1J0bda/9N70q83a3enzUHWVjbR1sW0xp6sd6fPI72VmUt3zA+kymD6N5vnIBMrHsxHTjsUXOX0e+iVaTNU5Q0A/Q+k+4oAp+ixMbw6A4rGVVjGHR92ulNXWuTAlBNJN/FFyr5yy3qN9rawmF9IxR4hqX4U1WMplmGtruVBDuiuswbKkzaGhX+cfXsqbZlXXv0dsYR13nw9fLenGXD7f6U5Ony4yTpzyZLNMUcpMr0xNzfwdRRMR1/LP2cqMctNqKx1LZFydm2U022ueEtLL6HbHfmSRYRn4HDXaXyzU4XRkkZWK/+JlRBBBBBFEEEEEEUQQQQQRRBBB5B9uYJc7SyuLw+nI7R2ptKWJcywd18Utza0rnM4iN66M6qzS5E93Lf1zLaviUL/ISs/Nt6W00DEyuRgiP2Yxvrd15z/Y26ncG76jy1Ta5jEy/L0p/VMWy33woVm8UYN1Y9fqKrzfZ5iedtaV34+kNxHak2Wg2SSkY7djx/bQWkNP6nkE0lH3Lyx7D1aak1Z1erWJ+U130Vz0Sude7mZqv995nW7mZxJd27Sg5XQppuMdWY3xl1XXOge8MasWjZfund0KbvrkE9fK7OPNne+2U9YEWX3nemtSbvLv6LJ7gZ9X45yBl9ZxrZ9d3vjT8rz62tOsny7jXkpYPX9jQmvF8yF55TdaslGviZy1vAmfoTobsZztGNEv7qZZSr/6HRc/0yzlb3HiKhURRBBBBBFEEEEEEUQQQQQRRBD5XSLav38tllbVzeH02Ww/UWA+6XgsHdXFKc2vK5Quoz/duVRnlrb26crpizzXOVU3l2Zb5Pfe+d1OX8ViqW7qH9gt51K44bukr2XxrW54vMaoy7mxa/cgvPRVKcQG7uOCD58HLQLt3r17Iy6AqjYeDG7TUenWW+p9Ot/IOF/lwuHV1nk6o8M469PWXhtr+0BeX/x7Ue40W3xacfb2gXFxUZcX8TYB3Kyfp+GThsjKti2zgZuMiLshxW3gpiQyrn/DXhR/i1NqIte5pkUEEUQQQQQRRBBBBBFEEEEEEUR+g4jQUZBEqjqFO9mOiyeShoXvYoukZOG4GCLpWZgu83/vTNRidhlE0rYAAAAAAAAAAAAAAAAAAACAZPkjwAAMDi+bsnPP/wAAAABJRU5ErkJggg==","$Meta":{"Type":"ActionTemplate"}},{"Id":"3dd60fea-b98a-4760-8867-cbd049f7aa31","Name":"AWS RDS SQL Server - Backup to S3 Bucket","Description":"Will create a database user using an existing server user if that database user does not exist without using SMO.","Version":2,"ExportedAt":"2020-08-18T14:30:56.431Z","ActionType":"Octopus.Script","Author":"octopusbob","Packages":[],"Parameters":[{"Id":"3e45bb88-3632-4115-a0d5-54680615f0ca","Name":"rdsSqlBackupSqlServer","Label":"SQL Server","HelpText":"The SQL Server to perform the work on","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"880a4e73-64fe-4a36-b4c3-a281b64e3c23","Name":"rdsSqlBackupSqlLoginUserWhoHasCreateUserRights","Label":"SQL Login","HelpText":"The login of the user who has permissions to create a database.\n\nLeave blank for integrated security","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"6689fbe5-f47a-4800-945d-df50fc19c7b0","Name":"rdsSqlBackupSqlLoginPasswordWhoHasRights","Label":"SQL Password","HelpText":"The password of the user who has permissions to create SQL Logins\n\nLeave blank for integrated security","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"1a358cca-5cd1-41ae-b763-fcaf2c7350f9","Name":"rdsSqlBackupDatabaseName","Label":"Database Name","HelpText":"The name of the database to create the user on","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"c5e2fa69-1b42-4427-91d2-10e1a13af744","Name":"rdsSqlBackupS3Bucket","Label":"S3 Bucket Name","HelpText":"The name of the bucket (including any sub directories).","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"ea9d9eb8-9c0f-4c69-a6d4-4d00e43383af","Name":"rdsSqlBackupFileName","Label":"Backup File Name and Extension","HelpText":"The name of the back up file (including the extension).","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"Write-Host \"SqlLoginWhoHasRights $rdsSqlBackupSqlLoginUserWhoHasCreateUserRights\"\nWrite-Host \"CreateSqlServer $rdsSqlBackupSqlServer\"\nWrite-Host \"CreateDatabaseName $rdsSqlBackupDatabaseName\"\nWrite-Host \"Backup S3 Bucket $rdsSqlBackupS3Bucket\"\nWrite-Host \"Backup File Name $rdsSqlBackupFileName\"\n\nif ([string]::IsNullOrWhiteSpace($rdsSqlBackupSqlLoginUserWhoHasCreateUserRights) -eq $true){\n\tWrite-Host \"No username found, using integrated security\"\n $connectionString = \"Server=$rdsSqlBackupSqlServer;Database=msdb;integrated security=true;\"\n}\nelse {\n\tWrite-Host \"Username found, using SQL Authentication\"\n $connectionString = \"Server=$rdsSqlBackupSqlServer;Database=msdb;User ID=$rdsSqlBackupSqlLoginUserWhoHasCreateUserRights;Password=$rdsSqlBackupSqlLoginPasswordWhoHasRights;\"\n}\n\n$sqlConnection = New-Object System.Data.SqlClient.SqlConnection\n$sqlConnection.ConnectionString = $connectionString\n\n$command = New-Object System.Data.SqlClient.SqlCommand(\"dbo.rds_backup_database\", $sqlConnection)\n$command.CommandType = [System.Data.CommandType]'StoredProcedure'\n\n$backupDestParamValue = \"arn:aws:s3:::$rdsSqlBackupS3Bucket/$rdsSqlBackupFileName\"\n$command.Parameters.AddWithValue(\"s3_arn_to_backup_to\", $backupDestParamValue)\n$command.Parameters.AddWithValue(\"overwrite_S3_backup_file\", 1)\n$command.Parameters.AddWithValue(\"source_db_name\", $rdsSqlBackupDatabaseName)\n\n$taskStatusCommand = New-Object System.Data.SqlClient.SqlCommand(\"dbo.rds_task_status\", $sqlConnection)\n$taskStatusCommand.CommandType = [System.Data.CommandType]'StoredProcedure'\n$taskStatusCommand.Parameters.AddWithValue(\"db_name\", $rdsSqlBackupDatabaseName)\n\n$taskStatusAdapter = New-Object System.Data.SqlClient.SqlDataAdapter $taskStatusCommand\n\nWrite-Host \"Opening the connection to $rdsSqlBackupSqlServer\"\n$sqlConnection.Open()\n \nWrite-Host \"Executing backup\"\n$command.ExecuteNonQuery()\n\nWrite-Host \"Closing the connection to $rdsSqlBackupSqlServer\"\n$sqlConnection.Close()\n\nWrite-Host \"Getting status of backup\"\n$backupIsActive = $true\n\nWhile ($backupIsActive)\n{\n\tWrite-Host \"Opening the connection to $rdsSqlBackupSqlServer\"\n\t$sqlConnection.Open()\n \n $taskStatusDataSet = New-Object System.Data.DataSet\n\t$taskStatusAdapter.Fill($taskStatusDataSet)\n $taskStatus = $taskStatusDataSet.Tables[0].Rows[0][\"lifecycle\"]\n $taskComplete = $taskStatusDataSet.Tables[0].Rows[0][\"% complete\"]\n \n Write-Host \"The task is $taskComplete% complete.\"\n $backupIsActive = $taskStatus -eq \"CREATED\" -or $taskStatus -eq \"IN_PROGRESS\"\n \n Write-Host \"Closing the connection to $rdsSqlBackupSqlServer\"\n\t$sqlConnection.Close()\n \n Start-Sleep -Seconds 5\n}"},"Category":"AWS","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/aws-rds-sql-backup-s3.json","Website":"/step-templates/3dd60fea-b98a-4760-8867-cbd049f7aa31","Logo":"iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////9o0R/eLD/Nu0/erS95Qg+bhr95sv/vHh+r96/vjw+bFc/NSl+KI++82W+saI+KpNeDqM1wAAA41JREFUeNrsnG2XazAURiuo0Cr//9feliIvR3DvXJFZe3+a6XpW5+xWEpyY2w0AAAAAAAAAAAAAAAAAAADgf1J0bda/9N70q83a3enzUHWVjbR1sW0xp6sd6fPI72VmUt3zA+kymD6N5vnIBMrHsxHTjsUXOX0e+iVaTNU5Q0A/Q+k+4oAp+ixMbw6A4rGVVjGHR92ulNXWuTAlBNJN/FFyr5yy3qN9rawmF9IxR4hqX4U1WMplmGtruVBDuiuswbKkzaGhX+cfXsqbZlXXv0dsYR13nw9fLenGXD7f6U5Ony4yTpzyZLNMUcpMr0xNzfwdRRMR1/LP2cqMctNqKx1LZFydm2U022ueEtLL6HbHfmSRYRn4HDXaXyzU4XRkkZWK/+JlRBBBBBFEEEEEEUQQQQQRRBBB5B9uYJc7SyuLw+nI7R2ptKWJcywd18Utza0rnM4iN66M6qzS5E93Lf1zLaviUL/ISs/Nt6W00DEyuRgiP2Yxvrd15z/Y26ncG76jy1Ta5jEy/L0p/VMWy33woVm8UYN1Y9fqKrzfZ5iedtaV34+kNxHak2Wg2SSkY7djx/bQWkNP6nkE0lH3Lyx7D1aak1Z1erWJ+U130Vz0Sude7mZqv995nW7mZxJd27Sg5XQppuMdWY3xl1XXOge8MasWjZfund0KbvrkE9fK7OPNne+2U9YEWX3nemtSbvLv6LJ7gZ9X45yBl9ZxrZ9d3vjT8rz62tOsny7jXkpYPX9jQmvF8yF55TdaslGviZy1vAmfoTobsZztGNEv7qZZSr/6HRc/0yzlb3HiKhURRBBBBBFEEEEEEUQQQQQRRBD5XSLav38tllbVzeH02Ww/UWA+6XgsHdXFKc2vK5Quoz/duVRnlrb26crpizzXOVU3l2Zb5Pfe+d1OX8ViqW7qH9gt51K44bukr2XxrW54vMaoy7mxa/cgvPRVKcQG7uOCD58HLQLt3r17Iy6AqjYeDG7TUenWW+p9Ot/IOF/lwuHV1nk6o8M469PWXhtr+0BeX/x7Ue40W3xacfb2gXFxUZcX8TYB3Kyfp+GThsjKti2zgZuMiLshxW3gpiQyrn/DXhR/i1NqIte5pkUEEUQQQQQRRBBBBBFEEEEEEUR+g4jQUZBEqjqFO9mOiyeShoXvYoukZOG4GCLpWZgu83/vTNRidhlE0rYAAAAAAAAAAAAAAAAAAACAZPkjwAAMDi+bsnPP/wAAAABJRU5ErkJggg==","$Meta":{"Type":"ActionTemplate"}},{"Id":"55848421-44b9-403c-b1f0-ba8a84b1f177","Name":"AWS RDS SQL Server - Restore from S3 Bucket","Description":"Will restore a database backup from an S3 bucket","Version":2,"ExportedAt":"2020-08-18T13:27:31.393Z","ActionType":"Octopus.Script","Author":"octopusbob","Packages":[],"Parameters":[{"Id":"3e45bb88-3632-4115-a0d5-54680615f0ca","Name":"rdsSqlRestoreBackupSqlServer","Label":"SQL Server","HelpText":"The SQL Server to perform the work on","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"880a4e73-64fe-4a36-b4c3-a281b64e3c23","Name":"rdsSqlRestoreBackupSqlLoginUserWhoHasCreateUserRights","Label":"SQL Login","HelpText":"The login of the user who has permissions to create a database.\n\nLeave blank for integrated security","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"6689fbe5-f47a-4800-945d-df50fc19c7b0","Name":"rdsSqlRestoreBackupSqlLoginPasswordWhoHasRights","Label":"SQL Password","HelpText":"The password of the user who has permissions to create SQL Logins\n\nLeave blank for integrated security","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"1a358cca-5cd1-41ae-b763-fcaf2c7350f9","Name":"rdsSqlRestoreBackupDatabaseName","Label":"Database Name","HelpText":"The name of the database to restore to","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"c5e2fa69-1b42-4427-91d2-10e1a13af744","Name":"rdsSqlRestoreBackupS3Bucket","Label":"S3 Bucket Name","HelpText":"The name of the bucket (including any sub directories).","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"ea9d9eb8-9c0f-4c69-a6d4-4d00e43383af","Name":"rdsSqlRestoreBackupFileName","Label":"Backup File Name and Extension","HelpText":"The name of the back up file (including the extension).","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"Write-Host \"SqlLoginWhoHasRights $rdsSqlRestoreBackupSqlLoginUserWhoHasCreateUserRights\"\nWrite-Host \"CreateSqlServer $rdsSqlRestoreBackupSqlServer\"\nWrite-Host \"CreateDatabaseName $rdsSqlRestoreBackupDatabaseName\"\nWrite-Host \"Backup S3 Bucket $rdsSqlRestoreBackupS3Bucket\"\nWrite-Host \"Backup File Name $rdsSqlRestoreBackupFileName\"\n\nif ([string]::IsNullOrWhiteSpace($rdsSqlRestoreBackupSqlLoginUserWhoHasCreateUserRights) -eq $true){\n\tWrite-Host \"No username found, using integrated security\"\n $connectionString = \"Server=$rdsSqlRestoreBackupSqlServer;Database=msdb;integrated security=true;\"\n}\nelse {\n\tWrite-Host \"Username found, using SQL Authentication\"\n $connectionString = \"Server=$rdsSqlRestoreBackupSqlServer;Database=msdb;User ID=$rdsSqlRestoreBackupSqlLoginUserWhoHasCreateUserRights;Password=$rdsSqlRestoreBackupSqlLoginPasswordWhoHasRights;\"\n}\n\n$sqlConnection = New-Object System.Data.SqlClient.SqlConnection\n$sqlConnection.ConnectionString = $connectionString\n\n$command = New-Object System.Data.SqlClient.SqlCommand(\"dbo.rds_restore_database\", $sqlConnection)\n$command.CommandType = [System.Data.CommandType]'StoredProcedure'\n\n$backupDestParamValue = \"arn:aws:s3:::$rdsSqlRestoreBackupS3Bucket/$rdsSqlRestoreBackupFileName\"\n$command.Parameters.AddWithValue(\"s3_arn_to_restore_from\", $backupDestParamValue)\n$command.Parameters.AddWithValue(\"with_norecovery\", 0)\n$command.Parameters.AddWithValue(\"restore_db_name\", $rdsSqlRestoreBackupDatabaseName)\n\n$taskStatusCommand = New-Object System.Data.SqlClient.SqlCommand(\"dbo.rds_task_status\", $sqlConnection)\n$taskStatusCommand.CommandType = [System.Data.CommandType]'StoredProcedure'\n$taskStatusCommand.Parameters.AddWithValue(\"db_name\", $rdsSqlRestoreBackupDatabaseName)\n\n$taskStatusAdapter = New-Object System.Data.SqlClient.SqlDataAdapter $taskStatusCommand\n\nWrite-Host \"Opening the connection to $rdsSqlRestoreBackupSqlServer\"\n$sqlConnection.Open()\n \nWrite-Host \"Executing backup\"\n$command.ExecuteNonQuery()\n\nWrite-Host \"Closing the connection to $rdsSqlRestoreBackupSqlServer\"\n$sqlConnection.Close()\n\nWrite-Host \"Getting status of backup\"\n$backupIsActive = $true\n\nWhile ($backupIsActive)\n{\n\tWrite-Host \"Opening the connection to $rdsSqlRestoreBackupSqlServer\"\n\t$sqlConnection.Open()\n \n $taskStatusDataSet = New-Object System.Data.DataSet\n\t$taskStatusAdapter.Fill($taskStatusDataSet)\n $taskStatus = $taskStatusDataSet.Tables[0].Rows[0][\"lifecycle\"]\n $taskComplete = $taskStatusDataSet.Tables[0].Rows[0][\"% complete\"]\n \n Write-Host \"The task is $taskComplete% complete.\"\n $backupIsActive = $taskStatus -eq \"CREATED\" -or $taskStatus -eq \"IN_PROGRESS\"\n \n Write-Host \"Closing the connection to $rdsSqlRestoreBackupSqlServer\"\n\t$sqlConnection.Close()\n \n Start-Sleep -Seconds 5\n}"},"Category":"AWS","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/aws-rds-restore-s3.json","Website":"/step-templates/55848421-44b9-403c-b1f0-ba8a84b1f177","Logo":"iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////9o0R/eLD/Nu0/erS95Qg+bhr95sv/vHh+r96/vjw+bFc/NSl+KI++82W+saI+KpNeDqM1wAAA41JREFUeNrsnG2XazAURiuo0Cr//9feliIvR3DvXJFZe3+a6XpW5+xWEpyY2w0AAAAAAAAAAAAAAAAAAADgf1J0bda/9N70q83a3enzUHWVjbR1sW0xp6sd6fPI72VmUt3zA+kymD6N5vnIBMrHsxHTjsUXOX0e+iVaTNU5Q0A/Q+k+4oAp+ixMbw6A4rGVVjGHR92ulNXWuTAlBNJN/FFyr5yy3qN9rawmF9IxR4hqX4U1WMplmGtruVBDuiuswbKkzaGhX+cfXsqbZlXXv0dsYR13nw9fLenGXD7f6U5Ony4yTpzyZLNMUcpMr0xNzfwdRRMR1/LP2cqMctNqKx1LZFydm2U022ueEtLL6HbHfmSRYRn4HDXaXyzU4XRkkZWK/+JlRBBBBBFEEEEEEUQQQQQRRBBB5B9uYJc7SyuLw+nI7R2ptKWJcywd18Utza0rnM4iN66M6qzS5E93Lf1zLaviUL/ISs/Nt6W00DEyuRgiP2Yxvrd15z/Y26ncG76jy1Ta5jEy/L0p/VMWy33woVm8UYN1Y9fqKrzfZ5iedtaV34+kNxHak2Wg2SSkY7djx/bQWkNP6nkE0lH3Lyx7D1aak1Z1erWJ+U130Vz0Sude7mZqv995nW7mZxJd27Sg5XQppuMdWY3xl1XXOge8MasWjZfund0KbvrkE9fK7OPNne+2U9YEWX3nemtSbvLv6LJ7gZ9X45yBl9ZxrZ9d3vjT8rz62tOsny7jXkpYPX9jQmvF8yF55TdaslGviZy1vAmfoTobsZztGNEv7qZZSr/6HRc/0yzlb3HiKhURRBBBBBFEEEEEEUQQQQQRRBD5XSLav38tllbVzeH02Ww/UWA+6XgsHdXFKc2vK5Quoz/duVRnlrb26crpizzXOVU3l2Zb5Pfe+d1OX8ViqW7qH9gt51K44bukr2XxrW54vMaoy7mxa/cgvPRVKcQG7uOCD58HLQLt3r17Iy6AqjYeDG7TUenWW+p9Ot/IOF/lwuHV1nk6o8M469PWXhtr+0BeX/x7Ue40W3xacfb2gXFxUZcX8TYB3Kyfp+GThsjKti2zgZuMiLshxW3gpiQyrn/DXhR/i1NqIte5pkUEEUQQQQQRRBBBBBFEEEEEEUR+g4jQUZBEqjqFO9mOiyeShoXvYoukZOG4GCLpWZgu83/vTNRidhlE0rYAAAAAAAAAAAAAAAAAAACAZPkjwAAMDi+bsnPP/wAAAABJRU5ErkJggg==","$Meta":{"Type":"ActionTemplate"}},{"Id":"5d5bd3ae-09a0-41ac-9a45-42a96ee6206a","Name":"AWS Secrets Manager - Retrieve Secrets","Description":"This step retrieves one or more secrets from AWS [Secrets Manager](https://aws.amazon.com/secrets-manager) and creates [sensitive output variables](https://octopus.com/docs/projects/variables/output-variables#sensitive-output-variables) for each value retrieved. The step supports creating a variable for each key-value in a secret that's retrieved, or you can specify individual keys. These values can be used in other steps in your deployment or runbook process.\n\n---\n\n**Specifying Secret names/keys to retrieve:**\n\nSpecify the names of the secrets to be returned from AWS Secrets Manager, in the format:\n\n`SecretName SecretVersionId SecretVersionStage | KeyNames | OutputVariableName` where:\n\n- `SecretName` is the name of the secret to retrieve. You can specify either the `Amazon Resource Name (ARN)` or the friendly name of the secret.\n- `SecretVersionId` is the unique identifier of the version of the secret that you want to retrieve. If this value isn't specified, the version with the `VersionStage` value as specified in `SecretVersionStage` will be retrieved.\n- `SecretVersionStage` specifies the secret version that you want to retrieve by the staging label attached to the version. *Staging labels are used to keep track of different versions during the rotation process*. If this value isn't specified, the version with the `VersionStage` value of `AWSCURRENT` will be retrieved.\n- `KeyNames` are the names of the keys stored in the secret that you wish to retrieve values for. Multiple fields can be retrieved separated by a space. Alternatively, you can specify all fields using the special keyword `all` or `*`.\n- `OutputVariableName` is the _optional_ Octopus [output variable](https://octopus.com/docs/projects/variables/output-variables) name to store the secret's value in. If multiple fields are specified the field name will be appended to this value. *If this value isn't specified, an output name will be generated dynamically*.\n\n**Examples:**\n\nGiven a secret named `OctoSamples-usercredentials`:\n\n1. `OctoSamples-usercredentials | Username | octousername`\n \n This would retrieve the secret and extract the value from the key-value named `Username` and save it into a sensitive output variable named `octousername`.\n\n2. `OctoSamples-usercredentials | Username Password | octocreds`\n \n This would retrieve the secret named `OctoSamples-usercredentials`, and then extract the values from the key-values named `Username` and `Password` and save them to two sensitive output variables named `octocreds.Username` and `octocreds.Password`.\n\n3. `OctoSamples-usercredentials | * | octocreds`\n \n This would retrieve the secret named `OctoSamples-usercredentials`, and then extract all key-values from the secret and save them to sensitive output variables *prefixed* with `octocreds`.\n\n4. `OctoSamples-usercredentials | all`\n \n This would retrieve the secret named `OctoSamples-usercredentials`, and then extract all key-values from the secret and save them to sensitive output variables *prefixed* with `OctoSamples-usercredentials`.\n\n---\n\n**AWS Dependencies:**\n\nThere are some dependencies/requirements for this step to work successfully.\n\n1. **CLI** - This step uses AWS tooling pre-installed on the target or worker. \n\n Scripts executed in this step need to use the [AWS CLI](https://aws.amazon.com/cli/) to authenticate to AWS and perform other actions. If the CLI can't be found, the step will fail.\n\n2. **AWS Account** - An [AWS account](https://octopus.com/docs/infrastructure/accounts/aws) with permissions to retrieve secrets from AWS Secrets Manager is also required.\n\n---\n\n**Notes:** \n- Tested on Octopus **2021.2**.\n- Tested on both Windows Server 2019 and Ubuntu 20.04.\n\n","Version":2,"ExportedAt":"2021-10-19T10:15:08.626Z","ActionType":"Octopus.AwsRunScript","Author":"harrisonmeister","Packages":[],"Parameters":[{"Id":"8623cdbe-f962-4801-9470-5d14d1d7d5ed","Name":"AWS.SecretsManager.RetrieveSecrets.Account","Label":"AWS Account","HelpText":"An AWS account with permissions to access secrets from Secrets Manager.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AmazonWebServicesAccount"}},{"Id":"55a1d3e8-90c8-4c1a-a315-246fd8660e81","Name":"AWS.SecretsManager.RetrieveSecrets.Region","Label":"AWS Region","HelpText":"Specify the default region. View the [AWS Regions and Endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region) documentation for a current list of the available region codes.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"e204a03d-80a6-437a-9a8b-8812c299741c","Name":"AWS.SecretsManager.RetrieveSecrets.SecretNames","Label":"Secret names to retrieve","HelpText":"Specify the names of the secrets to be returned from AWS Secrets Manager, in the format:\n\n`SecretName SecretVersionId SecretVersionStage | KeyNames | OutputVariableName` where:\n\n- `SecretName` is the name of the secret to retrieve. You can specify either the `Amazon Resource Name (ARN)` or the friendly name of the secret.\n- `SecretVersionId` is the unique identifier of the version of the secret that you want to retrieve. If this value isn't specified, the version with the `VersionStage` value as specified in `SecretVersionStage` will be retrieved.\n- `SecretVersionStage` specifies the secret version that you want to retrieve by the staging label attached to the version. *Staging labels are used to keep track of different versions during the rotation process*. If this value isn't specified, the version with the `VersionStage` value of `AWSCURRENT` will be retrieved.\n- `KeyNames` are the names of the keys stored in the secret that you wish to retrieve values for. Multiple fields can be retrieved separated by a space. Alternatively, you can specify all fields using the special keyword `all` or `*`. *See the step description for examples*.\n- `OutputVariableName` is the _optional_ Octopus [output variable](https://octopus.com/docs/projects/variables/output-variables) name to store the secret's value in. If multiple fields are specified the field name will be appended to this value. *If this value isn't specified, an output name will be generated dynamically*.\n\n**Note:** Multiple fields can be retrieved by entering each one on a new line.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"17ba53a4-bf94-498c-8905-0d37b86eaeea","Name":"AWS.SecretsManager.RetrieveSecrets.PrintVariableNames","Label":"Print output variable names","HelpText":"Write out the Octopus [output variable](https://octopus.com/docs/projects/variables/output-variables) names to the task log. Default: `False`.","DefaultValue":"False","DisplaySettings":{"Octopus.ControlType":"Checkbox"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Aws.AssumeRole":"False","Octopus.Action.AwsAccount.UseInstanceRole":"False","OctopusUseBundledTooling":"False","Octopus.Action.Script.ScriptBody":"$ErrorActionPreference = 'Stop'\n\n# Variables\n$SecretNames = $OctopusParameters[\"AWS.SecretsManager.RetrieveSecrets.SecretNames\"]\n$PrintVariableNames = $OctopusParameters[\"AWS.SecretsManager.RetrieveSecrets.PrintVariableNames\"]\n\n# Validation\nif ([string]::IsNullOrWhiteSpace($SecretNames)) {\n throw \"Required parameter AWS.SecretsManager.RetrieveSecrets.SecretNames not specified\"\n}\n\n# Functions\nfunction Format-SecretName {\n [CmdletBinding()]\n Param(\n [string] $Name,\n [string] $VersionId,\n [string] $VersionStage,\n [string[]] $Keys\n )\n $displayName = \"'$Name'\"\n if (![string]::IsNullOrWhiteSpace($VersionId)) {\n $displayName += \" $VersionId\"\n }\n if (![string]::IsNullOrWhiteSpace($VersionStage)) {\n $displayName += \" $VersionStage\"\n }\n if ($Keys.Count -gt 0) {\n $displayName += \" ($($Keys -Join \",\"))\"\n }\n return $displayName\n}\n\n# End Functions\n\n$Secrets = @()\n$VariablesCreated = 0\n$StepName = $OctopusParameters[\"Octopus.Step.Name\"]\n\n# Extract secret names\n@(($SecretNames -Split \"`n\").Trim()) | ForEach-Object {\n if (![string]::IsNullOrWhiteSpace($_)) {\n Write-Verbose \"Working establishing secret definition for: '$_'\"\n $secretDefinition = ($_ -Split \"\\|\")\n \n # Establish the secret name/version requirements\n $secretName = $secretDefinition[0].Trim()\n $secretVersionId = \"\"\n $secretVersionStage = \"\"\n $secretNameAndVersion = ($secretName -Split \" \")\n \n if ($secretNameAndVersion.Count -gt 1) {\n $secretName = $secretNameAndVersion[0].Trim()\n $secretVersionId = $secretNameAndVersion[1].Trim()\n if ($secretNameAndVersion.Count -eq 3) {\n $secretVersionStage = $secretNameAndVersion[2].Trim()\n }\n }\n \n if ([string]::IsNullOrWhiteSpace($secretName)) {\n throw \"Unable to establish secret name from: '$($_)'\"\n }\n\n # Establish the secret field(s)/output variable name requirements.\n $VariableName = \"\"\n $Keys = @()\n if ($secretDefinition.Count -gt 1) {\n $KeyNames = $secretDefinition[1].Trim() \n $Keys = @(($KeyNames -Split \" \"))\n $EmptyKeys = $Keys | Where-Object { [string]::IsNullOrWhiteSpace($_) }\n if ($Keys.Count -le 0 -or $EmptyKeys.Count -gt 0) {\n throw \"No keys (field names) were specified for '$_'. To retrieve all keys in a secret, add the word ALL or the wildcard (*) character.\" \n }\n \n if ($secretDefinition.Count -gt 2) {\n $VariableName = $secretDefinition[2].Trim()\n }\n }\n else {\n throw \"No keys (field names) were specified for '$_'. To retrieve all keys in a secret, add the word ALL or the wildcard (*) character.\"\n }\n\n $secret = [PsCustomObject]@{\n Name = $secretName\n SecretVersionId = $secretVersionId\n SecretVersionStage = $secretVersionStage\n Keys = $Keys\n variableNameOrPrefix = $VariableName\n }\n $Secrets += $secret\n }\n}\n\nWrite-Verbose \"Secrets to retrieve: $($Secrets.Count)\"\nWrite-Verbose \"Print variables: $PrintVariableNames\"\n\n# Retrieve Secrets\nforeach ($secret in $secrets) {\n $name = $secret.Name\n $versionId = $secret.SecretVersionId\n $versionStage = $secret.SecretVersionStage\n $variableNameOrPrefix = $secret.variableNameOrPrefix\n $keys = $secret.Keys\n \n # Should we extract only specified keys, or all values?\n $SpecifiedKeys = $True\n if ($keys.Count -eq 1 -and ($keys[0] -ieq \"all\" -or $keys[0] -ieq \"*\")) {\n $SpecifiedKeys = $False\n }\n \n $displayName = Format-SecretName -Name $name -VersionId $versionId -VersionStage $versionStage -Keys $keys\n Write-Verbose \"Retrieving Secret $displayName\"\n \n $params = @(\"--secret-id $name\")\n if (![string]::IsNullOrWhiteSpace($versionId)) {\n $params += \"--version-id $versionId\"\n }\n if (![string]::IsNullOrWhiteSpace($versionStage)) {\n $params += \"--version-stage $versionStage\"\n }\n\n $command = \"aws secretsmanager get-secret-value $($params -Join \" \")\"\n Write-Verbose \"Invoking command: $command\"\n $response = Invoke-Expression -Command $command\n \n if ([string]::IsNullOrWhiteSpace($response)) {\n throw \"Error: Secret $displayName not found or has no versions.\"\n }\n \n $AwsSecret = $response | ConvertFrom-Json\n $AwsSecretValue = $AwsSecret.SecretString | ConvertFrom-Json\n $secretKeyValues = $AwsSecretValue | Get-Member | Where-Object { $_.MemberType -eq \"NoteProperty\" } | Select-Object -ExpandProperty \"Name\"\n\n if ($SpecifiedKeys -eq $True) {\n foreach ($keyName in $keys) {\n $variableName = $variableNameOrPrefix\n if ([string]::IsNullOrWhiteSpace($variableName)) {\n $variableName = \"$($name.Trim())\"\n }\n if ($keys.Count -gt 1) {\n $variableName += \".$keyName\"\n }\n if ($secretKeyValues -inotcontains $keyName) {\n throw \"Key '$keyName' not found in AWS Secret: $name.\"\n }\n $variableValue = $AwsSecretValue.$keyName\n Set-OctopusVariable -Name $variableName -Value $variableValue -Sensitive\n if ($PrintVariableNames -eq $True) {\n Write-Host \"Created output variable: ##{Octopus.Action[$StepName].Output.$variableName}\"\n }\n $VariablesCreated += 1\n }\n }\n else {\n \n foreach ($secretKeyValueName in $secretKeyValues) {\n $variableName = $variableNameOrPrefix\n if ([string]::IsNullOrWhiteSpace($variableName)) {\n $variableName = \"$($name.Trim())\"\n }\n if ($secretKeyValues.Count -gt 1) {\n $variableName += \".$secretKeyValueName\"\n }\n $variableValue = $AwsSecretValue.$secretKeyValueName\n Set-OctopusVariable -Name $variableName -Value $variableValue -Sensitive\n if ($PrintVariableNames -eq $True) {\n Write-Host \"Created output variable: ##{Octopus.Action[$StepName].Output.$variableName}\"\n }\n $VariablesCreated += 1\n }\n }\n}\n\nWrite-Host \"Created $variablesCreated output variables\"","Octopus.Action.AwsAccount.Variable":"#{AWS.SecretsManager.RetrieveSecrets.Account}","Octopus.Action.Aws.Region":"#{AWS.SecretsManager.RetrieveSecrets.Region}"},"Category":"AWS","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/aws-secrets-manager-retrieve-secrets.json","Website":"/step-templates/5d5bd3ae-09a0-41ac-9a45-42a96ee6206a","Logo":"iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////9o0R/eLD/Nu0/erS95Qg+bhr95sv/vHh+r96/vjw+bFc/NSl+KI++82W+saI+KpNeDqM1wAAA41JREFUeNrsnG2XazAURiuo0Cr//9feliIvR3DvXJFZe3+a6XpW5+xWEpyY2w0AAAAAAAAAAAAAAAAAAADgf1J0bda/9N70q83a3enzUHWVjbR1sW0xp6sd6fPI72VmUt3zA+kymD6N5vnIBMrHsxHTjsUXOX0e+iVaTNU5Q0A/Q+k+4oAp+ixMbw6A4rGVVjGHR92ulNXWuTAlBNJN/FFyr5yy3qN9rawmF9IxR4hqX4U1WMplmGtruVBDuiuswbKkzaGhX+cfXsqbZlXXv0dsYR13nw9fLenGXD7f6U5Ony4yTpzyZLNMUcpMr0xNzfwdRRMR1/LP2cqMctNqKx1LZFydm2U022ueEtLL6HbHfmSRYRn4HDXaXyzU4XRkkZWK/+JlRBBBBBFEEEEEEUQQQQQRRBBB5B9uYJc7SyuLw+nI7R2ptKWJcywd18Utza0rnM4iN66M6qzS5E93Lf1zLaviUL/ISs/Nt6W00DEyuRgiP2Yxvrd15z/Y26ncG76jy1Ta5jEy/L0p/VMWy33woVm8UYN1Y9fqKrzfZ5iedtaV34+kNxHak2Wg2SSkY7djx/bQWkNP6nkE0lH3Lyx7D1aak1Z1erWJ+U130Vz0Sude7mZqv995nW7mZxJd27Sg5XQppuMdWY3xl1XXOge8MasWjZfund0KbvrkE9fK7OPNne+2U9YEWX3nemtSbvLv6LJ7gZ9X45yBl9ZxrZ9d3vjT8rz62tOsny7jXkpYPX9jQmvF8yF55TdaslGviZy1vAmfoTobsZztGNEv7qZZSr/6HRc/0yzlb3HiKhURRBBBBBFEEEEEEUQQQQQRRBD5XSLav38tllbVzeH02Ww/UWA+6XgsHdXFKc2vK5Quoz/duVRnlrb26crpizzXOVU3l2Zb5Pfe+d1OX8ViqW7qH9gt51K44bukr2XxrW54vMaoy7mxa/cgvPRVKcQG7uOCD58HLQLt3r17Iy6AqjYeDG7TUenWW+p9Ot/IOF/lwuHV1nk6o8M469PWXhtr+0BeX/x7Ue40W3xacfb2gXFxUZcX8TYB3Kyfp+GThsjKti2zgZuMiLshxW3gpiQyrn/DXhR/i1NqIte5pkUEEUQQQQQRRBBBBBFEEEEEEUR+g4jQUZBEqjqFO9mOiyeShoXvYoukZOG4GCLpWZgu83/vTNRidhlE0rYAAAAAAAAAAAAAAAAAAACAZPkjwAAMDi+bsnPP/wAAAABJRU5ErkJggg==","$Meta":{"Type":"ActionTemplate"}},{"Id":"234ed1c6-a5fa-47ee-8669-a187d8787057","Name":"AWS Win - Install Octopus Tentacle","Description":"This step template will install the latest tentacle on an AWS hosted, Windows virtual machine. This will also open the firewall for inbound traffic on port 10933 on the Security Group.\n
\n*Note: Expects the AWS CLI and Powershell to be installed on the worker running this task*","Version":2,"ExportedAt":"2021-08-23T12:40:10.975Z","ActionType":"Octopus.AwsRunScript","Author":"benjimac93","Packages":[],"Parameters":[{"Id":"dea51842-271f-48fa-901e-243488049f97","Name":"awsInstallWinTentacle.AWSAccount","Label":"AWS Account","HelpText":"AWS account with permissions to the virtual machine in which to install the tentacle on","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AmazonWebServicesAccount"}},{"Id":"6a97548c-3b97-4a19-8b9a-45aa58ac62d9","Name":"awsInstallWinTentacle.awsRegion","Label":"AWS Region","HelpText":"The name of the aws region. I.E. `us-east-1`","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"d9efb017-65c0-4010-b09f-0a6a34fc009f","Name":"awsInstallWinTentacle.awsSGName","Label":"Security Group Name","HelpText":"The name of the AWS security group to create an exception in","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"e4358aec-2798-412a-bcd2-1c7e41a0728d","Name":"awsInstallWinTentacle.awsVmInstanceId","Label":"VM Instance ID","HelpText":"The instance ID of the virtual machine to target when ","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"8dbe0a29-4e0f-43f8-8ef2-ae23a2884e85","Name":"awsInstallWinTentacle.octoServerThumb","Label":"Server Thumbprint","HelpText":"The Thumbprint of the octopus server","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"a0859551-6c84-45d1-af2b-c57becb4e8ef","Name":"awsInstallWinTentacle.octoApiKey","Label":"Octo User API Key","HelpText":"The API key used to configure the tentacle.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"dd07815d-bfb7-43b9-90f8-21ec5a2d2953","Name":"awsInstallWinTentacle.octopusRoles","Label":"Roles","HelpText":"Roles to assign to this tentacle installation.
\n*Note: Each role should be on it's own line*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"d3ffb38e-7fcf-4547-be9a-6cd8e46f8e5e","Name":"awsInstallWinTentacle.octopusEnvironments","Label":"Environments","HelpText":"Environments to assign this tentacle installation to.
\n*Note: Each environment should be on its own line*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"15150827-7bd3-4146-a798-66344851f602","Name":"instrallTentacle.octoServerUrl","Label":"Octo Server Url","HelpText":"The server url to register the tentacle with. Defaults to the base url","DefaultValue":"#{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"9bcd6bb5-2db3-453f-b4f6-6a78f3c39b59","Name":"awsInstallWinTentacle.tentacleType","Label":"Tentacle Type","HelpText":"Select between a listening or polling tentacle","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"TentaclePassive|Listening\nTentacleActive|Polling"}},{"Id":"6bb98570-fe3e-4ab7-adfb-79ef7ce5c2ce","Name":"awsInstallWinTentacle.tentacleHostName","Label":"Tentacle Host Name","HelpText":"The host name to register the listening tentacles with. Octopus deploy server uses this value to reach out to the vm.
\n*Note: Leave blank to automatically use assigned public IP address.*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"386d9f39-9e90-4215-b739-53a1af5bd105","Name":"awsInstallWinTentacle.tentacleName","Label":"Tentacle Name","HelpText":"The name of the tentacle to use in the infrastructure area of octopus deploy. Will use the host name if not provided","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"2dc806d8-bba5-44a7-b21d-4b3f041f4d49","Name":"awsInstallWinTentacle.portNumber","Label":"Port Number","HelpText":"Port number used when installing and registering the tentacle. This is also the port opened on the firewall","DefaultValue":"10933","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Azure.AccountId":"#{awsInstallWinTentacle.AWSAccount}","Octopus.Action.Script.ScriptBody":"$sgName = $OctopusParameters[\"awsInstallWinTentacle.awsSGName\"]\n$instanceId = $OctopusParameters[\"awsInstallWinTentacle.awsVmInstanceId\"]\n$serverUri = $OctopusParameters[\"awsInstallWinTentacle.octoServerUrl\"]\n$apiKey = $OctopusParameters[\"awsInstallWinTentacle.octoApiKey\"]\n$rolesRaw = $OctopusParameters[\"awsInstallWinTentacle.octopusRoles\"]\n$enviroRaw = $OctopusParameters[\"awsInstallWinTentacle.octopusEnvironments\"]\n$octoThumb = $OctopusParameters[\"awsInstallWinTentacle.octoServerThumb\"]\n$comStyle = $OctopusParameters[\"awsInstallWinTentacle.tentacleType\"]\n$hostname = $OctopusParameters[\"awsInstallWinTentacle.tentacleHostName\"]\n$tentacleName = $OctopusParameters[\"awsInstallWinTentacle.tentacleName\"]\n$portNumber = $OctopusParameters[\"awsInstallWinTentacle.portNumber\"]\n\nWrite-Host \"Parsing Parameters\"\n\nif([string]::IsNullOrEmpty($sgName))\n{\n\tthrow \"Security Group name must be provided\"\n}\n\nif([string]::IsNullOrEmpty($instanceId))\n{\n\tthrow \"Instance Id must be provided\"\n}\n\nif([string]::IsNullOrEmpty($apiKey))\n{\n\tthrow \"apiKey must be provided\"\n}\n\nif([string]::IsNullOrEmpty($rolesRaw))\n{\n\tthrow \"At least one role must be defined\"\n}\n\nif([string]::IsNullOrEmpty($enviroRaw))\n{\n\tthrow \"At least one environment must be defined\"\n}\n\nif([string]::IsNullOrEmpty($octoThumb))\n{\n\tthrow \"octo thumbprint must be provided\"\n}\n\n$roles = \"\"\n$rolesRaw -split \"`n\" | ForEach-Object { $roles += \"--role $_ \"}\n$roles = $roles.TrimEnd(' ')\n\n$environments = \"\"\n$enviroRaw -split \"`n\" | ForEach-Object { $environments += \"--env $_ \"}\n$environments = $environments.TrimEnd(' ')\n\nif($comStyle -eq \"TentaclePassive\")\n{\n\tif([string]::IsNullOrEmpty($hostname))\n {\n \t$hostname = aws ec2 describe-instances --filters \"Name=instance-id,Values=$instanceId\" --query \"Reservations[].Instances[].NetworkInterfaces[].Association.PublicIp\" --output=text\n $hostname = $hostname.Trim(\"`n\")\n }\n\n $noListen = \"--port $portNumber --noListen 'false'\"\n $comStyle += \" --publicHostName='$hostname'\"\n $openFirewall = 'true'\n}\nelse\n{\n\t$noListen = \"--noListen 'true'\"\n $openFirewall = 'false'\n}\n\nif([string]::IsNullOrEmpty($tentacleName))\n{\n\t$tentacleName = $hostname\n}\n\nif($openFirewall -eq 'true')\n{\n\tWrite-Host \"Checking SG...\" -NoNewline\n $sgCheck = aws ec2 describe-security-groups --group-names $sgName --output json --filters Name=ip-permission.from-port,Values=$portNumber Name=ip-permission.cidr,Values='0.0.0.0/0' | convertfrom-json\n\n if($sgCheck.SecurityGroups.count -eq 0)\n {\n\t\tWrite-Host \"Creating SG Rule\"\n \taws ec2 authorize-security-group-ingress --group-name $sgName --ip-permissions IpProtocol=tcp,ToPort=$portNumber,FromPort=$portNumber,IpRanges='[{CidrIp=0.0.0.0/0,Description=\"OctopusListeningTentacle\"}]'\n\t}\n else\n {\n \tWrite-Host \"Found Existing SG Rule\"\n }\n}\n$remoteGuid = (new-guid).guid\nWrite-Verbose \"hostname: $hostname`nnoListen: $noListen\"\n\n$remoteScript = @\"\n{ \"commands\": [\n\"if('$env:PROCESSOR_ARCHITECTURE' -eq \\\"x86\\\") {Invoke-WebRequest -Uri 'http://octopus.com/downloads/latest/OctopusTentacle' -OutFile `$env:TEMP/$remoteGuid.msi -UseBasicParsing} else { Invoke-WebRequest -Uri 'http://octopus.com/downloads/latest/OctopusTentacle64' -OutFile `$env:TEMP/$remoteGuid.msi -UseBasicParsing}\",\n\"Start-Process `$env:TEMP/$remoteGuid.msi /quiet -Wait\",\n\"Remove-Item \\\"`$env:TEMP/$remoteGuid.msi\\\"\",\n\"cd 'C:/Program Files/Octopus Deploy/Tentacle'\",\n\".\\\\Tentacle.exe create-instance --instance 'Tentacle' --config 'C:/Octopus/Tentacle.config' --console\",\n\".\\\\Tentacle.exe new-certificate --instance 'Tentacle' --if-blank --console\",\n\".\\\\Tentacle.exe configure --instance 'Tentacle' --reset-trust --console\",\n\".\\\\Tentacle.exe configure --instance 'Tentacle' --home 'C:/Octopus/' --app 'C:/Octopus/Applications' $noListen --console\",\n\".\\\\Tentacle.exe configure --instance 'Tentacle' --trust '$octoThumb' --console\",\n\"if('$openFirewall' -eq 'true'){New-NetFirewallRule -DisplayName 'Octopus Tentacle' -Direction Inbound -LocalPort $portNumber -Protocol TCP -Action Allow}\",\n\".\\\\Tentacle.exe register-with --instance 'Tentacle' --server '$serverUri' --apiKey=$apiKey $roles $environments --comms-style $comStyle --force --console\",\n\".\\\\Tentacle.exe service --instance 'Tentacle' --install --start --console\"\n]}\n\"@\n\nWrite-Host \"Installing tentacle on remote machine\"\n$guid = (new-guid).guid\nSet-Content -Value $remoteScript.Replace('`r','') -Path \"$env:Temp/$guid.json\"\n\nwrite-verbose $remoteScript\n\nwrite-verbose \"aws ssm send-command --document-name AWS-RunPowerShellScript --instance-ids $instanceId --parameters file://$env:Temp/$guid.json\"\ntry {\n\t$cmdResponse = aws ssm send-command --document-name \"AWS-RunPowerShellScript\" --instance-ids \"$instanceId\" --parameters \"file://$env:Temp/$guid.json\" --query \"Command\" --output json | convertfrom-json\n $cmdId = $cmdResponse.CommandId\n $errorResponse = aws ssm get-command-invocation --command-id \"$cmdId\" --instance-id \"$instanceId\" --output json | convertfrom-json\n\n while($errorResponse.Status -eq 'InProgress')\n {\n \twrite-verbose \"`nStatus: $($errorResponse.Status)\"\n \t$errorResponse = aws ssm get-command-invocation --command-id \"$cmdId\" --instance-id \"$instanceId\" --output json | convertfrom-json\n }\n\n write-verbose \"`nErrorResponse: $errorResponse`n\"\n\n if(![string]::IsNullOrEmpty($errorResponse.StandardErrorContent))\n {\n \tthrow $errorResponse.StandardErrorContent\n }\n}\nfinally {\n\tremove-item \"$env:Temp\\$guid.json\"\n}\n","Octopus.Action.Aws.AssumeRole":"False","Octopus.Action.AwsAccount.UseInstanceRole":"False","Octopus.Action.AwsAccount.Variable":"#{awsInstallWinTentacle.AWSAccount}","Octopus.Action.Aws.Region":"#{awsInstallWinTentacle.awsRegion}"},"Category":"AWS","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/aws-windows-install-tentacle.json","Website":"/step-templates/234ed1c6-a5fa-47ee-8669-a187d8787057","Logo":"iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////9o0R/eLD/Nu0/erS95Qg+bhr95sv/vHh+r96/vjw+bFc/NSl+KI++82W+saI+KpNeDqM1wAAA41JREFUeNrsnG2XazAURiuo0Cr//9feliIvR3DvXJFZe3+a6XpW5+xWEpyY2w0AAAAAAAAAAAAAAAAAAADgf1J0bda/9N70q83a3enzUHWVjbR1sW0xp6sd6fPI72VmUt3zA+kymD6N5vnIBMrHsxHTjsUXOX0e+iVaTNU5Q0A/Q+k+4oAp+ixMbw6A4rGVVjGHR92ulNXWuTAlBNJN/FFyr5yy3qN9rawmF9IxR4hqX4U1WMplmGtruVBDuiuswbKkzaGhX+cfXsqbZlXXv0dsYR13nw9fLenGXD7f6U5Ony4yTpzyZLNMUcpMr0xNzfwdRRMR1/LP2cqMctNqKx1LZFydm2U022ueEtLL6HbHfmSRYRn4HDXaXyzU4XRkkZWK/+JlRBBBBBFEEEEEEUQQQQQRRBBB5B9uYJc7SyuLw+nI7R2ptKWJcywd18Utza0rnM4iN66M6qzS5E93Lf1zLaviUL/ISs/Nt6W00DEyuRgiP2Yxvrd15z/Y26ncG76jy1Ta5jEy/L0p/VMWy33woVm8UYN1Y9fqKrzfZ5iedtaV34+kNxHak2Wg2SSkY7djx/bQWkNP6nkE0lH3Lyx7D1aak1Z1erWJ+U130Vz0Sude7mZqv995nW7mZxJd27Sg5XQppuMdWY3xl1XXOge8MasWjZfund0KbvrkE9fK7OPNne+2U9YEWX3nemtSbvLv6LJ7gZ9X45yBl9ZxrZ9d3vjT8rz62tOsny7jXkpYPX9jQmvF8yF55TdaslGviZy1vAmfoTobsZztGNEv7qZZSr/6HRc/0yzlb3HiKhURRBBBBBFEEEEEEUQQQQQRRBD5XSLav38tllbVzeH02Ww/UWA+6XgsHdXFKc2vK5Quoz/duVRnlrb26crpizzXOVU3l2Zb5Pfe+d1OX8ViqW7qH9gt51K44bukr2XxrW54vMaoy7mxa/cgvPRVKcQG7uOCD58HLQLt3r17Iy6AqjYeDG7TUenWW+p9Ot/IOF/lwuHV1nk6o8M469PWXhtr+0BeX/x7Ue40W3xacfb2gXFxUZcX8TYB3Kyfp+GThsjKti2zgZuMiLshxW3gpiQyrn/DXhR/i1NqIte5pkUEEUQQQQQRRBBBBBFEEEEEEUR+g4jQUZBEqjqFO9mOiyeShoXvYoukZOG4GCLpWZgu83/vTNRidhlE0rYAAAAAAAAAAAAAAAAAAACAZPkjwAAMDi+bsnPP/wAAAABJRU5ErkJggg==","$Meta":{"Type":"ActionTemplate"}},{"Id":"38791635-a3fc-4b26-bcd7-b65f0f6de5d2","Name":"Azure - Backup Table Storage to Blob","Description":"This script allow to backup the specified azure table storage into the specified blob.","Version":6,"ExportedAt":"2016-11-30T16:22:50.113Z","ActionType":"Octopus.Script","Author":"phuot","Parameters":[{"Name":"sourceStorageAccountName","Label":"Source Storage Account Name","HelpText":"Name of the source storage account","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"sourceStorageAccountKey","Label":"Source Storage Account Key","HelpText":"Key of the source storage account","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Name":"sourceTableName","Label":"Source Table Name","HelpText":"Name of the Source Azure Table","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"destinationStorageAccountName","Label":"Destination Storage Account Name","HelpText":"Name of the destination storage account","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"destinationStorageAccountKey","Label":"Destination Storage Account Key","HelpText":"Key of the destination storage account","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Name":"IsEnabled","Label":"IsEnabled","HelpText":null,"DefaultValue":"True","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"True\nFalse"}}],"Properties":{"Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.ScriptBody":"if($IsEnabled -eq \"True\")\n{\nWrite-Output \"Starting Backup the Azure table 'https://$sourceStorageAccountName.table.core.windows.net/$sourceTableName' to the Blob 'https://$destinationStorageAccountName.blob.core.windows.net/$sourceStorageAccountName-$sourceTableName'\"\n\n& \"${Env:ProgramFiles(x86)}\\Microsoft SDKs\\Azure\\AzCopy\\azCopy.exe\" `\n /Source:https://$sourceStorageAccountName.table.core.windows.net/$sourceTableName/ `\n /Dest:https://$destinationStorageAccountName.blob.core.windows.net/$sourceStorageAccountName-$sourceTableName/ `\n /SourceKey:$sourceStorageAccountKey `\n /Destkey:$destinationStorageAccountKey `\n /y\n\nWrite-Output \"Backup Completed\"\n}\nelse\n{\n Write-Output \"This Step is disabled\"\n}","Octopus.Action.Script.ScriptFileName":null,"Octopus.Action.Package.NuGetFeedId":null,"Octopus.Action.Package.NuGetPackageId":null},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/Azure-Backup-TableStorage-to-Blob.json","Website":"/step-templates/38791635-a3fc-4b26-bcd7-b65f0f6de5d2","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"}},{"Id":"dd2b147c-3f20-42e1-a94c-17b157a0f0a4","Name":"Azure - Capture AzureRM Virtual Machine Image","Description":"Prepares an AzureRM Virtual Machine (Managed Disk or Storage Account based) and captures a [Managed Image](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/capture-image-resource) or [Image VHD](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/capture-image):\n1. Runs Sysprep\n2. Deallocates & Generalizes VM\n3. Creates Managed Image or Image VHD\n4. Removes virtual machine resource group","Version":1,"ExportedAt":"2017-05-29T18:58:54.733Z","ActionType":"Octopus.AzurePowerShell","Author":"paulmarsy","Parameters":[{"Id":"911668fe-9653-4f08-892c-0e103e72cad0","Name":"StepTemplate_Account","Label":"Octopus Azure Account","HelpText":"Select the [account id](#/accounts) to use for the connection.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"b838a80e-3e49-4788-8302-6b64bf0159ea","Name":"StepTemplate_ResourceGroupName","Label":"Resource Group Name","HelpText":"Name of the Azure Resource Group containing the Virtual Machine.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"8be775a8-53e4-4740-ae0f-10d72f9fdc67","Name":"StepTemplate_VMName","Label":"Virtual Machine Name","HelpText":"The name of the AzureRM Virtual Machine to capture. This VM will be shut down & generalized.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"73dae502-7a82-461c-a82b-8c40f519611f","Name":"StepTemplate_ImageType","Label":"Image Type","HelpText":"Desired type of image to capture from the Virtual Machine.","DefaultValue":"managed","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"managed|Managed Image\nunmanaged|Storage Account VHD"},"Links":{}},{"Id":"111b827b-a2c2-4d57-895e-b18daf9c6344","Name":"StepTemplate_ImageDest","Label":"Image Destination","HelpText":"Where the image should be created.\n\n**Managed Images** should enter a _Resource Group_ name\n\n**Storage Account VHDs** should enter a _Storage Account_ name","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"f461eac4-565c-47e6-8bf0-923f9647e3b2","Name":"StepTemplate_ImageName","Label":"Image Name","HelpText":"Name to use when creating the image.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"ba0ea0f4-710c-4732-8fb4-9f9b4faf325b","Name":"StepTemplate_DeleteVMResourceGroup","Label":"Delete VM Resource Group?","HelpText":"Delete the virtual machine resource group after an image has been captured.\n\n**Once a Virtual Machine is marked as generalized Azure will prevent it from being started or modified.**","DefaultValue":"True","DisplaySettings":{"Octopus.ControlType":"Checkbox"},"Links":{}}],"Properties":{"Octopus.Action.Azure.AccountId":"#{StepTemplate_Account}","Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.ScriptBody":"<#\n ----- Capture AzureRM Virtual Machine Image ----- \n Paul Marston @paulmarsy (paul@marston.me)\nLinks\n https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-capture-virtualmachine-image.json\n \nThe sequence of steps performed by the step template:\n 1) Virtual Machine prep\n a) PowerState/running - Custom script extension is used to sysprep & shutdown\n b) PowerState/stopped - only when the VM is shutdown by the OS, if Azure stops the VM it is automatically deallocated\n c) PowerState/deallocated\n d) OSState/generalized\n 2) Image capture\n - Managed VM & Managed Image - New image with VM as source\n - Managed VM & Unmanaged VHD - Access to the underlying blob is granted, and the VHD copied into the specified storage account\n - Unmanaged VM & Managed Image - New image with VM as source\n - Unmanaged VM & Unmanaged VHD - VM image is saved, a SAS token is generated and it is copied from the VM's storage account into the specified storage account\n 3) Virtual machine cleanup.\n Once a VM has been marked as 'generalized' Azure will no longer allow it to be started up, making the VM unusable\n If the delete option is selected, and the image just created has been moved outside the VM's resource group \n \n----- Advanced Configuration Settings -----\nVariable names can use either of the following two formats: \n Octopus.Action. - will apply to all steps in the deployment, e.g.\n Octopus.Action.DebugLogging\n Octopus.Action[Step Name]. - will apply to 'step name' alone, e.g.\n Octopus.Action[Capture Web VM Image].StorageAccountKey\n\nAvailable Settings:\n VhdDestContainer - overrides the default container that an unmanaged VHD image is copied to, default is 'images'\n StorageAccountKey - allows copying to a storage account in a different subscription by using the providing the key, default is null\n#>\n#Requires -Modules AzureRM.Resources\n#Requires -Modules AzureRM.Compute\n#Requires -Modules AzureRM.Storage\n#Requires -Modules Azure.Storage\n\n$ErrorActionPreference = 'Stop'\n\n<#---------- SysPrep Script - Begin ----------#>\n<#\n Sysprep marker file: C:\\WindowsAzure\\sysprep\n 1) If marker file exists, sysprep has already been run so exit script\n 2) Start a new powershell process and exit with code 0, this allows the custom script extension to report back as having run successfully to Azure\n a) In the child script wait until the successful exit code has been logged\n b) Create the marker file\n c) Run sysprep\n#>\n$SysPrepScript = @'\nif (Test-Path \"${env:SystemDrive}\\WindowsAzure\\sysprep\") { return }\n\nStart-Process -FilePath 'powershell.exe' -ArgumentList @('-NonInteractive','-NoProfile',('-EncodedCommand {0}' -f ([System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes({\n do {\n Start-Sleep -Seconds 1\n $status = Get-ChildItem \"${env:SystemDrive}\\Packages\\Plugins\\Microsoft.Compute.CustomScriptExtension\\*\\Status\\\" -File | Sort-Object LastWriteTime -Descending | Select-Object -First 1 | Get-Content | ConvertFrom-Json\n } while ($status[0].status.code -ne 0)\n New-Item -ItemType File -Path \"${env:SystemDrive}\\WindowsAzure\\sysprep\" -Force | Out-Null\n & (Join-Path -Resolve ([System.Environment]::SystemDirectory) 'sysprep\\sysprep.exe') /oobe /generalize /quiet /shutdown\n}.ToString())))))\n\nexit 0\n'@\n<#---------- SysPrep Script - End ----------#>\n\nfunction Get-OctopusSetting {\n param([Parameter(Position = 0, Mandatory)][string]$Name, [Parameter(Position = 1)]$DefaultValue)\n $formattedName = 'Octopus.Action.{0}' -f $Name\n if ($OctopusParameters.ContainsKey($formattedName)) {\n $value = $OctopusParameters[$formattedName]\n if ($DefaultValue -is [int]) { return ([int]::Parse($value)) }\n if ($DefaultValue -is [bool]) { return ([System.Convert]::ToBoolean($value)) }\n if ($DefaultValue -is [array] -or $DefaultValue -is [hashtable] -or $DefaultValue -is [pscustomobject]) { return (ConvertFrom-Json -InputObject $value) }\n return $value\n }\n else { return $DefaultValue }\n}\nfunction Test-String {\n param([Parameter(Position=0)]$InputObject,[switch]$ForAbsence)\n\n $hasNoValue = [System.String]::IsNullOrWhiteSpace($InputObject)\n if ($ForAbsence) { $hasNoValue }\n else { -not $hasNoValue }\n}\nfilter Out-Verbose {\n Write-Verbose ($_ | Out-String)\n}\nfunction Split-BlobUri {\n param($Uri)\n $uriRegex = [regex]::Match($Uri, '(?>https:\\/\\/)(?[a-z0-9]{3,24})\\.blob\\.core\\.windows\\.net\\/(?[-a-z0-9]{3,63})\\/(?.+)')\n if (!$uriRegex.Success) {\n throw \"Unable to parse blob uri: $Uri\"\n }\n [pscustomobject]@{\n Account = $uriRegex.Groups['Account'].Value\n Container = $uriRegex.Groups['Container'].Value\n Blob = $uriRegex.Groups['Blob'].Value\n }\n}\nfunction Get-AzureRmAccessToken {\n # https://github.com/paulmarsy/AzureRest/blob/master/Internals/Get-AzureRmAccessToken.ps1\n $accessToken = Invoke-RestMethod -UseBasicParsing -Uri ('https://login.microsoftonline.com/{0}/oauth2/token?api-version=1.0' -f $OctopusAzureADTenantId) -Method Post -Body @{\"grant_type\" = \"client_credentials\"; \"resource\" = \"https://management.core.windows.net/\"; \"client_id\" = $OctopusAzureADClientId; \"client_secret\" = $OctopusAzureADPassword }\n [System.Net.Http.Headers.AuthenticationHeaderValue]::new('Bearer', $accessToken.access_token).ToString()\n}\nfunction Get-TemporarySasBlob {\n param($BlobName)\n # https://github.com/paulmarsy/AzureRest/blob/master/Exported/New-AzureBlob.ps1\n $sasToken = Invoke-RestMethod -UseBasicParsing -Uri 'https://mscompute2.iaas.ext.azure.com/api/Compute/VmExtensions/GetTemporarySas/' -Headers @{\n [Microsoft.WindowsAzure.Commands.Common.ApiConstants]::AuthorizationHeaderName = (Get-AzureRmAccessToken)\n }\n $containerSas = [uri]::new($sasToken)\n $container = [Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer]::new($containerSas)\n $blobRef = $container.GetBlockBlobReference($BlobName)\n \n [psobject]@{\n Blob = $blobRef\n Uri = [uri]::new($blobRef.Uri.AbsoluteUri + $containerSas.Query)\n }\n}\n\n'Checking AzureRM Modules...' | Out-Verbose\nGet-Module | ? Name -like 'AzureRM.*' | Format-Table -AutoSize -Property Name,Version | Out-String | Out-Verbose\nif ((Get-Module AzureRM.Compute | % Version) -lt '2.6.0') {\n $bundledErrorMessage = if ([System.Convert]::ToBoolean($OctopusUseBundledAzureModules)) {\n 'The Azure PowerShell Modules bundled with Octopus have been loaded. To use the version installed on the server create a variable named \"Octopus.Action.Azure.UseBundledAzurePowerShellModules\" and set its value to \"False\".'\n }\n throw \"${bundledErrorMessage}Please ensure version 2.6.0 or newer of the AzureRM.Compute module has been installed. The module can be installed with the PowerShell command: Install-Module AzureRM.Compute -MinimumVersion 2.6.0\"\n}\n\n$vm = Get-AzureRmVM -ResourceGroupName $StepTemplate_ResourceGroupName -Name $StepTemplate_VMName -WarningAction SilentlyContinue\nif ($null -eq $vm) {\n throw \"Unable to find virtual machine '$StepTemplate_VMName' in resource group '$StepTemplate_ResourceGroupName'\"\n}\nWrite-Host \"Image will be captured from Virtual Machine '$($vm.Name)' in resource group '$($vm.ResourceGroupName)'\"\nif (Test-String $StepTemplate_ImageDest -ForAbsence) {\n throw \"The Image Destination parameter is required\"\n}\n$StepTemplate_ImageStorageContext = if ($StepTemplate_ImageType -eq 'unmanaged') {\n $storageAccountKey = Get-OctopusSetting StorageAccountKey $null\n if (Test-String $storageAccountKey) {\n Write-Host \"Image will be copied to storage account context '$StepTemplate_ImageDest' using provided key\"\n New-AzureStorageContext -StorageAccountName $StepTemplate_ImageDest -StorageAccountKey $storageAccountKey\n } else {\n $storageAccountResource = Find-AzureRmResource -ResourceNameEquals $StepTemplate_ImageDest -ResourceType Microsoft.Storage/storageAccounts\n if ($storageAccountResource) {\n Write-Host \"Image will be copied to storage account '$($storageAccountResource.Name)' found in resource group '$($storageAccountResource.ResourceGroupName)'\"\n } else {\n throw \"Unable to find storage account '$StepTemplate_ImageDest'\"\n }\n Get-AzureRmStorageAccount -ResourceGroupName $storageAccountResource.ResourceGroupName -Name $storageAccountResource.Name | % Context\n }\n}\n$StepTemplate_ImageResourceGroupName = switch ($StepTemplate_ImageType) {\n 'managed' {\n $resourceGroup = Get-AzureRmResourceGroup -Name $StepTemplate_ImageDest | % ResourceGroupName \n Write-Host \"Managed Image will be created in resource group '$resourceGroup'\"\n $resourceGroup\n }\n 'unmanaged' { Find-AzureRmResource -ResourceNameEquals $StepTemplate_ImageDest -ResourceType Microsoft.Storage/storageAccounts | % ResourceGroupName }\n}\nif ($StepTemplate_ImageResourceGroupName -ieq $StepTemplate_ResourceGroupName -and $StepTemplate_DeleteVMResourceGroup -ieq 'True') {\n throw \"You have chosen to delete the virtual machine and it's resource group ($StepTemplate_ResourceGroupName), however this resource group is also where the captured image will be created!\"\n}\n\nWrite-Host ('-'*80)\nWrite-Host \"Preparing virtual machine $($vm.Name) for image capture...\"\n\n$sysprepRun = $false\nwhile ($true) {\n $statusCode = Get-AzureRmVM -ResourceGroupName $StepTemplate_ResourceGroupName -Name $StepTemplate_VMName -Status -WarningAction SilentlyContinue | % Statuses | % Code\n if ($statusCode -contains 'OSState/generalized') {\n Write-Host 'VM is deallocated & generalized, proceeding to image capture...'\n break\n }\n if ($statusCode -contains 'PowerState/deallocated') {\n Write-Host 'VM has been deallocated, setting state to generalized... '\n Set-AzureRmVM -ResourceGroupName $StepTemplate_ResourceGroupName -Name $StepTemplate_VMName -Generalized | Out-Verbose\n continue\n }\n if ($statusCode -contains 'PowerState/deallocating') {\n Write-Host 'VM is deallocating, waiting...'\n Start-Sleep 30\n continue\n }\n if ($statusCode -contains 'PowerState/stopped') {\n Write-Host 'VM has been shutdown, starting deallocation...'\n Stop-AzureRmVm -ResourceGroupName $StepTemplate_ResourceGroupName -Name $StepTemplate_VMName -Force | Out-Verbose\n continue\n }\n if ($statusCode -contains 'PowerState/stopping') {\n Write-Host 'VM is stopping, waiting...'\n Start-Sleep 30\n continue\n }\n if ($statusCode -contains 'PowerState/running' -and $sysprepRun) {\n Write-Host 'VM is running, but sysprep already deployed, waiting...'\n Start-Sleep 30\n continue\n }\n if ($statusCode -contains 'PowerState/running') {\n Write-Host 'VM is running, performing sysprep...'\n $existingCustomScriptExtensionName = $vm.Extensions | ? VirtualMachineExtensionType -eq 'CustomScriptExtension' | % Name\n if ($existingCustomScriptExtensionName) {\n Write-Warning \"Removing existing CustomScriptExtension ($existingCustomScriptExtensionName)...\"\n Remove-AzureRmVMCustomScriptExtension -ResourceGroupName $StepTemplate_ResourceGroupName -VMName $StepTemplate_VMName -Name $existingCustomScriptExtensionName -Force | Out-Verbose\n }\n \n Write-Host 'Uploading sysprep script to blob storage...'\n $sysprepScriptFileName = 'Sysprep.ps1'\n $sysprepScriptBlob = Get-TemporarySasBlob $sysprepScriptFileName\n $sysprepScriptBlob.Blob.UploadText($SysPrepScript)\n \n Write-Host 'Deploying sysprep custom script extension...'\n Set-AzureRmVMCustomScriptExtension -ResourceGroupName $StepTemplate_ResourceGroupName -VMName $StepTemplate_VMName -Name 'Sysprep' -Location $vm.Location -FileUri $sysprepScriptBlob.Uri -Run $sysprepScriptFileName -ForceRerun (Get-Date).Ticks | Out-Verbose\n $sysprepRun = $true\n continue\n }\n Write-Warning \"VM is in an unknown state. Current status codes: $($statusCode -join ', '). Waiting...\"\n Start-Sleep -Seconds 30\n}\n\nWrite-Host ('-'*80)\n\nWrite-Host 'Retrieving virtual machine disk configuration...'\n$vm = Get-AzureRmVM -ResourceGroupName $StepTemplate_ResourceGroupName -Name $StepTemplate_VMName -WarningAction SilentlyContinue \n$isManagedVm = $null -ne $vm.StorageProfile.OsDisk.ManagedDisk\nif ($isManagedVm) { Write-Host \"Virtual machine $($vm.Name) is using Managed Disks\" }\n$isUnmanagedVm = $null -ne $vm.StorageProfile.OsDisk.Vhd\nif ($isUnmanagedVm) { Write-Host \"Virtual machine $($vm.Name) is using unmanaged storage account VHDs\" }\n\nif ($StepTemplate_ImageType -eq 'managed') {\n Write-Host \"Creating Managed Image of $($vm.Name)...\"\n $image = New-AzureRmImageConfig -Location $vm.Location -SourceVirtualMachineId $vm.Id\n New-AzureRmImage -Image $image -ImageName $StepTemplate_ImageName -ResourceGroupName $StepTemplate_ImageResourceGroupName | Out-Verbose\n Write-Host 'Image created:'\n Get-AzureRmImage -ImageName $StepTemplate_ImageName -ResourceGroupName $StepTemplate_ImageResourceGroupName | Out-Host\n}\n\nif ($StepTemplate_ImageType -eq 'unmanaged') {\n if ($isManagedVm) {\n Write-Host \"Granting access to os disk ($($vm.StorageProfile.OsDisk.Name)) blob...\"\n $manageDisk = Grant-AzureRmDiskAccess -ResourceGroupName $StepTemplate_ResourceGroupName -DiskName $vm.StorageProfile.OsDisk.Name -DurationInSecond 3600 -Access Read \n $vhdSasUri = $manageDisk.AccessSAS\n }\n if ($isUnmanagedVm) {\n Write-Host \"Saving Unmanaged Image of $($vm.Name)...\"\n $armTemplatePath = [System.IO.Path]::GetTempFileName()\n $vhdDestContainer = Get-OctopusSetting VhdDestContainer 'images'\n Save-AzureRmVMImage -ResourceGroupName $StepTemplate_ResourceGroupName -Name $StepTemplate_VMName -DestinationContainerName $vhdDestContainer -VHDNamePrefix $StepTemplate_ImageName -Overwrite -Path $armTemplatePath | Out-Verbose\n $armTemplate = Get-Content -Path $armTemplatePath\n \"VM Image ARM Template:`n$armTemplate\" | Out-Verbose\n Remove-Item $armTemplatePath -Force\n $osDiskUri = ($armTemplate | ConvertFrom-Json).resources.properties.storageprofile.osdisk.image.uri\n \"OS Disk Image URI: $osDiskUri\" | Out-Verbose\n $unmanagedVhd = Split-BlobUri $osDiskUri\n \n Write-Host \"Granting access to vhd image ($($unmanagedVhd.Blob))...\"\n $unmanagedVhdStorageResource = Find-AzureRmResource -ResourceNameEquals $unmanagedVhd.Account -ResourceType Microsoft.Storage/storageAccounts\n $unmanagedVhdStorageResource | Out-Verbose\n $unmanagedVhdStorageContext = Get-AzureRmStorageAccount -ResourceGroupName $unmanagedVhdStorageResource.ResourceGroupName -Name $unmanagedVhdStorageResource.Name | % Context\n $vhdSasUri = New-AzureStorageBlobSASToken -Container $unmanagedVhd.Container -Blob $unmanagedVhd.Blob -Permission r -ExpiryTime (Get-Date).AddHours(1) -FullUri -Context $unmanagedVhdStorageContext\n }\n Write-Host \"Source image SAS token created: $vhdSasUri\"\n\n Write-Host 'Copying image to storage account...'\n $destContainerName = Get-OctopusSetting VhdDestContainer 'images'\n $destContainer = Get-AzureStorageContainer -Name $destContainerName -Context $StepTemplate_ImageStorageContext -ErrorAction SilentlyContinue\n if ($destContainer) {\n Write-Host \"Using container '$destContainerName' in storage account $StepTemplate_ImageDest...\"\n } else {\n Write-Host \"Creating container '$destContainerName' in storage account $StepTemplate_ImageDest...\"\n $destContainer = New-AzureStorageContainer -Name $destContainerName -Context $StepTemplate_ImageStorageContext -Permission Off\n }\n\n $copyBlob = Start-AzureStorageBlobCopy -AbsoluteUri $vhdSasUri -DestContainer $destContainerName -DestContext $StepTemplate_ImageStorageContext -DestBlob $StepTemplate_ImageName -Force\n $copyBlob | Out-Verbose\n do { \n if ($copyState.Status -eq 'Pending') {\n Start-Sleep -Seconds 60\n }\n $copyState = $copyBlob | Get-AzureStorageBlobCopyState\n $copyState | Out-Verbose\n $percent = ($copyState.BytesCopied / $copyState.TotalBytes) * 100\n Write-Host \"Blob transfer $($copyState.Status.ToString().ToLower())... $('{0:N2}' -f $percent)% @ $([System.Math]::Round($copyState.BytesCopied/1GB, 2))GB / $([System.Math]::Round($copyState.TotalBytes/1GB, 2))GB\"\n } while ($copyState.Status -eq 'Pending')\n Write-Host \"Final image transfer status: $($copyState.Status)\"\n \n if ($isManagedVm) {\n Write-Host 'Revoking access to os disk blob...'\n Revoke-AzureRmDiskAccess -ResourceGroupName $StepTemplate_ResourceGroupName -DiskName $vm.StorageProfile.OsDisk.Name | Out-Verbose\n }\n}\n\nWrite-Host \"Image of $($vm.Name) captured successfully!\"\n\nif ($StepTemplate_DeleteVMResourceGroup -ieq 'True') {\n Write-Host ('-'*80)\n Write-Host \"Removing $($vm.Name) VM's resource group $StepTemplate_ResourceGroupName, the following resources will be deleted...\"\n Find-AzureRmResource -ResourceGroupNameEquals $StepTemplate_ResourceGroupName | Sort-Object -Property ResourceId -Descending | Select-Object -Property ResourceGroupName,ResourceType,ResourceName | Format-Table -AutoSize | Out-Host\n Remove-AzureRmResourceGroup -Name $StepTemplate_ResourceGroupName -Force | Out-Verbose\n}","Octopus.Action.Package.FeedId":null,"Octopus.Action.Script.ScriptFileName":null,"Octopus.Action.Package.PackageId":null},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-capture-virtualmachine-image.json","Website":"/step-templates/dd2b147c-3f20-42e1-a94c-17b157a0f0a4","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"}},{"Id":"bf955a12-57ee-41b0-af58-672ca48ea07d","Name":"Azure - Copy Storage Account Containers","Description":"Copy blobs between specified containers across two different storage accounts","Version":1,"ExportedAt":"2016-05-12T03:09:48.287+00:00","ActionType":"Octopus.Script","Author":"ahmedig","Parameters":[{"Name":"SourceStorageAccountName","Label":"Source Storage Account Name","HelpText":null,"DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"SourceStorageAccountKey","Label":"Source Storage Account Key","HelpText":null,"DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"SourceContainerName","Label":"Source Container Name","HelpText":null,"DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"SourceBlobPrefix","Label":"Source Blob Prefix (Optional)","HelpText":null,"DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"DestinationStorageAccountName","Label":"Destination Storage Account Name","HelpText":null,"DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"DestinationStorageAccountKey","Label":"Destination Storage Account Key","HelpText":null,"DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"DestinationContainerName","Label":"Destination Container Name","HelpText":null,"DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"DestinationBlobPrefix","Label":"Destination Blob Prefix (Optional)","HelpText":null,"DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.ScriptBody":"# Define the source storage account and context\n$SourceStorageAccountName = $OctopusParameters['SourceStorageAccountName'];\n$SourceStorageAccountKey = $OctopusParameters['SourceStorageAccountKey'];\n$SourceContainerName = $OctopusParameters['SourceContainerName'];\n$SourceContext = New-AzureStorageContext -StorageAccountName $SourceStorageAccountName -StorageAccountKey $SourceStorageAccountKey\n$SourceBlobPrefix = $OctopusParameters['SourceBlobPrefix'];\n\n# Define the destination storage account and context\n$DestinationStorageAccountName = $OctopusParameters['DestinationStorageAccountName'];\n$DestinationStorageAccountKey = $OctopusParameters['DestinationStorageAccountKey'];\n$DestinationContainerName = $OctopusParameters['DestinationContainerName'];\n$DestinationContext = New-AzureStorageContext -StorageAccountName $DestinationStorageAccountName -StorageAccountKey $DestinationStorageAccountKey\n$DestinationBlobPrefix = $OctopusParameters['DestinationBlobPrefix'];\n\n# Check if container exists, otherwise create it\n$isContainerExist = Get-AzureStorageContainer -Context $DestinationContext | Where-Object { $_.Name -eq $DestinationContainerName }\nif($isContainerExist -eq $null)\n{\n New-AzureStorageContainer -Name $DestinationContainerName -Context $DestinationContext\n}\n\n# Get a reference to blobs in the source container\n$blobs = $null\nif ($SourceBlobPrefix -eq $null) {\n $blobs = Get-AzureStorageBlob -Container $SourceContainerName -Context $SourceContext\n}\nelse {\n $blobs = Get-AzureStorageBlob -Container $SourceContainerName -Context $SourceContext -Prefix $SourceBlobPrefix\n}\n\n# Copy blobs from one container to another\nif ($DestinationBlobPrefix -eq $null) {\n\t$blobs | Start-AzureStorageBlobCopy -DestContainer $DestinationContainerName -DestContext $DestinationContext\n}\nelse {\n\t$uri = $SourceContext.BlobEndPoint + $SourceContainerName +\"/\" \n\t$blobs | ForEach-Object `\n \t{ Start-AzureStorageBlobCopy `\n\t -SrcUri \"$uri$($_.Name)\" `\n -Context $SourceContext `\n\t -DestContext $DestinationContext `\n\t -DestContainer $DestinationContainerName `\n\t -DestBlob \"$DestinationBlobPrefix/$($_.Name)\" `\n\t } \n}\n ","Octopus.Action.Script.ScriptFileName":null,"Octopus.Action.Package.NuGetFeedId":null,"Octopus.Action.Package.NuGetPackageId":null},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/Azure-Container-Copy-to-another-Container.json","Website":"/step-templates/bf955a12-57ee-41b0-af58-672ca48ea07d","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"}},{"Id":"24ab7967-8ae5-4852-bfdf-4e81d57245f6","Name":"Azure - Copy Storage Account Containers AZCopy Inline","Description":"Copies Storage Account containers, from a source storage account to destination. It copies the containers with the same names.","Version":2,"ExportedAt":"2016-07-24T12:55:38.909+00:00","ActionType":"Octopus.Script","Author":"ahmedig","Parameters":[{"Name":"SourceStorageAccountName","Label":"Source Storage Account Name","HelpText":"Storage Account Name of the source storage account","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"SourceStorageAccountKey","Label":"Source Storage Account Key","HelpText":"Storage Account Key of the source storage account","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"DestinationStorageAccountName","Label":"Destination Storage Account Name","HelpText":"Storage Account Name of the destination storage account","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"DestinationStorageAccountKey","Label":"Destination Storage Account Key","HelpText":"Storage Account key of the destination storage account","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"ContainersIncluded","Label":"Containers Included","HelpText":"A comma separated list of containers that will be copied only, and all the rest will be excluded. If this value is filled with a value, the \"Containers Excluded\" value will be neglected.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"ContainersExcluded","Label":"Containers Excluded","HelpText":"A comma separated list of containers that will be excluded. All containers in source storage account will be copied to destination except these containers. Please note that if the \"Containers Included\" has a value, the \"Containers Excluded\" will be neglected.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"$SourceStorageAccountName = $OctopusParameters['SourceStorageAccountName'];\n$SourceStorageAccountKey = $OctopusParameters['SourceStorageAccountKey'];\n$DestinationStorageAccountName = $OctopusParameters['DestinationStorageAccountName'];\n$DestinationStorageAccountKey = $OctopusParameters['DestinationStorageAccountKey'];\n$ContainersIncluded = $OctopusParameters['ContainersIncluded'];\n$ContainersExcluded = $OctopusParameters['ContainersExcluded'];\n\n$AzCopy = Join-Path ${env:ProgramFiles(x86)} \"Microsoft SDKs\\Azure\\AzCopy\\AzCopy.exe\"\n\nfunction AzCopyContainer($containerName)\n{\n &$AzCopy /Source:http://$($SourceStorageAccountName).blob.core.windows.net/$containerName `\n\t/Dest:http://$($DestinationStorageAccountName).blob.core.windows.net/$containerName `\n\t/SourceKey:$SourceStorageAccountKey `\n\t/DestKey:$DestinationStorageAccountKey `\n\t/S /XO /XN /V | Out-Host\n}\n\n# List all Containers\n$ctx = New-AzureStorageContext -StorageAccountName $SourceStorageAccountName -StorageAccountKey $SourceStorageAccountKey\n$containers = Get-AzureStorageContainer -Context $ctx\n\n\t\n# If Containers Included is there => Copy Included Only \nif($ContainersIncluded)\n{\n\t# Parse the Included list\n\t$ContainersIncluded.Split(\",\") | foreach {\n\t\tAzCopyContainer $_\n\t}\n}\n\n# If Containers Excluded is there, and no Included => Copy all except excluded\nelseif(!$ContainersIncluded -and $ContainersExcluded)\n{\n\t#Parse the exclusion list\n\t[Collections.Generic.List[String]]$lst = $ContainersExcluded.Split(\",\")\n\n\t# Loop through all the containers, and\n\tforeach ($container in $containers) \n\t{\n\t\tif($lst.Contains($container.Name)) {\n\t\t\tcontinue\n\t\t}\n\t\telse \n\t\t{\n\t\t\t$containerName = $container.Name\n AzCopyContainer $containerName\n\t\t}\n\t} \n}\n\n# Copy all containers\nelse\n{\n\t# Loop through all the containers, and\n\tforeach ($container in $containers) \n\t{\n\t\t$containerName = $container.Name\n AzCopyContainer $containerName\n\t} \n}","Octopus.Action.Script.ScriptFileName":null,"Octopus.Action.Package.NuGetFeedId":null,"Octopus.Action.Package.NuGetPackageId":null},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/Azure-CopySelectiveStorageAccountContainersUsingAZCopy.json","Website":"/step-templates/24ab7967-8ae5-4852-bfdf-4e81d57245f6","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"}},{"Id":"7351a3e7-df59-4e0c-863a-dca6f33ad2e1","Name":"Azure - Remove Resource Group Deployments","Description":"There is a cap in Azure that prevents having more than 800 deployments in the history at any given time: link to microsoft docs\n\nThis script helps alleviate this issue by limiting how many deployments are allowed exist, keeps the latest specified number of deployments, and will remove the rest.\n\nWhat it does: Logs into Azure, selects the resource group of the app. Based on how many deployments it wants to keep, it will keep the latest X deployments and remove the rest. If there are less deployments than X to keep, the script will skip.","Version":2,"ExportedAt":"2019-04-25T13:33:59.856Z","ActionType":"Octopus.AzurePowerShell","Author":"bmdixon","Packages":[],"Parameters":[{"Id":"30a798bd-db11-44d3-82bd-28c3b13e77a5","Name":"AzureSubscriptionAccount","Label":"Azure Subscription Account","HelpText":null,"DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"27c68d1f-7fdc-4e10-aa4a-77a0ff55eb29","Name":"Azure.RemoveResourceGroupDeployments.ResourceGroupName","Label":"Resource Group Name","HelpText":"Enter the name of the resource group.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"2adcf1a9-d319-4ed3-80e7-4c533ddbe5cd","Name":"Azure.RemoveResourceGroupDeployments.NumberOfDeploymentsToKeep","Label":"Number Of Deployments To Keep","HelpText":"Number Of Deployments To Keep. Defaults to empty and will not be used.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"c5ce930b-ea04-42b8-8ade-d167a26dab2a","Name":"Azure.RemoveResourceGroupDeployments.NumberOfDaysToKeep","Label":"Number Of Days To Keep.","HelpText":"Number Of Days To Keep. Defaults to empty and will not be used.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Azure.AccountId":"#{AzureSubscriptionAccount}","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"function Get-Param($Name, [switch]$Required, $Default) {\n $result = $null\n\n if ($null -ne $OctopusParameters) {\n $result = $OctopusParameters[$Name]\n }\n\n if ($null -eq $result) {\n $variable = Get-Variable $Name -EA SilentlyContinue\n if ($null -ne $variable) {\n $result = $variable.Value\n }\n }\n\n if ($null -eq $result) {\n if ($Required) {\n throw \"Missing parameter value $Name\"\n }\n else {\n $result = $Default\n }\n }\n\n return $result\n}\n\nFunction Get-Deployments {\n Param(\n [Parameter(Mandatory = $true)]\n [string]$resourceGroupName\n )\n $listOfDeployments = Get-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName\n $azureDeploymentNameAndDate = @()\n $listOfDeployments | ForEach-Object { $azureDeploymentNameAndDate += [PSCustomObject]@{DeploymentName = $_.DeploymentName; Time = $_.Timestamp } }\n\n return $azureDeploymentNameAndDate\n}\n\nFunction Remove-AzureRmResourceDeployments {\n\n [CmdletBinding()]\n Param(\n [Parameter(Mandatory = $true)]\n [string]$resourceGroupName,\n\n [ValidateRange(0, 800)]\n [int]$numberOfDeploymentsToKeep,\n\n [int]$numberOfDaysToKeep\n )\n\n if ($null -ne $($numberOfDaysToKeep) -and $($numberOfDaysToKeep) -gt 0) {\n $azureDeploymentNameAndDate = Get-Deployments $resourceGroupName\n\n Write-Output \"Found $($azureDeploymentNameAndDate.Count) deployments from the $resourceGroupName resource group\"\n\n $itemsToRemove = $azureDeploymentNameAndDate | Where-Object { $_.Time -lt ((get-date).AddDays( - $($numberOfDaysToKeep))) }\n $numberOfItemsToRemove = $itemsToRemove | Measure-Object\n\n if ($numberOfitemsToRemove.Count -eq 0) {\n Write-Output \"There are no deployments older than $($numberOfDaysToKeep) days old in $($resourceGroupName)... skipping\"\n }\n else {\n Write-Output \"Deleting $($numberOfitemsToRemove.Count) deployment(s) from $($resourceGroupName) as they are more than $($numberOfDaysToKeep) days old.\"\n $itemsToRemove | ForEach-Object { Write-Output \"Deleting $($_.DeploymentName)\"; Remove-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -name $_.DeploymentName }\n }\n }\n\n if ($null -ne $($numberOfDeploymentsToKeep) -and $($numberOfDeploymentsToKeep) -gt 0) {\n $azureDeploymentNameAndDate = Get-Deployments $resourceGroupName\n\n Write-Output \"Found $($azureDeploymentNameAndDate.Count) deployments from the $resourceGroupName resource group\"\n\n $itemsToRemove = $azureDeploymentNameAndDate | Sort-Object Time -Descending | select-object -skip $numberOfDeploymentsToKeep\n $numberOfItemsToRemove = $itemsToRemove | Measure-Object\n\n if ($numberOfitemsToRemove.Count -eq 0) {\n Write-Output \"Max number of deployments set to keep is $numberOfDeploymentsToKeep... skipping\"\n }\n else {\n Write-Output \"Maximum number of deployments exceeded. Deleting $($numberOfitemsToRemove.Count) deployment(s) from $($resourceGroupName)\"\n $itemsToRemove | ForEach-Object { Write-Output \"Deleting $($_.DeploymentName)\"; Remove-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -name $_.DeploymentName }\n }\n }\n}\n\n## --------------------------------------------------------------------------------------\n## Input\n## --------------------------------------------------------------------------------------\n\n$resourceGroupName = Get-Param 'Azure.RemoveResourceGroupDeployments.ResourceGroupName' -Required\n$numberOfDeploymentsToKeep = Get-Param 'Azure.RemoveResourceGroupDeployments.NumberOfDeploymentsToKeep' -Default 0\n$numberOfDaysToKeep = Get-Param 'Azure.RemoveResourceGroupDeployments.NumberOfDaysToKeep' -Default 0\n\nRemove-AzureRmResourceDeployments -resourceGroupName $resourceGroupName -numberOfDeploymentsToKeep $numberOfDeploymentsToKeep -numberOfDaysToKeep $numberOfDaysToKeep -Verbose\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-remove-resource-group-deployments.json","Website":"/step-templates/7351a3e7-df59-4e0c-863a-dca6f33ad2e1","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"}},{"Id":"72a32f48-2de9-4dac-9c47-b491413478e2","Name":"Azure - Set Web App SSL Certificate","Description":"Configures the SSL binding for an Azure Web App to use an [Octopus-managed certificate](https://octopus.com/docs/deploying-applications/certificates)","Version":1,"ExportedAt":"2018-03-29T00:48:05.333Z","ActionType":"Octopus.AzurePowerShell","Author":"MJRichardson","Parameters":[{"Id":"a8d7da9d-39d6-4bcd-9a08-fe81210e364c","Name":"SslAzureSubscription","Label":"Azure Subscription","HelpText":null,"DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"},"Links":{}},{"Id":"4b978b3d-4f87-49d7-b814-14e2f9ef878a","Name":"SslWebApp","Label":"Azure Web App","HelpText":"The name of the Azure Web App for which the SSL binding will be created.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"df5ee03d-1a63-44c0-b3c4-d75020b1f2b8","Name":"SslResourceGroup","Label":"Resource Group","HelpText":"The name of the Azure Resource Group containing the Web App","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"ff318b09-27de-483c-a9c8-b0583e15208c","Name":"SslSlot","Label":"Slot","HelpText":"The Azure Deployment Slot (optional)","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"9f488222-f373-4f70-841b-3f340357bb85","Name":"SslDomainName","Label":"Domain Name","HelpText":"The fully qualified domain name for the SSL binding. e.g. store.acme.com","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"b8bda333-894a-4223-a07d-afb336b8f75f","Name":"SslCertificate","Label":"Certificate","HelpText":"The certificate to be used for the SSL binding","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Certificate"},"Links":{}},{"Id":"b9c953f5-a21d-4c64-b134-7295d6d7d48e","Name":"SslState","Label":"SSL State","HelpText":"Specifies the SSL state of the certificate","DefaultValue":"SniEnabled","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"SniEnabled\nIpBasedEnabled\nDisabled"},"Links":{}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Azure.AccountId":"#{SslAzureSubscription}","Octopus.Action.Script.ScriptBody":"<#\nTakes an Octopus certificate variable and\n 1) Writes it to a temporary file with a password (as Azure requires the PFX have a password)\n 2) Invokes New-AzureRmWebAppSSLBinding\n 3) Removes the temporary certificate file\n#>\n\n$ErrorActionPreference = 'Stop'\n\nWrite-Verbose \"Creating temporary certificate file\"\n$TempCertificateFile = New-TemporaryFile\n# The PFX upload to Azure must have a password. So we give it a GUID.\n$Password = [guid]::NewGuid().ToString(\"N\")\n\n$CertificateName = $OctopusParameters[\"SslCertificate.Name\"]\n\nWrite-Host \"Creating HTTPS binding on web app '$SslWebApp' for domain $SslDomainName using certificate '$CertificateName' \"\n\n$CertificateBytes = [Convert]::FromBase64String($OctopusParameters[\"SslCertificate.Pfx\"])\n[IO.File]::WriteAllBytes($TempCertificateFile.FullName, $CertificateBytes)\nGet-PfxData -FilePath $TempCertificateFile.FullName | Export-PfxCertificate -FilePath $TempCertificateFile.FullName -Password (ConvertTo-SecureString -String $Password -AsPlainText -Force)\n\n$BindingParams = @{\n WebAppName = $SslWebApp\n ResourceGroupName = $SslResourceGroup\n Name = $SslDomainName\n CertificateFilePath = $TempCertificateFile.FullName\n CertificatePassword = $Password\n SslState = $SslState\n}\n\nif ($SslSlot) { $BindingParams['Slot'] = $SslSlot }\n\nNew-AzureRmWebAppSSLBinding @BindingParams\n\nWrite-Verbose \"Removing temporary certificate file\"\nRemove-Item $TempCertificateFile.FullName -Force"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-web-app-ssl.json","Website":"/step-templates/72a32f48-2de9-4dac-9c47-b491413478e2","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"}},{"Id":"8a0a75da-4960-40ca-b641-5ed2305fa655","Name":"Azure - Sync Instance Count","Description":"This step template is useful when you want to have the instance count matched just before the VIP swap. It takes the source slot (usually Production slot) and match with the current deployment slot (normally Staging). Note: This will be helpful in scenario when 15 instances in Production and 4 instance in staging. This step template should only be used when a production slot already exists.","Version":7,"ExportedAt":"2015-06-18T13:48:39.548+00:00","ActionType":"Octopus.Script","Author":"mani0070","Parameters":[{"Name":"sourceslot","Label":"Specify the Slot to Get Instance Count","HelpText":"This is usually Production Slot to obtain the Count and match to staging before swap.","DefaultValue":"Production","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"# Current Cloud Service name \n$ServiceName =$octopusparameters[\"Octopus.Action.Azure.CloudServiceName\"]\n\n$deployment = Get-AzureDeployment -slot $sourceslot -serviceName $serviceName\n# Obtain the instance count and role name.\n$SourceInstanceCount =$deployment.RolesConfiguration.values.InstanceCount\n$rolenameService = $deployment.RolesConfiguration.values.Name\n#Set the Current deployment slot instance count to match production count\nSet-AzureRole -ServiceName $serviceName -Slot $octopusparameters[\"Octopus.Action.Azure.Slot\"] -RoleName $rolenameService -Count $SourceInstanceCount "},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-sync-instancecount-from-prod-to-staging.json","Website":"/step-templates/8a0a75da-4960-40ca-b641-5ed2305fa655","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"}},{"Id":"bc18b460-06a7-412f-850f-44098f1b497a","Name":"Azure - Upload Files to Azure","Description":"Uploads files and folders to an Azure container from a specified location.\n\n**IMPORTANT:** Azure PowerShell must be installed on the tentacle server for this step to work. This can be downloaded from http://bit.ly/AzurePowershellDownload","Version":8,"ExportedAt":"2016-10-25T19:17:25.877+00:00","ActionType":"Octopus.Script","Author":"kemyke","Parameters":[{"Id":"4cb76611-ff29-4256-9475-3769fd890e0f","Name":"storageAccountName","Label":"Azure Storage Account Name","HelpText":"Name of the account that the files and folders will be uploaded to.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"cc0eb63d-4545-4d9d-aca3-7844e1e0a54e","Name":"storageAccountKey","Label":"Azure Storage Account Key","HelpText":"The key that is used to log into the account.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"8245c4b0-014d-467c-a95d-ab6aac230075","Name":"containerName","Label":"Azure Container Name","HelpText":"The name of the container the files and folder will be uploaded to.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"45f6df33-d04d-44bd-8a26-1ab45c634afc","Name":"localFolder","Label":"Name of the Parent Folder","HelpText":"Name of the Parent Folder being uploaded","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"8c559f0f-2d6e-4202-8614-65cabb29e643","Name":"doRecurse","Label":"Recursive","HelpText":null,"DefaultValue":"True","DisplaySettings":{"Octopus.ControlType":"Checkbox"}},{"Id":"8a06615b-69a2-4d32-be29-981b6c5725fc","Name":"doForce","Label":"Force","HelpText":"Override is enabled or not","DefaultValue":"False","DisplaySettings":{"Octopus.ControlType":"Checkbox"}}],"Properties":{"Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"#Sets the Permissions to public if the selection is true\nif ([boolean]::Parse($doRecurse)) \n{\n \n\t$recurse = \"-Recurse\"\n\n}\n\nif ([boolean]::Parse($doForce)) \n{\n \n\t$force = \"-Force\"\n\n}\n\n#--------------------------------------------------------------------\n#Checking to see if Azure is installed on the computer\n$name = 'Azure'\n\nWrite-Output \"Checking if Azure Powershell is installed\"\n\nif(Get-Module -ListAvailable | Where-Object {$_.name -eq $name})\n{\n\t(Get-Module -ListAvailable | Where-Object{ $_.Name -eq $name}) |\n\tSelect Version, Name, Author, PowerShellVersion | Format-List;\n\tWrite-Output \"Azure Powershell is installed\"\n}\nelse\n{\n\t#Provides the link to install Azure Powershell, if it is not installed\n\tWrite-Warning \"Please install Azure Powershell. To install Azure Powershell go to http://bit.ly/AzurePowershellDownload\"\n\tExit 1\n}\n\n\n\n#--------------------------------------------------------------------\n\n#Initialises the Azure Credentials based on the Storage Account Name and the Storage Account Key, \n#so that we can invoke the APIs further down. \n$storageContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKey\n\n#--------------------------------------------------------------------\n\nGet-ChildItem -Path $localFolder -File $recurse | Set-AzureStorageBlobContent -Container $containerName -Blob $blobName -Context $storageContext $force\n\nWrite-Output \"All files in $localFolder uploaded to $containerName!\"\n","Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.RunOnServer":"false","Octopus.Action.Script.ScriptFileName":null,"Octopus.Action.Package.FeedId":null,"Octopus.Action.Package.PackageId":null},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-upload-files.json","Website":"/step-templates/bc18b460-06a7-412f-850f-44098f1b497a","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"}},{"Id":"ac7868f9-dc5c-42b8-ab8c-0c1e801f6957","Name":"Azure Administer WebJob","Description":"Start, Stop, or Delete a WebJob from the Azure Web App","Version":2,"ExportedAt":"2015-11-23T20:15:06.113+00:00","ActionType":"Octopus.Script","Author":"dustinchilson","Parameters":[{"Name":"WebJobWebApp","Label":"Web App","HelpText":"The Web App the Azure WebJob is hosted under.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"WebJobUserName","Label":"User Name","HelpText":"The Username of the authentication to the Kudu Api.\n\nSee https://github.com/projectkudu/kudu/wiki/Deployment-credentials","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"WebJobPassword","Label":"Password","HelpText":"The Password of the authentication to the Kudu Api.\n\nSee https://github.com/projectkudu/kudu/wiki/Deployment-credentials","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Name":"WebJobAction","Label":"Action","HelpText":"The action to perform. Start, Stop, or Delete.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"start|Start\nstop|Stop\ndelete|Delete"}},{"Name":"WebJobType","Label":"Job Type","HelpText":"The type of job, Continuous or Triggered","DefaultValue":"continuouswebjobs","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"continuouswebjobs|Continuous\ntriggeredwebjobs|Triggered"}},{"Name":"WebJobName","Label":"Job Name","HelpText":"The name of the Job to act upon.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"$httpAction = 'POST'\n\nif ($WebJobAction -eq 'delete') {\n $httpAction = 'DELETE'\n}\n\n$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes((\"{0}:{1}\" -f $WebJobUserName,$WebJobPassword)))\n$apiUrl = \"https://$WebJobWebApp.scm.azurewebsites.net/api/$WebJobType/$WebJobName/$WebJobAction\"\nInvoke-RestMethod -Uri $apiUrl -Headers @{Authorization=(\"Basic {0}\" -f $base64AuthInfo)} -Method $httpAction -ContentType \"Application/Json\""},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-administer-webjob.json","Website":"/step-templates/ac7868f9-dc5c-42b8-ab8c-0c1e801f6957","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"}},{"Id":"745fa985-7022-4b19-a788-2fd77aa5b365","Name":"Azure Blob Storage set CORS Rule","Description":"Set a given CORS rule on the specified Azure storage blob container","Version":4,"ExportedAt":"2016-01-22T04:49:27.549+00:00","ActionType":"Octopus.Script","Author":"bobjwalker","Parameters":[{"Name":"PublishSettingsFile","Label":"Publish Settings File","HelpText":"Absolute path on the tentacle to the Azure publishsettings file to use. Eg. C:\\Azure\\Azure.publishsettings","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"StorageAccount","Label":"Storage Account","HelpText":"The Azure Storage Account to use.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"StorageAccountKey","Label":"Storage Account Key","HelpText":"The primary or secondary key for the Azure Storage Account.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Name":"StorageContainer","Label":"Storage Container","HelpText":"The storage container to use.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"AllowedHeaders","Label":"Allowed Headers","HelpText":"The allowed headers for the CORS rule","DefaultValue":"\"x-ms-blob-content-type\",\"x-ms-blob-content-disposition\"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"AllowedOrigins","Label":"Allowed Origins","HelpText":"The allowed origins for the CORS rule","DefaultValue":"*","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"MaxAgeInSeconds","Label":"Max Age In Seconds","HelpText":"The max age in seconds that a pre-flight response can be cached on the client for.","DefaultValue":"1800","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"AllowedMethods","Label":"Allowed Methods","HelpText":"The allowed HTTP methods for the CORS rule","DefaultValue":"Get","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"try\n{ \n Import-Module Azure -ErrorAction Stop\n}\ncatch\n{\n throw \"Windows Azure Powershell not found! Please make sure to install them from http://www.windowsazure.com/en-us/downloads/#cmd-line-tools\" \n}\n\nImport-AzurePublishSettingsFile $PublishSettingsFile\n\n$context = New-AzureStorageContext `\n -StorageAccountName $StorageAccount `\n -StorageAccountKey $StorageAccountKey\n\n$container = Get-AzureStorageContainer -Context $context | \n Where-Object { $_.Name -like $StorageContainer }\n\nif (-not $container)\n{\n throw \"Azure storage container ($StorageAccount) not found\"\n}\n\n$corsRules = (@{\n AllowedHeaders=@($AllowedHeaders);\n AllowedOrigins=@($AllowedOrigins);\n MaxAgeInSeconds=$MaxAgeInSeconds;\n AllowedMethods=@($AllowedMethods)})\n\nSet-AzureStorageCORSRule -Context $context -ServiceType Blob -CorsRules $corsRules\n\nWrite-Host \"Added CORS rule to container: $StorageContainer\""},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-blob-storage-set-cors.json","Website":"/step-templates/745fa985-7022-4b19-a788-2fd77aa5b365","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"}},{"Id":"0b167d34-832e-4c96-8a8f-2ea0a6c0fe0c","Name":"Azure Blob Storage Upload","Description":"Upload files in a directory to a specified Azure Storage blob container.","Version":14,"ExportedAt":"2016-01-21T07:21:36.182+00:00","ActionType":"Octopus.Script","Author":"shawnmclean","Parameters":[{"Name":"CopyDirectory","Label":"Copy Directory","HelpText":"Replicates files and directory under the Copy Directory.\nEg. `Content/CDN` that is located at the root of the nuget package.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"PublishSettingsFile","Label":"Publish Settings File","HelpText":"Absolute path on the tentacle to the Azure publishsettings file to use.\nEg. `C:\\Azure\\Azure.publishsettings`","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"StorageAccount","Label":"Storage Account","HelpText":"The Azure Storage Account to use.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"StorageAccountKey","Label":"Storage Account Key","HelpText":"The primary or secondary key for the Azure Storage Account.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"StorageContainer","Label":"Storage Container","HelpText":"The storage container to use.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"NugetPackageStepName","Label":"Nuget Package Step Name","HelpText":"Name of the previously-deployed package step that contains the Copy Directory.","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptBody":"function Find-InstallLocations {\n $result = @()\n $OctopusParameters.Keys | foreach {\n if ($_.EndsWith('].Output.Package.InstallationDirectoryPath')) {\n $result += $OctopusParameters[$_]\n }\n }\n return $result\n}\n\nfunction Find-InstallLocation($stepName) {\n $result = $OctopusParameters.Keys | where {\n $_.Equals(\"Octopus.Action[$stepName].Output.Package.InstallationDirectoryPath\", [System.StringComparison]::OrdinalIgnoreCase)\n } | select -first 1\n \n if ($result) {\n return $OctopusParameters[$result]\n }\n \n throw \"No install location found for step: $stepName\"\n}\n\nfunction Find-SingleInstallLocation {\n $all = @(Find-InstallLocations)\n if ($all.Length -eq 1) {\n return $all[0]\n }\n if ($all.Length -eq 0) {\n throw \"No package steps found\"\n }\n throw \"Multiple package steps have run; please specify a single step\"\n}\n\n# Check if Windows Azure Powershell is avaiable \ntry{ \n Import-Module Azure -ErrorAction Stop\n}catch{\n throw \"Windows Azure Powershell not found! Please make sure to install them from http://www.windowsazure.com/en-us/downloads/#cmd-line-tools\" \n}\n\nImport-AzurePublishSettingsFile $PublishSettingsFile\n\n# The script has been tested on Powershell 3.0\nSet-StrictMode -Version 3\n\n$stepPath = \"\"\nif (-not [string]::IsNullOrEmpty($NugetPackageStepName)) {\n Write-Host \"Finding path to package step: $NugetPackageStepName\"\n $stepPath = Find-InstallLocation $NugetPackageStepName\n} else {\n $stepPath = Find-SingleInstallLocation\n}\nWrite-Host \"Package was installed to: $stepPath\"\n\n$fullPath = \"$stepPath\\$CopyDirectory\"\nWrite-Host \"Copying Files in: $fullPath\"\n\n# Get a list of files from the project folder\n$files = @(ls -Path $fullPath -File -Recurse)\n\n$fileCount = $files.Count\nWrite-Host \"Found $fileCount Files: $files\"\n\n$context = New-AzureStorageContext `\n -StorageAccountName $StorageAccount `\n -StorageAccountKey $StorageAccountKey\n\nif ($files -ne $null -and $files.Count -gt 0)\n{\n # Create the storage container.\n $existingContainer = Get-AzureStorageContainer -Context $context | \n Where-Object { $_.Name -like $StorageContainer }\n\n if (-not $existingContainer)\n {\n $newContainer = New-AzureStorageContainer `\n -Context $context `\n -Name $StorageContainer `\n -Permission Blob\n \"Storage container '\" + $newContainer.Name + \"' created.\"\n }\n\n # Upload the files to storage container.\n $fileCount = $files.Count\n $time = [DateTime]::UtcNow\n if ($files.Count -gt 0)\n {\n foreach ($file in $files) \n {\n $blobFileName = $file.FullName.Replace($fullPath, '').TrimStart('\\')\n $contentType = switch ([System.IO.Path]::GetExtension($file))\n\t {\n\t \".css\" {\"text/css\"}\n\t \".js\" {\"text/javascript\"}\n\t \".json\" {\"application/json\"}\n\t \".html\" {\"text/html\"}\n\t \".png\" {\"image/png\"}\n\t \".svg\" {\"image/svg+xml\"}\n\t default {\"application/octet-stream\"}\n\t }\n\n Set-AzureStorageBlobContent `\n -Container $StorageContainer `\n -Context $context `\n -File $file.FullName `\n -Blob $blobFileName `\n -Properties @{ContentType=$contentType} `\n -Force\n }\n }\n\n $duration = [DateTime]::UtcNow - $time\n\n \"Uploaded \" + $files.Count + \" files to blob container '\" + $StorageContainer + \"'.\"\n \"Total upload time: \" + $duration.TotalMinutes + \" minutes.\"\n}\nelse\n{\n Write-Warning \"No files found.\"\n}","Octopus.Action.Script.Syntax":"PowerShell"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-blob-storage-upload.json","Website":"/step-templates/0b167d34-832e-4c96-8a8f-2ea0a6c0fe0c","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"}},{"Id":"c1d6e994-16c8-4896-b6f2-57f9558184ea","Name":"Azure Database - Export","Description":"Exports a database to a bacpac\n\n*Depends on az cli*\n\n*Source database requires 'Allow Azure services and resources to access this server' option turn on in the SQL server firewall*","Version":2,"ExportedAt":"2020-06-23T21:41:09.205Z","ActionType":"Octopus.AzurePowerShell","Author":"bobjwalker","Packages":[],"Parameters":[{"Id":"0bf888db-667e-4303-a4bd-c721bf1de0ad","Name":"azDbExport.AzAcct","Label":"Azure Account","HelpText":null,"DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"d5885f12-d921-4ce8-afc2-384f0b82daae","Name":"azDbExport.rgName","Label":"Resource Group Name","HelpText":null,"DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"03b281f5-e1e2-42a8-bb43-317bc4981393","Name":"azDbExport.sqlSvrName","Label":"SQL Server Name","HelpText":"The name of the SQL Server to connect to.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"e67ef4ab-3084-45e7-81df-7cda76baf2fc","Name":"azDbExport.dbName","Label":"Database Name","HelpText":"The name of the database you wish to export","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"6da5679d-1c84-4fb4-8f91-22fd91b50baa","Name":"azDbExport.adminName","Label":"SQL Server Admin Name","HelpText":"The admin name of the SQL server containing the database you wish to export","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"44e1a2a3-6b9b-44a5-893d-d26f14166b52","Name":"azDbExport.adminPwd","Label":"Admin Password","HelpText":"The admin password of the SQL server containing the database you wish to export","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"40715e88-4892-48c6-83f2-603c0193439b","Name":"azDbExport.blobAccessKey","Label":"Azure Blob Access Key","HelpText":"the access key (Shared Access Key or Storage Access Key) to grant access to the storage account","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"fcb94050-5f81-410e-9ed9-c5f52653f9c6","Name":"azDbExport.accessKeyType","Label":"Access Key Type","HelpText":"The type of key the access key represents","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"SharedAccessKey|Shared Access Key\nStorageAccessKey|Storage Access Key"}},{"Id":"a8631db7-556e-4532-aacd-595266c4347f","Name":"azDbExport.ContainerUri","Label":"Container Uri","HelpText":"The URI of the container to save the exported database in. Format is: `https://{StorageAccountName}.blob.core.windows.net/{ContainerName}`","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"85686923-5e57-4b1d-8dd7-6b5ca263ba42","Name":"azDbExport.backupName","Label":"Backup Name","HelpText":"The name of the file being saved. The bacpac extension (`.bacpac`) will be appended automatically. Defaults to DB Name","DefaultValue":"#{azDbExport.dbName}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Azure.AccountId":"#{azDbExport.AzAcct}","Octopus.Action.Script.ScriptBody":"$rgname = $OctopusParameters[\"azDbExport.rgName\"]\n$svrName = $OctopusParameters[\"azDbExport.sqlSvrName\"]\n$dbName = $OctopusParameters[\"azDbExport.dbName\"]\n$adminName = $OctopusParameters[\"azDbExport.adminName\"]\n$adminPwd = $OctopusParameters[\"azDbExport.adminPwd\"]\n$accessKey = $OctopusParameters[\"azDbExport.blobAccessKey\"]\n$accessKeyType = $OctopusParameters[\"azDbExport.accessKeyType\"]\n$containerUri = $OctopusParameters[\"azDbExport.ContainerUri\"]\n$backupName = $OctopusParameters[\"azDbExport.backupName\"]\n\n$backupUri = \"$containerUri/$backupName.bacpac\"\n\nif([string]::IsNullOrEmpty($rgname))\n{\n\tthrow \"resource group name is not provided\"\n}\n\nif([string]::IsNullOrEmpty($svrName))\n{\n\tthrow \"sql server name is not provided\"\n}\n\nif([string]::IsNullOrEmpty($dbName))\n{\n\tthrow \"database name not provided\"\n}\n# admin name, password and access key will not be validated in favor of security\n\nif([string]::IsNullOrEmpty($accessKeyType))\n{\n\tthrow \"access key type not provided\"\n}\n\nif([string]::IsNullOrEmpty($containerUri))\n{\n\tthrow \"containerUri not provided\"\n}\n\nif([string]::IsNullOrEmpty($backupName))\n{\n\tthrow \"backup name not provided\"\n}\n\nwrite-host \"starting db export\"\naz sql db export --resource-group $rgname --server $svrName --name $dbName --admin-password $adminPwd --admin-user $adminName --storage-key $accessKey --storage-key-type $accessKeyType --storage-uri $backupUri\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-database-export.json","Website":"/step-templates/c1d6e994-16c8-4896-b6f2-57f9558184ea","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"}},{"Id":"5b4544ed-987b-4532-9d6d-7c7a2ce5bd00","Name":"Azure Database - Import","Description":"Imports a bacpac file into an existing database.\n\n*depends on az cli*\n\n*Target database requires 'Allow Azure services and resources to access this server' option turn on in the SQL server firewall*","Version":2,"ExportedAt":"2020-06-16T14:33:48.670Z","ActionType":"Octopus.AzurePowerShell","Author":"bobjwalker","Packages":[],"Parameters":[{"Id":"0bf888db-667e-4303-a4bd-c721bf1de0ad","Name":"azDbImport.AzAcct","Label":"Azure Account","HelpText":null,"DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"d5885f12-d921-4ce8-afc2-384f0b82daae","Name":"azDbImport.rgName","Label":"Resource Group Name","HelpText":null,"DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"03b281f5-e1e2-42a8-bb43-317bc4981393","Name":"azDbImport.sqlSvrName","Label":"SQL Server Name","HelpText":"The name of the SQL Server to connect to.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"85686923-5e57-4b1d-8dd7-6b5ca263ba42","Name":"azDbImport.backupName","Label":"Backup Name","HelpText":"The name of the file being saved. Defaults to DB Name","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"6da5679d-1c84-4fb4-8f91-22fd91b50baa","Name":"azDbImport.adminName","Label":"SQL Server Admin Name","HelpText":"The admin name of the SQL server containing the database you wish to import","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"44e1a2a3-6b9b-44a5-893d-d26f14166b52","Name":"azDbImport.adminPwd","Label":"Admin Password","HelpText":"The admin password of the SQL server containing the database you wish to import","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"40715e88-4892-48c6-83f2-603c0193439b","Name":"azDbImport.blobAccessKey","Label":"Azure Blob Access Key","HelpText":"the access key (Shared Access Key or Storage Access Key) to grant access to the storage account","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"fcb94050-5f81-410e-9ed9-c5f52653f9c6","Name":"azDbImport.accessKeyType","Label":"Access Key Type","HelpText":"The type of key the access key represents","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"SharedAccessKey|Shared Access Key\nStorageAccessKey|Storage Access Key"}},{"Id":"a8631db7-556e-4532-aacd-595266c4347f","Name":"azDbImport.ContainerUri","Label":"Container Uri","HelpText":"The URI of the container to save the exported database in. Format is: `https://{StorageAccountName}.blob.core.windows.net/{ContainerName}`","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"e67ef4ab-3084-45e7-81df-7cda76baf2fc","Name":"azDbImport.dbName","Label":"Database Name","HelpText":"The name of the database you wish to import","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Azure.AccountId":"#{azDbImport.AzAcct}","Octopus.Action.Script.ScriptBody":"$rgname = $OctopusParameters[\"azDbImport.rgName\"]\n$svrName = $OctopusParameters[\"azDbImport.sqlSvrName\"]\n$dbName = $OctopusParameters[\"azDbImport.dbName\"]\n$adminName = $OctopusParameters[\"azDbImport.adminName\"]\n$adminPwd = $OctopusParameters[\"azDbImport.adminPwd\"]\n$accessKey = $OctopusParameters[\"azDbImport.blobAccessKey\"]\n$accessKeyType = $OctopusParameters[\"azDbImport.accessKeyType\"]\n$containerUri = $OctopusParameters[\"azDbImport.ContainerUri\"]\n$backupName = $OctopusParameters[\"azDbImport.backupName\"]\n\n$backupUri = \"$containerUri/$backupName.bacpac\"\n\nif([string]::IsNullOrEmpty($rgname))\n{\n\tthrow \"resource group name is not provided\"\n}\n\nif([string]::IsNullOrEmpty($svrName))\n{\n\tthrow \"sql server name is not provided\"\n}\n\nif([string]::IsNullOrEmpty($dbName))\n{\n\tthrow \"database name not provided\"\n}\n\n# admin name, password and access key will not be validated in favor of security\n\nif([string]::IsNullOrEmpty($accessKeyType))\n{\n\tthrow \"access key type not provided\"\n}\n\nif([string]::IsNullOrEmpty($containerUri))\n{\n\tthrow \"containerUri not provided\"\n}\n\nif([string]::IsNullOrEmpty($backupName))\n{\n\tthrow \"backup name not provided\"\n}\n\nwrite-host \"starting db import\"\naz sql db import --resource-group $rgname --server $svrName --name $dbName --admin-password $adminPwd --admin-user $adminName --storage-key $accessKey --storage-key-type $accessKeyType --storage-uri $backupUri\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-database-import.json","Website":"/step-templates/5b4544ed-987b-4532-9d6d-7c7a2ce5bd00","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"}},{"Id":"cc3b7dd9-f107-4477-acc4-4d1ffdf9e820","Name":"Azure Database - Import Create New DTU","Description":"restores a bacpac to a new database\n\n*Depends on az cli*\n\n*Source database requires 'Allow Azure services and resources to access this server' option turn on in the SQL server firewall*","Version":1,"ExportedAt":"2020-06-23T20:12:56.412Z","ActionType":"Octopus.AzurePowerShell","Author":"xtreampb","Packages":[],"Parameters":[{"Id":"918c8c99-4afe-4d8b-8c3d-3f7d5443a951","Name":"azDbImportNewDTU.azAccount","Label":"Azure Account","HelpText":"Azure account with permissions to the subscription and resource group","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"dcf78060-568c-4717-87d5-d1d2d1044418","Name":"azDbImportNewDTU.resourceGroup","Label":"Resource Group","HelpText":"Resource group name housing the target SQL server","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"2a35cc98-c991-4bbf-bf80-b6fb74b5d066","Name":"azDbImportNewDTU.server","Label":"SQL Server","HelpText":"Name of the Azure SQL server","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"aad2ddb7-ea11-4e7b-b90a-8ccb354e4a60","Name":"azDbImportNewDTU.dbName","Label":"Database Name","HelpText":"Name of the database that will be created","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"1c794a0d-d7f2-4757-875a-e2e0148e8fd1","Name":"azDbImportNewDTU.serviceObjective","Label":"Service Objective","HelpText":"The service objective for the new database","DefaultValue":"Basic","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"Basic|Basic\nS0|S0\nS1|S1\nS3|S3\nS4|S4\nS6|S6\nS7|S7\nS9|S9\nS12|S12\nP1|P1\nP2|P2\nP4|P4\nP6|P6\nP11|P11\nP15|P15"}},{"Id":"81cef05c-98d2-4e82-bc78-f1bcb6536291","Name":"azDbImportNewDTU.elasticPool","Label":"Elastic Pool","HelpText":"The name or resource id of the elastic pool to create the database in","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"48128da8-94e8-4560-8fa7-7c30e68d1849","Name":"azDbImportNewDTU.readScale","Label":"Read Scale","HelpText":"If enabled, connections that have application intent set to readonly in their connection string may be routed to a readonly secondary replica. This property is only settable for Premium and Business Critical databases","DefaultValue":"false","DisplaySettings":{"Octopus.ControlType":"Checkbox"}},{"Id":"4a52b908-7515-4089-91ad-0736e6bb687c","Name":"azDbImportNewDTU.zoneRedundant","Label":"Zone Redundant","HelpText":"Specifies whether to enable zone redundancy","DefaultValue":"false","DisplaySettings":{"Octopus.ControlType":"Checkbox"}},{"Id":"948d5fa8-7d9a-4d51-bcd3-6ac6eaf37d3b","Name":"azDbImportNewDTU.maxsize","Label":"Max Storage Size","HelpText":"The max storage size. If no unit is specified, defaults to bytes (B)","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"4bc52675-3963-4bdd-9ca4-b2611dc968eb","Name":"azDbImportNewDTU.tags","Label":"Tags","HelpText":"Space-separated tags. `key[=value] key[=value]`","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"40715e88-4892-48c6-83f2-603c0193439b","Name":"azDbImportNewDTU.blobAccessKey","Label":"Azure Blob Access Key","HelpText":"the access key (Shared Access Key or Storage Access Key) to grant access to the storage account","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"fcb94050-5f81-410e-9ed9-c5f52653f9c6","Name":"azDbImportNewDTU.accessKeyType","Label":"Access Key Type","HelpText":"The type of key the access key represents","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"SharedAccessKey|Shared Access Key\nStorageAccessKey|Storage Access Key"}},{"Id":"a8631db7-556e-4532-aacd-595266c4347f","Name":"azDbImportNewDTU.ContainerUri","Label":"Container Uri","HelpText":"The URI of the container to save the exported database in. Format is: `https://{StorageAccountName}.blob.core.windows.net/{ContainerName}`","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"85686923-5e57-4b1d-8dd7-6b5ca263ba42","Name":"azDbImportNewDTU.backupName","Label":"Backup Name","HelpText":"The name of the file being saved. Defaults to DB Name","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"6da5679d-1c84-4fb4-8f91-22fd91b50baa","Name":"azDbImportNewDTU.adminName","Label":"SQL Server Admin Name","HelpText":"The admin name of the SQL server containing the database you wish to import","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"44e1a2a3-6b9b-44a5-893d-d26f14166b52","Name":"azDbImportNewDTU.adminPwd","Label":"Admin Password","HelpText":"The admin password of the SQL server containing the database you wish to import","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"#get variables into easy to use format\n# Create DB Variables\n$databaseName = $OctopusParameters[\"azDbImportNewDTU.dbName\"]\n$sqlServer = $OctopusParameters[\"azDbImportNewDTU.server\"]\n$rgName = $OctopusParameters[\"azDbImportNewDTU.resourceGroup\"]\n$elasticPool = $OctopusParameters[\"azDbImportNewDTU.elasticPool\"]\n$readScaleTruthy = $OctopusParameters[\"azDbImportNewDTU.readScale\"]\n$serviceObjective = $OctopusParameters[\"azDbImportNewDTU.serviceObjective\"]\n$tags = $OctopusParameters[\"azDbImportNewDTU.tags\"]\n$zoneRedundant = $OctopusParameters[\"azDbImportNewDTU.zoneRedundant\"]\n$maxSize = $OctopusParameters[\"azDbImportNewDTU.maxSize\"]\n\n# Import bacpac variables\n$adminName = $OctopusParameters[\"azDbImportNewDTU.adminName\"]\n$adminPwd = $OctopusParameters[\"azDbImportNewDTU.adminPwd\"]\n$accessKey = $OctopusParameters[\"azDbImportNewDTU.blobAccessKey\"]\n$accessKeyType = $OctopusParameters[\"azDbImportNewDTU.accessKeyType\"]\n$containerUri = $OctopusParameters[\"azDbImportNewDTU.ContainerUri\"]\n$backupName = $OctopusParameters[\"azDbImportNewDTU.backupName\"]\n$backupUri = \"$containerUri/$backupName.bacpac\"\n\n$readScaleValue = \"Disabled\"\n\nif($readScaleTruthy -eq \"true\") { $readScalevalue = \"Enabled\" }\n\n$ServiceObjectiveSizes = @{Basic = 2GB; S0 = 250GB; S1 = 250GB; S2 = 250GB; S3 = 1TB; S4 = 1TB; S6 = 1TB; S7 = 1TB; S9 = 1TB; S12 = 1TB; P1 = 1TB; P2 = 1TB; P4 = 1TB; P6 = 1TB; P11 = 4TB; P15 = 4TB}\n\nif($null -eq (az sql server list --query \"[?Name==$sqlServer]\" | ConvertFrom-Json))\n{\n throw \"$sqlServer doesn't exist or the selected azure account doesn't have access to it.\"\n}\n\nif($null -ne (az sql db list --resource-group $rgName --server $sqlServer --query \"[?Name==$databaseName]\" | ConvertFrom-Json))\n{\n throw \"$databaseName already exists\"\n}\n\n#validate parameters\n\nif(($maxSize / 1GB) -gt ($ServiceObjectiveSizes[$serviceObjective] / 1GB))\n{\n Write-Warning \"Desired max size of $($maxSize / 1GB)GB exceeds max size of $($ServiceObjectiveSizes[$serviceObjective] / 1GB)GB for selected service objective: $serviceObjective\"\n Write-Warning \"Setting max size to $($ServiceObjectiveSizes[$serviceObjective] / 1GB)GB\"\n $maxSize = \"$($ServiceObjectiveSizes[$serviceObjective] / 1GB)GB\"\n}\n\nif([string]::IsNullOrEmpty($rgname))\n{\n\tthrow \"resource group name is not provided\"\n}\n\nif([string]::IsNullOrEmpty($sqlServer))\n{\n\tthrow \"sql server name is not provided\"\n}\n\nif([string]::IsNullOrEmpty($databaseName))\n{\n\tthrow \"database name not provided\"\n}\n\n# admin name, password and access key will not be validated in favor of security\n\nif([string]::IsNullOrEmpty($accessKeyType))\n{\n\tthrow \"access key type not provided\"\n}\n\nif([string]::IsNullOrEmpty($containerUri))\n{\n\tthrow \"containerUri not provided\"\n}\n\nif([string]::IsNullOrEmpty($backupName))\n{\n\tthrow \"backup name not provided\"\n}\n\n# validate premium SKU settings\nif(!$serviceObjective.Contains('P'))\n{\n if($readScaleValue -eq \"Enabled\")\n {\n Write-Warning \"Read Scaling only available for premium SKUs. Setting database read scale to disabled\"\n $readScaleValue = \"Disabled\"\n }\n if($zoneRedundant -eq \"true\")\n {\n Write-Warning \"Zone redundant only available for premium SKUs. Setting database zone redundant to false\"\n $zoneRedundant = \"false\"\n }\n}\n\n$cliArgs = \"--name $databaseName --resource-group $rgName --server $sqlServer\"\n\nif($elasticPool) {$cliArgs += \" --elastic-pool $elasticPool\"}\nelse {$cliArgs += \" --max-size $maxSize --service-objective $serviceObjective --zone-redundant $zoneRedundant\"}\n\nif($tags) {$cliArgs += \" --tags $tags\"}\nif($readScale) {$cliArgs += \" --read-scale $readScaleValue\"}\n\n\n$cmd = \"az sql db create $cliArgs\"\n\nwrite-verbose \"cmd is: $cmd\"\n\nWrite-Host \"Creating Database\"\nInvoke-Expression $cmd\n\nwrite-host \"starting db import\"\nwrite-verbose \"import cmd az sql db import --resource-group $rgname --server $sqlServer --name $databaseName --admin-password $adminPwd --admin-user $adminName --storage-key $accessKey --storage-key-type $accessKeyType --storage-uri $backupUri\"\n\naz sql db import --resource-group $rgname --server $sqlServer --name $databaseName --admin-password $adminPwd --admin-user $adminName --storage-key $accessKey --storage-key-type $accessKeyType --storage-uri $backupUri\n","Octopus.Action.Azure.AccountId":"azureserviceprincipal-chris-azure-account-spaces-1"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-database-import-create-new-DTU.json","Website":"/step-templates/cc3b7dd9-f107-4477-acc4-4d1ffdf9e820","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"}},{"Id":"4f03ce31-a9ce-4aff-8c7b-5144af5401a1","Name":"Azure Database - Import Create New vcpu","Description":"Restores a bacpac to a new database\n\n*Depends on az cli*\n\n*Source database requires 'Allow Azure services and resources to access this server' option turn on in the SQL server firewall*","Version":1,"ExportedAt":"2020-06-23T20:13:26.129Z","ActionType":"Octopus.AzurePowerShell","Author":"Your GitHub Username","Packages":[],"Parameters":[{"Id":"a7ee5061-2e7a-4b1a-876c-21bee392e455","Name":"azDbImportNewVCPU.azAccount","Label":"Azure Account","HelpText":"Azure account with permissions to the subscription and resource group","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"0f280e95-7f8b-4864-bd1d-6af9930257ec","Name":"azDbImportNewVCPU.resourceGroup","Label":"Resource Group","HelpText":"Resource group name housing the target SQL server","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"12c084b7-1a60-4076-91e4-6471a57f8978","Name":"azDbImportNewVCPU.server","Label":"SQL Server","HelpText":"Name of the Azure SQL server","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"7e8e96ee-63d6-4b6b-ab69-da69bf35a798","Name":"azDbImportNewVCPU.dbName","Label":"Database Name","HelpText":"Name of the database that will be created","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"a7db94c4-7954-4bbb-af9f-b25f0d282978","Name":"azDbImportNewVCPU.edition","Label":"Edition","HelpText":"The edition component of the sku","DefaultValue":"GeneralPurpose","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"GeneralPurpose|General Purpose\nBusinessCritical|Business Critical\nHyperscale|Hyperscale"}},{"Id":"20568782-31c5-496a-8885-f69f4240a9b4","Name":"azDbImportNewVCPU.computeModel","Label":"Compute Model","HelpText":"The compute model of the database. Only applicable for general purpose instances","DefaultValue":"Provisioned","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"Provisioned|Provisioned\nServerless|Serverless"}},{"Id":"c99d1edc-62c4-4d3a-9896-8a7647a42783","Name":"azDbImportNewVCPU.family","Label":"Hardware Configuration","HelpText":"Select Between Gen5, Fsv2 , or M-Series. Please note the documented vCPU overrides if listed.","DefaultValue":"Gen5","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"Gen5|Gen5\nFsv2|Fsv2 (General Purpose, Compute Optimized 72 vCPUs)\nM|M-Series (Business Critical, Memory Opimized 128 vCPUs)"}},{"Id":"d869775f-4bf4-4497-a1eb-c83fddf4c215","Name":"azDbImportNewVCPU.coreCount","Label":"vCPU Core Count","HelpText":"the number of vCores to use.\n*General purpose FSv2 hardware is set to 72*","DefaultValue":"2","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"1|1 (Only available for general purpose, serverless instances)\n2|2\n4|4\n6|6\n8|8\n10|10\n12|12\n14|14\n16|16\n18|18\n20|20\n24|24\n32|32\n40|40\n80|80 (Not available for general purpose, serverless instances)"}},{"Id":"fd690b8e-8467-4872-a8b9-b6b046f8c91d","Name":"azDbImportNewVCPU.maxsize","Label":"Max Storage Size","HelpText":"The max storage size. If no unit is specified, defaults to bytes (B)","DefaultValue":"1GB","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"ff278593-3b7a-4923-b15e-3dc958c87496","Name":"azDbImportNewVCPU.elasticPool","Label":"Elastic Pool","HelpText":"The name or resource id of the elastic pool to create the database in","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"26414a8b-d167-4b94-9142-fa9bf1c984fe","Name":"azDbImportNewVCPU.zoneRedundant","Label":"Zone Redundant","HelpText":"Specifies whether to enable zone redundancy. This property is only applied to Business Critical databases.","DefaultValue":"false","DisplaySettings":{"Octopus.ControlType":"Checkbox"}},{"Id":"a2e4e51d-8a3b-4447-92f4-39e83f82339e","Name":"azDbImportNewVCPU.readScale","Label":"Read Scale","HelpText":"If enabled, connections that have application intent set to read only in their connection string may be routed to a read only secondary replica. This property is only applied to Business Critical databases.","DefaultValue":"false","DisplaySettings":{"Octopus.ControlType":"Checkbox"}},{"Id":"61ef6953-b59c-44f4-80a4-a005feba912c","Name":"azDbImportNewVCPU.readReplicaCount","Label":"Read Reaplica Count","HelpText":"The number of readonly replicas to provision for the database. This property is only applied to hyperscale databases.","DefaultValue":"0","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"0|0\n1|1\n2|2\n3|3\n4|4"}},{"Id":"713515d2-9dd1-4d63-8a66-14cfd08a7065","Name":"azDbImportNewVCPU.tags","Label":"Tags","HelpText":"Space-separated tags. `key[=value] key[=value]`","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"53913bf4-b70e-455f-8dbe-7002e3584ef0","Name":"azDbImportNewVCPU.blobAccessKey","Label":"Azure Blob Access Key","HelpText":"the access key (Shared Access Key or Storage Access Key) to grant access to the storage account","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"9c7cdde5-e5a1-4566-80f2-f9f5391c398b","Name":"azDbImportNewVCPU.accessKeyType","Label":"Access Key Type","HelpText":"The type of key the access key represents","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"SharedAccessKey|Shared Access Key\nStorageAccessKey|Storage Access Key"}},{"Id":"fda41fbc-36cc-47b2-864f-2670144ad3e7","Name":"azDbImportNewVCPU.ContainerUri","Label":"Container Uri","HelpText":"The URI of the container to save the exported database in. Format is: `https://{StorageAccountName}.blob.core.windows.net/{ContainerName}`","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"0a0da7eb-afee-4595-a073-993a9e951838","Name":"azDbImportNewVCPU.backupName","Label":"Backup Name","HelpText":"The name of the file being saved. Defaults to DB Name","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"8a601118-6e0d-4340-badd-c66d5c8101dd","Name":"azDbImportNewVCPU.adminName","Label":"SQL Server Admin Name","HelpText":"The admin name of the SQL server containing the database you wish to import","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"f3f441ba-e92e-4cf2-bab9-0477591bc907","Name":"azDbImportNewVCPU.adminPwd","Label":"SQL Server Admin Password","HelpText":"The admin password of the SQL server containing the database you wish to import","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"#get variables into easy to use format\n\n# vCPU vars\n$family = $OctopusParameters[\"azDbImportNewVCPU.family\"] # Gen4 is being phased out.\n$computeModel = $OctopusParameters[\"azDbImportNewVCPU.computeModel\"]\n$readReplicaCount = $OctopusParameters[\"azDbImportNewVCPU.readReplicaCount\"]\n$edition = $OctopusParameters[\"azDbImportNewVCPU.edition\"]\n$capacity = $OctopusParameters[\"azDbImportNewVCPU.coreCount\"] -as [int]\n\n# Create DB Variables\n$databaseName = $OctopusParameters[\"azDbImportNewVCPU.dbName\"]\n$sqlServer = $OctopusParameters[\"azDbImportNewVCPU.server\"]\n$rgName = $OctopusParameters[\"azDbImportNewVCPU.resourceGroup\"]\n$elasticPool = $OctopusParameters[\"azDbImportNewVCPU.elasticPool\"]\n$readScaleTruthy = $OctopusParameters[\"azDbImportNewVCPU.readScale\"]\n\n$tags = $OctopusParameters[\"azDbImportNewVCPU.tags\"]\n$zoneRedundant = $OctopusParameters[\"azDbImportNewVCPU.zoneRedundant\"]\n$maxSize = $OctopusParameters[\"azDbImportNewVCPU.maxSize\"]\n\n# Import bacpac variables\n$adminName = $OctopusParameters[\"azDbImportNewVCPU.adminName\"]\n$adminPwd = $OctopusParameters[\"azDbImportNewVCPU.adminPwd\"]\n$accessKey = $OctopusParameters[\"azDbImportNewVCPU.blobAccessKey\"]\n$accessKeyType = $OctopusParameters[\"azDbImportNewVCPU.accessKeyType\"]\n$containerUri = $OctopusParameters[\"azDbImportNewVCPU.ContainerUri\"]\n$backupName = $OctopusParameters[\"azDbImportNewVCPU.backupName\"]\n$backupUri = \"$containerUri/$backupName.bacpac\"\n\n$readScaleValue = \"Disabled\"\n\nif($readScaleTruthy -eq \"true\") { $readScalevalue = \"Enabled\" }\n$maxAvailableSize = 1TB\n\n$gen5VcpuCount = 2,4,6,8,10,12,14,16,18,20,24,32,40,80\n$gen5VcpuCountSvrless = 1,2,4,6,8,10,12,14,16,18,20,24,32,40\n\n#validate parameters\n\nif($null -eq (az sql server list --query \"[?Name==$sqlServer]\" | ConvertFrom-Json))\n{\n throw \"$sqlServer doesn't exist or the selected azure account doesn't have access to it.\"\n}\n\nif($null -ne (az sql db list --resource-group $rgName --server $sqlServer --query \"[?Name==$databaseName]\" | ConvertFrom-Json))\n{\n throw \"$database already exists\"\n}\n\n# max size for all databases (except GP serverless) is 1TB\n\nif([string]::IsNullOrEmpty($rgName))\n{\n\tthrow \"resource group name is not provided\"\n}\n\nif([string]::IsNullOrEmpty($sqlServer))\n{\n\tthrow \"sql server name is not provided\"\n}\n\nif([string]::IsNullOrEmpty($databaseName))\n{\n\tthrow \"database name not provided\"\n}\n\n# admin name, password and access key will not be validated in favor of security\n\nif([string]::IsNullOrEmpty($accessKeyType))\n{\n\tthrow \"access key type not provided\"\n}\n\nif([string]::IsNullOrEmpty($containerUri))\n{\n\tthrow \"containerUri not provided\"\n}\n\nif([string]::IsNullOrEmpty($backupName))\n{\n\tthrow \"backup name not provided\"\n}\n\nswitch($edition)\n{\n \"GeneralPurpose\"\n {\n switch($computeModel)\n {\n \"Provisioned\"\n {\n switch($family)\n {\n \"Gen5\"\n {\n \twrite-verbose \"Capacity set to: $capacity\"\n if($capacity -lt 2)\n {\n \tWrite-Warning \"Minimum vCPU for provisioned is 2\"\n Write-Warning \"setting vCPU to 2\"\n $capacity = 2\n }\n if(!$gen5VcpuCount.Contains($capacity))\n {\n throw \"Invalid max vCPU count entered valid values for Gen5 hardware is: $gen5VcpuCount\"\n }\n $maxAvailableSize = 1TB\n }\n \"FSv2\"\n {\n $capacity = 72\n $maxAvailableSize = 4TB\n }\n \"Default\"\n {\n throw \"Invalid hardware family selected for General purpose\"\n }\n }\n }\n \"Serverless\"\n {\n if($capacity -gt 40)\n {\n Write-Warning \"Max vCPUs for serverless is 40\"\n Write-Warning \"Setting max vCPU to 40\"\n $capacity = 40\n }\n\n if($family -ne \"Gen5\") {throw \"Only Gen5 hardware family available for serverless\"}\n\n if(!$gen5VcpuCountSvrless.Contains($capacity))\n {\n throw \"Invalid max vCPU count entered valid values for serverless Gen5 hardware is: $gen5VcpuCountSvrless\"\n }\n $maxAvailableSize = 512GB\n }\n }\n }\n \"Hyperscale\"\n {\n if($family -ne \"Gen5\") {throw \"Only Gen5 hardware family available for Hyperscale\"}\n\n if($capacity -lt 2)\n {\n Write-Warning \"Minimum vCPU for provisioned is 2\"\n Write-Warning \"setting vCPU to 2\"\n $capacity = 2\n }\n\n if(!$gen5VcpuCount.Contains($capacity))\n {\n throw \"Invalid max vCPU count entered valid values for Gen5 hardware is: $gen5VcpuCount\"\n }\n }\n \"BusinessCritical\"\n {\n switch ($family)\n {\n \"Gen5\"\n {\n if($capacity -lt 2)\n {\n Write-Warning \"Minimum vCPU for provisioned is 2\"\n Write-Warning \"setting vCPU to 2\"\n $capacity = 2\n }\n\n if(!$gen5VcpuCount.Contains($capacity))\n {\n throw \"Invalid max vCPU count entered valid values for Gen5 hardware is: $gen5VcpuCount\"\n }\n $maxAvailableSize = 1TB\n }\n \"M\"\n {\n $capacity = 128\n $maxAvailableSize = 4TB\n if($zoneRedundant -eq \"true\")\n {\n Write-Warning \"Zone redundant not available for M-Series hardware configuration\"\n Write-Warning \"Setting zone redundant to false\"\n $zoneRedundant = \"false\"\n }\n }\n }\n }\n}\n\nif(($maxSize / 1GB) -gt ($maxAvailableSize / 1GB))\n{\n Write-Warning \"Desired max size of $($maxSize / 1GB)GB exceeds available max size of $($maxAvailableSize / 1GB)GB\"\n Write-Warning \"Setting max size to $($maxAvailableSize / 1GB)GB\"\n $maxSize = $maxAvailableSize\n}\n\n$cliArgs = \"--name $databaseName --resource-group $rgName --server $sqlServer\"\n\nif($elasticPool) {$cliArgs += \" --elastic-pool $elasticPool\"}\nelse {$cliArgs += \" --edition $edition --family $family --capacity $capacity\"}\n\nif((!$edition -eq \"Hyperscale\") -and $maxSize) {$cliArgs += \" --max-size $maxSize\"}\nif($edition -eq \"GeneralPurpose\") {$cliArgs += \" --compute-model $computeModel\"}\nif($edition -eq \"Hyperscale\") {cliArgs += \" --read-replicas $readReplicaCount\"}\nif($tags) {$cliArgs += \" --tags $tags\"}\nif($edition -eq \"BusinessCritical\") {$cliArgs += \" --read-scale $readScaleValue --zone-redundant $zoneRedundant\"}\nif($elasticPool) {$cliArgs += \" --elastic-pool $elasticPool\"}\n\n$cmd = \"az sql db create $cliArgs\"\n\nwrite-verbose \"cmd is: $cmd\"\n\nWrite-Host \"Creating Database\"\ninvoke-expression \"$cmd\"\n\nwrite-host \"starting db import\"\nwrite-verbose \"import cmd az sql db import --resource-group $rgname --server $sqlServer --name $databaseName --admin-password $adminPwd --admin-user $adminName --storage-key $accessKey --storage-key-type $accessKeyType --storage-uri $backupUri\"\n\naz sql db import --resource-group $rgname --server $sqlServer --name $databaseName --admin-password $adminPwd --admin-user $adminName --storage-key $accessKey --storage-key-type $accessKeyType --storage-uri $backupUri\n","Octopus.Action.Azure.AccountId":"#{azDbImportNewVCPU.azAccount}"},"Category":"Other","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-database-import-create-new-vcpu.json","Website":"/step-templates/4f03ce31-a9ce-4aff-8c7b-5144af5401a1","Logo":"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","$Meta":{"Type":"ActionTemplate"}},{"Id":"d09f55f6-5b32-441f-b6b2-1ee6c3e53182","Name":"Azure DB - Execute SQL ","Description":"Runs a sql command against an Azure SQL Server database.\n\nAdds a firewall rule to allow the machine executing the step to access the database; the rule is then removed.\n\n*Depends on az cli*\n\n*Depends on sqlserver powershell module *","Version":1,"ExportedAt":"2020-07-22T16:38:39.012Z","ActionType":"Octopus.AzurePowerShell","Author":"xtreampb","Packages":[],"Parameters":[{"Id":"4f94e536-a48f-4d9a-854d-c02ca56d6ef2","Name":"azDbSqlCmd.azAccount","Label":"Azure Account","HelpText":"An Azure account with permissions to the subscription and the sql server being targeted","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"068237eb-7329-426e-8dee-72ed96eb3e32","Name":"azDbSqlCmd.resourceGroupName","Label":"Resource Group Name","HelpText":"The name of the resource group hosting the sql server","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"12590219-613f-4556-908a-cd87c509449f","Name":"azDbSqlCmd.ServerName","Label":"SQL Server Name","HelpText":"The name of the sql server. The FQDN (`database.windows.net`) will automatically be appended to this when needed.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"3fe35f76-f140-48df-be0c-2a927069bc8b","Name":"azDbSqlCmd.dbName","Label":"Database Name","HelpText":"The name of the database to execute the sql command against","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"bbe9a203-89db-4286-a684-c95748543805","Name":"azDbSqlCmd.AuthType","Label":"SQL Server Authentication Type","HelpText":"The type of authentication to use when connecting.","DefaultValue":"sql","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"sql|SQL Authentication\nadPwd|Active Directory Password\nad|Active Directory Integration"}},{"Id":"539885ef-8ff9-407e-8e33-3bf211d58df6","Name":"azDbSqlCmd.userId","Label":"User Id","HelpText":"The user id to use when authenticating with the sql server","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"60af2045-ec59-4f4f-baf4-79e0ae8bd60d","Name":"azDbSqlCmd.userPwd","Label":"User Password","HelpText":"Used with SQL or Active directory Password authentication.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"e631537b-c109-4678-a7e5-bbc8166cca78","Name":"azDbSqlCmd.connectionTimeout","Label":"Connection Timeout","HelpText":"The timeout for the query measured in seconds between 0 and 65534. 0 indicates no timeout","DefaultValue":"0","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"9f787938-012a-45e9-ae58-5a06b1f4f012","Name":"azDbSqlCmd.sqlCmd","Label":"SQL Command","HelpText":"The sql command to execute","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"273c678e-008e-4598-978e-9d7abaadbf6c","Name":"azDbSqlCmd.resultsOutput","Label":"Results Output","HelpText":"How should the results of the sql statement be retained. Results are only provided with select statements.","DefaultValue":"none","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"none|None\nvariable|Output Variable\nartifact|Process Artifact"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Azure.AccountId":"#{azDbSqlCmd.azAccount}","Octopus.Action.Script.ScriptBody":"# insure module installed. Designed to run on cloud infrastructure where owners doesn't have controll over the workers.\n\nif (Get-Module -ListAvailable -Name sqlserver)\n{\n\tWrite-Verbose \"sqlserver module installed and available\"\n Import-Module sqlserver\n}\n\nelse\n{\n\tWrite-Warning \"installing module for the current user.`nIf worker is owned, consider installing the powershell module 'sqlserver' globally to speed up deployments\"\n\tInstall-Module -Name sqlserver -Scope CurrentUser -AllowClobber -Force\n}\n\n# parse parameters\n\n$resourceGroup = $OctopusParameters[\"azDbSqlCmd.resourceGroupName\"]\n$sqlServerName = $OctopusParameters[\"azDbSqlCmd.ServerName\"]\n$dbName = $OctopusParameters[\"azDbSqlCmd.dbName\"]\n$userId = $OctopusParameters[\"azDbSqlCmd.userId\"]\n$userPwd = $OctopusParameters[\"azDbSqlCmd.userPwd\"]\n$authType = $OctopusParameters[\"azDbSqlCmd.AuthType\"]\n$connTimeout = $OctopusParameters[\"azDbSqlCmd.connectionTimeout\"] -as [int]\n$resultsOutput = $OctopusParameters[\"azDbSqlCmd.resultsOutput\"]\n\n$sqlCmd = $OctopusParameters[\"azDbSqlCmd.sqlCmd\"]\n\n# get current IP address\nWrite-Host \"Getting worker IP address...\" -NoNewLine\n$workerPublicIp = (Invoke-WebRequest -uri \"http://ifconfig.me/ip\" -UseBasicParsing).Content\nWrite-Host \"Done. IP is: $workerPublicIp\"\n\n# create Connection string\nswitch ($authType)\n{\n\t\"sql\"\n {\n \t$connectionString = \"Server=tcp:$sqlServerName.database.windows.net;Initial Catalog=$dbName;Persist Security Info=False;User ID=$userId;Password=$userPwd;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;\"\n }\n \"adPwd\"\n {\n \t$connectionString = \"Server=tcp:$sqlServerName.database.windows.net;Initial Catalog=$dbName;Persist Security Info=False;User ID=$userId;Password=$userPwd;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Authentication=`\"Active Directory Password`\";\"\n }\n \"ad\"\n {\n \t$connectionString = \"Server=tcp:$sqlServerName.database.windows.net;Initial Catalog=$dbName;Persist Security Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Authentication=`\"Active Directory Integrated`\";\"\n }\n}\n\n# open firewall port\nwrite-host \"opening firewall on server $sqlServerName for ip: $workerPublicIp\"\nInvoke-Expression \"az sql server firewall-rule create -g $resourceGroup -n tempOctoSqlCmd -s $sqlServerName --start-ip-address $workerPublicIp --end-ip-address $workerPublicIp\"\n\n# invoke sql cmd\ntry\n{\n\t$id = New-Guid\n $resultFilePath = \"$env:temp/$id.txt\"\n\tWrite-Host \"running sql statement: ``$sqlCmd``\"\n \n switch ($resultsOutput)\n {\n 'none'\n {\n \tInvoke-SqlCmd -ConnectionString $connectionString -Query $sqlCmd -QueryTimeout $connTimeout\n }\n\n 'variable'\n {\n \tInvoke-SqlCmd -ConnectionString $connectionString -Query $sqlCmd -QueryTimeout $connTimeout | ConvertTo-CSV | Out-File -FilePath \"$resultFilePath\"\n $outputContent = Get-Content -Path $resultFilePath | ConvertFrom-CSV\n Set-OctopusVariable -name \"azDbSqlCmd.results\"\n }\n\n 'artifact'\n {\n \tInvoke-SqlCmd -ConnectionString $connectionString -Query $sqlCmd -QueryTimeout $connTimeout | ConvertTo-CSV | Out-File -FilePath \"$resultFilePath\"\n New-OctopusArtifact -Path $resultFilePath -Name azDbSqlCmd.results.csv\n }\n }\n}\ncatch\n{\n\tthrow\n}\nfinally\n{\n # close firewall port\n write-host \"closing firewall on server $sqlServerName for ip: $workerPublicIp\"\n Invoke-Expression \"az sql server firewall-rule delete -g $resourceGroup -n tempOctoSqlCmd -s $sqlServerName\"\n}\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-database-execute-sql-cmd.json","Website":"/step-templates/d09f55f6-5b32-441f-b6b2-1ee6c3e53182","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"}},{"Id":"03bb1a08-52be-43ad-bdfd-117eb562b414","Name":"Azure Functions Deployment","Description":"Deploys Azure Functions via the Kudu API to an Azure Function App.\n\nDO NOT RUN THIS STEP ON AN AZURE WEB APP TARGET. USE A PLAIN TENTACLE TARGET ONLY.\n\nProcess:\n1. Deploys the package to a tentacle.\n2. Zips up the deployment artefacts and uploads the resulting zip file.\n\nThis process enables the following:\n- Config and variable transform \n- Package type agnostic (i.e. will work with .nupkg as well as .zip files)\n- Retention policies can be applied to the target in step 1\n\n**Notes:**\n\nThis deployment step requires an available tentacle to deploy the package to before the final package is deployed to Azure. This tentacle does not need to be within the target deployment environment. It is advised to install the tentacle on the Octopus Deploy server, and deploy to that tentacle.\n\nThe target Function App will not be purged before deployment. This is by design of the Kudu API. An advantage of this is that multiple deployment packages can be deployed to a single Function App, as long as each function to be deployed has a unique name. However, you should be careful not to expect functions that have been removed from the deployment package to also be removed from the Functions App.\n\nThe package to deploy should mirror exactly the file and folder structure that the Functions App expects. A quick and easy way to get this up and running is to download an existing Function App's content from the Azure portal, and upload the downloaded zip file to Octopus Deploy via the Library > Packages page.","Version":4,"ExportedAt":"2020-03-15T18:13:57.632Z","ActionType":"Octopus.TentaclePackage","Author":"twerthi","Parameters":[{"Id":"538b02c5-ca4c-4bb6-aadc-e46906e69537","Name":"Azf.Username","Label":"Username","HelpText":"See [Kudu Deployment Credentials](https://github.com/projectkudu/kudu/wiki/Deployment-credentials#user-level-credentials-aka-deployment-credentials) for more information.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"5510ce13-6016-471b-a65d-051597c0c972","Name":"Azf.Password","Label":"Password","HelpText":"See [Kudu Deployment Credentials](https://github.com/projectkudu/kudu/wiki/Deployment-credentials#user-level-credentials-aka-deployment-credentials) for more information.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"},"Links":{}},{"Id":"2bcc2c06-26c7-48c1-9408-1892ecd15910","Name":"Azf.ApplicationName","Label":"Application Name","HelpText":"This value can be determined from the URL of your application. i.e.: https://{ApplicationName}.azurewebsites.net","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"f6ac1609-2cdf-4ba9-a598-6c32df68db85","Name":"Azf.PackageName","Label":"Package Name","HelpText":"The name of the package to deploy.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"0d71cd13-9fb7-4b7f-b352-004a96d6a741","Name":"Azf.JsonConfigFiles","Label":"Json Configuration Files","HelpText":"A comma- or newline-separated list of file names to replace settings in, relative to the package contents. Extended wildcard syntax is supported. E.g., appsettings.json, Config\\*.json, **\\specific-folder\\*.json.. Configuration values can be replaced using a `:` separated key, starting from the root of the hierarchy.\n\nConsider the following appsettings.json file:\n\n {\n \"Data\": {\n \"DefaultConnection\": {\n \"ConnectionString\": \"Server=(localdb)\\\\SQLEXPRESS;Database=OctoFX;Trusted_Connection=True\"\n }\n }\n }\n\nTo replace the value of `ConnectionString` you would add a variable name `Data:DefaultConnection:ConnectionString` to your project variables / library variable set. The JSON also supports extended template syntax.\n\nThe 'Target files' field supports extended template syntax. Conditional `if` and `unless`:\n\n #{if MyVar}...#{/if}\n\nIteration over variable sets or comma-separated values with `each`:\n\n #{each mv in MyVar}...#{mv}...#{/each}","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"},"Links":{}}],"Properties":{"Octopus.Action.Package.AutomaticallyRunConfigurationTransformationFiles":"True","Octopus.Action.Package.AutomaticallyUpdateAppSettingsAndConnectionStrings":"True","Octopus.Action.EnabledFeatures":"Octopus.Features.CustomScripts,Octopus.Features.JsonConfigurationVariables","Octopus.Action.Package.DownloadOnTentacle":"False","Octopus.Action.Package.FeedId":"feeds-builtin","Octopus.Action.Package.JsonConfigurationVariablesEnabled":"True","Octopus.Action.CustomScripts.PostDeploy.ps1":"$installationPath = $OctopusParameters[\"Octopus.Action.Package.InstallationDirectoryPath\"]\n$packageId = $OctopusParameters[\"Octopus.Action.Package.PackageId\"]\n$packageVersion = $OctopusParameters[\"Octopus.Action.Package.PackageVersion\"]\n\nWrite-Host \"Installation Path: $($installationPath)\"\nWrite-Host \"Package ID: $($packageId)\"\nWrite-Host \"Package Version: $($packageVersion)\"\n\n$zipFilePath = \"$($installationPath)\\$($packageId).$($packageVersion).zip\"\n\nWrite-Host \"Zip File Path: $($zipFilePath)\"\n\nCompress-Archive -Path \"$($installationPath)\\*\" -DestinationPath $zipFilePath\n\nWrite-Host \"Deployment zip file created\"\n\n$username = $OctopusParameters[\"Azf.Username\"]\n$password = $OctopusParameters[\"Azf.Password\"]\n$appName = $OctopusParameters[\"Azf.ApplicationName\"]\n\nif(!$username){\n Write-Error \"No Username has been supplied. You can do this from the Step Details page of this step.\"\n \n exit 1;\n}\n\n\nif(!$password){\n Write-Error \"No Password has been supplied. You can do this from the Step Details page of this step.\"\n \n exit 1;\n}\n\n\nif(!$appName){\n Write-Error \"No Application Name has been supplied. You can do this from the Step Details page of this step.\"\n \n exit 1;\n}\n\n$authHeader = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes((\"{0}:{1}\" -f $username,$password)))\n\n$apiUrl = \"https://$($appName).scm.azurewebsites.net/api/zipdeploy\"\n\nWrite-Host \"Uploading deployment zip file to $($apiUrl)\"\n\n# Set secure protocols\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls11 -bor [System.Net.SecurityProtocolType]::Tls12\n\nInvoke-RestMethod -Uri $apiUrl -Headers @{Authorization=(\"Basic {0}\" -f $authHeader)} -Method POST -InFile $zipFilePath -ContentType \"multipart/form-data\"\n\nWrite-Host \"Upload complete\"\n","Octopus.Action.Package.PackageId":"#{Azf.PackageName}","Octopus.Action.Package.JsonConfigurationVariablesTargets":"#{Azf.JsonConfigFiles}","Octopus.Action.CustomScripts.PreDeploy.ps1":"","Octopus.Action.CustomScripts.Deploy.ps1":""},"Category":"Azurefunctions","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-function-deployment.json","Website":"/step-templates/03bb1a08-52be-43ad-bdfd-117eb562b414","Logo":"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","$Meta":{"Type":"ActionTemplate"}},{"Id":"6f59f8aa-b2db-4f7a-b02d-a72c13d386f0","Name":"Azure Key Vault - Retrieve Secrets","Description":"This step retrieves one or more secrets from an Azure Key Vault and creates [sensitive output variables](https://octopus.com/docs/projects/variables/output-variables#sensitive-output-variables) for each value retrieved. These values can be used in other steps in your deployment or runbook process.\n\nYou can retrieve secrets with a specific version, and you can choose a custom output variable name for each secret.\n\n---\n\n**Required:** \n- An azure account with permissions to retrieve secrets from the Azure Key Vault.\n- The`Az.KeyVault` PowerShell module installed on the target or worker. If the module can't be found, the step will fail. *The `Az` module(s) can be installed from the [PowerShell gallery](https://www.powershellgallery.com/packages/Az)*\n\nNotes:\n\n- Tested on Octopus `2021.1`.\n- Tested with both Windows PowerShell and PowerShell Core on Linux.\n\n","Version":2,"ExportedAt":"2021-06-02T08:34:02.548Z","ActionType":"Octopus.AzurePowerShell","Author":"harrisonmeister","Packages":[],"Parameters":[{"Id":"5b05337d-a62d-44f4-a702-95b45a400160","Name":"Azure.KeyVault.RetrieveSecrets.Account","Label":"Azure Account","HelpText":"An Azure account with permissions to retrieve secrets from the Azure Key Vault.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"9b09b2b3-3c4d-4cbb-a065-8955f62448ad","Name":"Azure.KeyVault.RetrieveSecrets.VaultName","Label":"Vault Name","HelpText":"The name of the Azure Key Vault to retrieve secrets from.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"43949afd-1049-41fc-bd01-e878476f5952","Name":"Azure.KeyVault.RetrieveSecrets.VaultSecrets","Label":"Vault Secrets to retrieve","HelpText":"Specify the names of the Secrets to be returned from Azure Key Vault, in the format `SecretName SecretVersion | OutputVariableName` where:\n\n- `SecretName` is the name of the Secret to retrieve.\n- `SecretVersion` is the _optional_ version of the Secret to retrieve. *If this value isn't specified, the latest version will be retrieved*.\n- `OutputVariableName` is the _optional_ Octopus [output variable](https://octopus.com/docs/projects/variables/output-variables) name to store the secret's value in. *If this value isn't specified, an output name will be generated dynamically*.\n\n**Note:** Multiple fields can be retrieved by entering each one on a new line.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"46842344-405e-4633-a63f-115baaff7774","Name":"Azure.KeyVault.RetrieveSecrets.PrintVariableNames","Label":"Print output variable names","HelpText":"Write out the Octopus [output variable](https://octopus.com/docs/projects/variables/output-variables) names to the task log. Default: `False`.","DefaultValue":"False","DisplaySettings":{"Octopus.ControlType":"Checkbox"}},{"Id":"0c20c004-c792-4acc-81c5-62ecceecf6ac","Name":"Azure.KeyVault.RetrieveSecrets.AzModule.SpecificVersion","Label":"Az PowerShell Module version (optional)","HelpText":"If you wish to use a specific version of the `Az` PowerShell module (rather than the default), enter the version number here. e.g. `5.9.0`.\n\n**Note:** The version specified must exist on the machine.\n","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"d4d93a9a-72e1-48be-9ed6-78986bbfaa06","Name":"Azure.KeyVault.RetrieveSecrets.AzModule.CustomInstallLocation","Label":"Az PowerShell Install Location (optional)","HelpText":"If you wish to provide a custom path to the `Az` PowerShell module (rather than the default), enter the value here.\n\n**Note:** The Module must exist at the specified location on the machine. This step template will not download the Module.\n","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","OctopusUseBundledTooling":"False","Octopus.Action.Script.ScriptBody":"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12\n$ErrorActionPreference = 'Stop'\n\n# Variables\n$AzVaultModuleName = \"Az.KeyVault\"\n$AzureKeyVaultName = $OctopusParameters[\"Azure.KeyVault.RetrieveSecrets.VaultName\"]\n$VaultSecretNames = $OctopusParameters[\"Azure.KeyVault.RetrieveSecrets.VaultSecrets\"]\n$AzVaultModuleSpecificVersion = $OctopusParameters[\"Azure.KeyVault.RetrieveSecrets.AzModule.SpecificVersion\"]\n$AzVaultModuleCustomInstallLocation = $OctopusParameters[\"Azure.KeyVault.RetrieveSecrets.AzModule.CustomInstallLocation\"]\n$PrintVariableNames = $OctopusParameters[\"Azure.KeyVault.RetrieveSecrets.PrintVariableNames\"]\n\n# Validation\nif ([string]::IsNullOrWhiteSpace($AzureKeyVaultName)) {\n throw \"Required parameter Azure.KeyVault.RetrieveSecrets.VaultName not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($VaultSecretNames)) {\n throw \"Required parameter Azure.KeyVault.RetrieveSecrets.VaultSecrets not specified\"\n}\n\nif ([string]::IsNullOrWhiteSpace($AzVaultModuleSpecificVersion) -eq $False) {\n $requiredVersion = [Version]$AzVaultModuleSpecificVersion\n}\n\n# Cross-platform bits\n$WindowsPowerShell = $True\nif ($PSEdition -eq \"Core\") {\n $WindowsPowerShell = $False\n}\n\n### Helper functions\nfunction Get-Module-CrossPlatform {\n [CmdletBinding()]\n Param(\n [Parameter(Mandatory = $true, Position = 0)]\n [string] $Name\n )\n\n $module = Get-Module -Name $Name -ListAvailable\n if($WindowsPowerShell -eq $True -and $null -eq $module) {\n $module = Get-InstalledModule -Name $Name\n }\n\n return $module\n}\n\n$PowerShellModuleName = $AzVaultModuleName\n\n# Check for Custom install location specified for AzVaultModule\nif ([string]::IsNullOrWhiteSpace($AzVaultModuleCustomInstallLocation) -eq $false) {\n if ((Test-Path $AzVaultModuleCustomInstallLocation -IsValid) -eq $false) {\n throw \"The path $AzVaultModuleCustomInstallLocation is not valid, please use a relative or absolute path.\"\n }\n \n $AzVaultModulesFolder = [System.IO.Path]::GetFullPath($AzVaultModuleCustomInstallLocation) \n $LocalModules = (New-Item \"$AzVaultModulesFolder\" -ItemType Directory -Force).FullName\n $env:PSModulePath = $LocalModules + [System.IO.Path]::PathSeparator + $env:PSModulePath\n\n # Check to see if there\n if ((Test-Path -Path \"$LocalModules/$AzVaultModuleName\") -eq $true)\n {\n # Use specific location\n $PowerShellModuleName = \"$LocalModules/$PowerShellModuleName\"\n }\n}\n\n# Import module\nif([string]::IsNullOrWhiteSpace($AzVaultModuleSpecificVersion)) {\n Write-Host \"Importing module $PowerShellModuleName ...\"\n Import-Module -Name $PowerShellModuleName\n}\nelse {\n Write-Host \"Importing module $PowerShellModuleName ($AzVaultModuleSpecificVersion)...\"\n Import-Module -Name $PowerShellModuleName -RequiredVersion $requiredVersion\n}\n\n# Check if Az.Vault Module is installed.\n$azVaultModule = Get-Module-CrossPlatform -Name $AzVaultModuleName\t\nif ($null -eq $azVaultModule) {\n throw \"Cannot find the '$AzVaultModuleName' module on the machine. If you think it is installed, try restarting the Tentacle service for it to be detected.\"\t\n}\n\n$Secrets = @()\n$VariablesCreated = 0\n$StepName = $OctopusParameters[\"Octopus.Step.Name\"]\n\n# Extract secret names+versions \n@(($VaultSecretNames -Split \"`n\").Trim()) | ForEach-Object {\n if (![string]::IsNullOrWhiteSpace($_)) {\n Write-Verbose \"Working on: '$_'\"\n $secretDefinition = ($_ -Split \"\\|\")\n $secretName = $secretDefinition[0].Trim()\n $secretNameAndVersion = ($secretName -Split \" \")\n $secretVersion = $null\n if($secretNameAndVersion.Count -gt 1) {\n \t$secretName = $secretNameAndVersion[0].Trim()\n $secretVersion = $secretNameAndVersion[1].Trim()\n }\n if([string]::IsNullOrWhiteSpace($secretName)) {\n throw \"Unable to establish secret name from: '$($_)'\"\n }\n $secret = [PsCustomObject]@{\n Name = $secretName\n SecretVersion= $secretVersion\n VariableName = if (![string]::IsNullOrWhiteSpace($secretDefinition[1])) { $secretDefinition[1].Trim() } else { \"\" }\n }\n $Secrets += $secret\n }\n}\n\nWrite-Verbose \"Vault Name: $AzureKeyVaultName\"\nWrite-Verbose \"Print variables: $PrintVariableNames\"\nWrite-Verbose \"Secrets to retrieve: $($Secrets.Count)\"\nWrite-Verbose \"Az Version specified: $AzVaultModuleSpecificVersion\"\nWrite-Verbose \"Az Custom Install Dir: $AzVaultModuleCustomInstallLocation\"\n\n# Retrieve Secrets\nforeach($secret in $secrets) {\n $name = $secret.Name\n $secretVersion = $secret.SecretVersion\n $variableName = $secret.VariableName\n if ([string]::IsNullOrWhiteSpace($variableName)) {\n $variableName = \"$($AzureKeyVaultName.Trim()).$($name.Trim())\"\n }\n \n if ([string]::IsNullOrWhiteSpace($secretVersion)) {\n \t$azSecretValue = Get-AzKeyVaultSecret -VaultName $AzureKeyVaultName -Name $name -AsPlainText \n }\n else {\n \t$azSecretValue = Get-AzKeyVaultSecret -VaultName $AzureKeyVaultName -Name $name -Version $secretVersion -AsPlainText\n }\n \n Set-OctopusVariable -Name $variableName -Value $azSecretValue -Sensitive\n\n if($PrintVariableNames -eq $True) {\n Write-Host \"Created output variable: ##{Octopus.Action[$StepName].Output.$variableName}\"\n }\n $VariablesCreated += 1\n}\n\nWrite-Host \"Created $variablesCreated output variables\"","Octopus.Action.Azure.AccountId":"#{Azure.KeyVault.RetrieveSecrets.Account}"},"Category":"Azure Key Vault","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-keyvault-retrieve-secrets.json","Website":"/step-templates/6f59f8aa-b2db-4f7a-b02d-a72c13d386f0","Logo":"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","$Meta":{"Type":"ActionTemplate"}},{"Id":"2d21abec-491a-4d85-9210-2784bc3dfeb8","Name":"Azure Linux - Install Octopus Tentacle","Description":"This step template will install the latest tentacle on an Azure hosted, Linux virtual machine. This will also open the firewall for inbound traffic on port 10933 on the NSG.\n
\n*Note: Expects the Azure CLI and Powershell to be installed on the worker running this task*
\n*Note: Requires dotnet core to be pre-installed on the target machine*
\n*Note: Firewall ports will not be opened on the remote machine*","Version":4,"ExportedAt":"2022-02-09T15:56:03.173Z","ActionType":"Octopus.AzurePowerShell","Author":"harrisonmeister","Packages":[],"Parameters":[{"Id":"dea51842-271f-48fa-901e-243488049f97","Name":"installLinuxTentacle.AzureAccount","Label":"Azure Account","HelpText":"Azure account with permissions to the virtual machine in which to install the tentacle on","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"6a97548c-3b97-4a19-8b9a-45aa58ac62d9","Name":"installLinuxTentacle.azRgName","Label":"Azure Resource Group","HelpText":"The name of the resource group housing the NSG and VM","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"d9efb017-65c0-4010-b09f-0a6a34fc009f","Name":"installLinuxTentacle.azNsgName","Label":"NSG Name","HelpText":"The name of the azure network security group to create ","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"36c6d441-9fe8-4ea2-957a-2135aa9d1687","Name":"installLinuxTentacle.azNsgRulePriority","Label":"Azure NSG Rule Priority","HelpText":"the priority to assign to the NSG rule created for the octopus tentacle. Defaults to 400","DefaultValue":"400","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"e4358aec-2798-412a-bcd2-1c7e41a0728d","Name":"installLinuxTentacle.azVmName","Label":"VM Name","HelpText":"The name of the virtual machine to target when ","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"8dbe0a29-4e0f-43f8-8ef2-ae23a2884e85","Name":"installLinuxTentacle.octoServerThumb","Label":"Server Thumbprint","HelpText":"The Thumbprint of the octopus server","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"a0859551-6c84-45d1-af2b-c57becb4e8ef","Name":"installLinuxTentacle.octoApiKey","Label":"API Key","HelpText":"The API key used to configure the tentacle.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"dd07815d-bfb7-43b9-90f8-21ec5a2d2953","Name":"installLinuxTentacle.octopusRoles","Label":"Roles","HelpText":"Roles to assign to this tentacle installation.
\n*Note: Each role should be on it's own line*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"d3ffb38e-7fcf-4547-be9a-6cd8e46f8e5e","Name":"installLinuxTentacle.octopusEnvironments","Label":"Environments","HelpText":"Environments to assign this tentacle installation to.
\n*Note: Each environment should be on its own line*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"15150827-7bd3-4146-a798-66344851f602","Name":"installLinuxTentacle.octoServerUrl","Label":"Server Url","HelpText":"The server url to register the tentacle with. Defaults to the base url","DefaultValue":"#{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"9bcd6bb5-2db3-453f-b4f6-6a78f3c39b59","Name":"installLinuxTentacle.tentacleType","Label":"Tentacle Type","HelpText":"Select between a listening or polling tentacle","DefaultValue":"TentaclePassive","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"TentaclePassive|Listening\nTentacleActive|Polling"}},{"Id":"6bb98570-fe3e-4ab7-adfb-79ef7ce5c2ce","Name":"installLinuxTentacle.tentacleHostName","Label":"Tentacle Host Name","HelpText":"The host name to register the listening tentacles with. Octopus deploy server uses this value to reach out to the vm.
\n*Note: Leave blank to automatically use assigned public IP address.*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"1ae37ac0-fc37-447c-941f-7b72ed32a647","Name":"installLinuxTentacle.portNumber","Label":"Port Number","HelpText":"Port number used when installing and registering the tentacle. This port is also opened when installing a listening tentacle","DefaultValue":"10933","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Azure.AccountId":"#{installLinuxTentacle.AzureAccount}","Octopus.Action.Script.ScriptBody":"$nsgName = $OctopusParameters[\"installLinuxTentacle.azNsgName\"]\n$resourceGroup = $OctopusParameters[\"installLinuxTentacle.azRgName\"]\n$nsgRulePriority = $OctopusParameters[\"installLinuxTentacle.azNsgRulePriority\"]\n$vmName = $OctopusParameters[\"installLinuxTentacle.azVmName\"]\n$serverUri = $OctopusParameters[\"instrallTentacle.octoServerUrl\"]\n$apiKey = $OctopusParameters[\"installLinuxTentacle.octoApiKey\"]\n$rolesRaw = $OctopusParameters[\"installLinuxTentacle.octopusRoles\"]\n$enviroRaw = $OctopusParameters[\"installLinuxTentacle.octopusEnvironments\"]\n$octoThumb = $OctopusParameters[\"installLinuxTentacle.octoServerThumb\"]\n$comStyle = $OctopusParameters[\"installLinuxTentacle.tentacleType\"]\n$hostname = $OctopusParameters[\"installLinuxTentacle.tentacleHostName\"]\n$portNumber = $OctopusParameters[\"installLinuxTentacle.portNumber\"]\n\nWrite-Host \"Parsing Parameters\"\n\nif([string]::IsNullOrEmpty($rolesRaw))\n{\n\tthrow \"At least one role must be defined\"\n}\n\nif([string]::IsNullOrEmpty($enviroRaw))\n{\n\tthrow \"At least one environment must be defined\"\n}\n\n$roles = \"\"\n$rolesRaw -split \"`n\" | ForEach-Object { $roles += \"--role $_ \"}\n$roles = $roles.TrimEnd(' ')\n\n$environments = \"\"\n$enviroRaw -split \"`n\" | ForEach-Object { $environments += \"--env $_ \"}\n$environments = $environments.TrimEnd(' ')\n\nif($comStyle -eq \"TentaclePassive\")\n{\n\tif([string]::IsNullOrEmpty($hostname))\n {\n \t$hostname = az vm show -d -g $resourceGroup -n $vmName --query publicIps -o tsv\n $hostname = $hostname.Trim(\"`n\")\n }\n\n $noListen = \"--port $portNumber --noListen `\"false`\"\"\n $comStyle += \" --publicHostName=`\"$hostname`\"\"\n $openFirewall = 'true'\n}\nelse\n{\n\t$noListen = \"--noListen `\"true`\"\"\n $openFirewall = 'false'\n}\n\nif($openFirewall -eq 'true')\n{\n\tWrite-Host \"Creating NSG Rule\"\n\taz network nsg rule create --name \"OctopusTentacle\" --nsg-name $nsgName --priority $nsgRulePriority --resource-group $resourceGroup --direction Inbound --destination-port-ranges $portNumber\n}\n\nWrite-Verbose \"hostname: $hostname`noListen: $noListen\"\n\n$remoteScript = @\"\n\nprintf '%s\\n' \"Test case x failed\" >&2\nexit 1\n\nconfigFilePath=\"/etc/octopus/default/tentacle-default.config\"\nappPath=\"/home/Octopus/Applications\"\n\n# try curl\n{\n curl -L https://octopus.com/downloads/latest/Linux_x64TarGz/OctopusTentacle --output /tmp/tentacle-linux_x64.tar.gz -fsS\n} || {\n wget https://octopus.com/downloads/latest/Linux_x64TarGz/OctopusTentacle -O /tmp/tentacle-linux_x64.tar.gz -fsS\n}\n\nif [ ! -d \"/opt/octopus\" ]; then\n mkdir /opt/octopus\nfi\n\ntar xvzf /tmp/tentacle-linux_x64.tar.gz -C /opt/octopus\nrm /tmp/tentacle-linux_x64.tar.gz\n\ncd /opt/octopus/tentacle\n\nsudo /opt/octopus/tentacle/Tentacle create-instance --config \"`$configFilePath\"\nsudo chmod a+rwx `$configFilePath\n/opt/octopus/tentacle/Tentacle new-certificate --if-blank\n/opt/octopus/tentacle/Tentacle configure --port $portNumber --noListen False --reset-trust --app \"`$appPath\"\n/opt/octopus/tentacle/Tentacle configure --trust $octoThumb\necho \"Registering the Tentacle $name with server $serverUri in environment $environments with role $roles\"\n/opt/octopus/tentacle/Tentacle register-with --server \"$serverUri\" --apiKey \"$apikey\" --name \"$name\" $environments $roles --comms-style $comStyle --force\nsudo /opt/octopus/tentacle/Tentacle service --install --start\n\n\"@\n\nWrite-Host \"Installing tentacle on remote machine\"\n$scriptGuid = (new-guid).guid\nSet-Content -Value $remoteScript -Path \".\\$scriptGuid.ps1\"\n\n$result = az vm run-command invoke --command-id RunShellScript --name $vmName -g $resourceGroup --scripts \"@script.ps1\"\n\n$result\n\n$msg = ($result | convertfrom-json).value[0].message\n\nif($msg -match \"(?<=\\[stderr\\]).+\")\n{\n\tthrow $msg\n}\n\nremove-item \".\\$scriptGuid.ps1\"\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-linux-install-octopus-tentacle.json","Website":"/step-templates/2d21abec-491a-4d85-9210-2784bc3dfeb8","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"}},{"Id":"7518eaa0-677c-4562-82d5-a131f29e1744","Name":"Azure Site Extensions - Install","Description":"Installs an Azure [site extension](https://www.siteextensions.net) in your Azure web app.","Version":1,"ExportedAt":"2017-09-06T20:42:23.783Z","ActionType":"Octopus.AzureResourceGroup","Author":"alfhenrik","Parameters":[{"Id":"d1494374-4db4-4bed-8136-eec378de7c9d","Name":"AzSiteExt_ResourceGroupName","Label":"Resource group name","HelpText":"The Resource Group of your Azure Web App.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"1d188d2a-915e-425f-a4d8-5780421ebb00","Name":"AzSiteExt_SiteName","Label":"Site name","HelpText":"The name of your Azure Web App.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"00edff48-a947-424b-b46e-4f58826568c3","Name":"AzSiteExt_AppServicePlanName","Label":"App service plan name","HelpText":"The App Service Plan of your Azure Web App.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"2d2cfc5f-1f41-4d7b-a4df-3dbb652553fb","Name":"AzSiteExt_ExtensionName","Label":"Site extension name","HelpText":"The package name of the extension you want to install.\n\nThe extensions available to be installed can be found on the [siteextensions.net](https://www.siteextensions.net/packages) website. The name of the package can be derived from the URL of the extension (e.g. for the Application Insights extension the URL is `https://www.siteextensions.net/packages/Microsoft.ApplicationInsights.AzureWebSites/`, so the package name is `Microsoft.ApplicationInsights.AzureWebSites`).","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"3629e43b-1af0-4df5-a6ce-6f36ead4dea0","Name":"AzSiteExt_AzureAccountId","Label":"Azure account ID","HelpText":"The Azure account to use for the connection.\n\n**NOTE:** a **service principal** account is required, a **management certificate** account will not work.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}}],"Properties":{"Octopus.Action.Azure.ResourceGroupName":"#{AzSiteExt_ResourceGroupName}","Octopus.Action.Azure.TemplateSource":"Inline","Octopus.Action.Azure.ResourceGroupTemplateParameters":"{\"siteName\":{\"value\":\"#{AzSiteExt_SiteName}\"},\"extensionName\":{\"value\":\"#{AzSiteExt_ExtensionName}\"},\"appServicePlanName\":{\"value\":\"#{AzSiteExt_AppServicePlanName}\"}}","Octopus.Action.Azure.ResourceGroupDeploymentMode":"Incremental","Octopus.Action.Azure.ResourceGroupTemplate":"{\r\n \"$schema\": \"http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#\",\r\n \"contentVersion\": \"1.0.0.0\",\r\n \"parameters\": { \r\n \"siteName\": {\r\n \"type\": \"string\",\r\n \"metadata\": {\r\n \"description\": \"Web site name\"\r\n }\r\n },\r\n \"appServicePlanName\": {\r\n \"type\": \"string\",\r\n \"metadata\": {\r\n \"description\": \"App service plan name\"\r\n }\r\n },\r\n \"extensionName\": {\r\n \"type\": \"string\",\r\n \"metadata\": {\r\n \"description\": \"Extension name\"\r\n }\r\n } \r\n },\r\n \"variables\": { \r\n \"extensionApi\": \"2015-06-01\"\r\n },\r\n \"resources\": [\r\n {\r\n \"apiVersion\": \"[variables('extensionApi')]\",\r\n \"name\": \"[parameters('siteName')]\",\r\n \"type\": \"Microsoft.Web/sites\",\r\n \"location\": \"[resourceGroup().location]\",\r\n \"dependsOn\": [],\r\n \"properties\": {\r\n \"name\": \"[parameters('siteName')]\",\r\n \"serverFarmId\": \"[parameters('appServicePlanName')]\"\r\n },\r\n \"resources\": [\r\n {\r\n \"apiVersion\": \"[variables('extensionApi')]\",\r\n \"name\": \"[parameters('extensionName')]\",\r\n \"type\": \"siteextensions\",\r\n \"dependsOn\": [\r\n \"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]\"\r\n ],\r\n \"properties\": {}\r\n }\r\n ]\r\n }\r\n ]\r\n}","Octopus.Action.Azure.AccountId":"#{AzSiteExt_AzureAccountId}"},"Category":"Azure Site Extensions","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-site-extensions-install.json","Website":"/step-templates/7518eaa0-677c-4562-82d5-a131f29e1744","Logo":"iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAtFBMVEUAAACASZigoaJZtNmASZiASZigoaKgoaKgoaKASZiASZiASZiASZiASZiASZiASZiASZiASZiASZigoaKgoaKgoaKgoaKgoaKgoaKgoaJZtNlZtNlZtNlZtNlZtNlZtNlZtNlZtNlZtNlZtNmgoaKgoaKgoaKgoaKgoaKgoaKgoaKgoaKgoaKgoaKgoaJZtNlZtNmgoaKgoaKgoaKgoaKgoaKgoaKgoaKASZigoaJZtNn///88MUhjAAAAOHRSTlMAAAAAWP2fomNT8fPy9f4TODVk+YKEhlLzOCpIR0UUkv3585YTPj9AJ0nx9vqZTFiZ9WQ1c/v+8s7KmYgAAAABYktHRDs5DvRsAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABAUlEQVR42u3YRw7CMBRFUUgg9N5L6L33tv+FMY9kLEe2RaR7F/DfGf9YTEvxRPIVLj37AAAAAAAAQKQBnlqptOPoBbwV8wAAAAAAwJ8CMtmcqHyhaAFQKgurVAvmAb+Kl3MAAAAAAABAVAE1r94I1mxZBLQ7qlsAAAAAYArgut1eX5Y/cA0ChqOxrIlvEjD9SBv3hYBsMSnMBqCUSYizAJAEAAAAAAAAAAAAwADAmc0Xopar4IPDBGC92Yra7W0ADjvxUQ8AAAAAAIQDHE9TWcOuOYBiAAAAAKANcL5cO2G63u56AI/zsx2m5/atB2AkAAAAAAAAAAAAAAAAAAAQBHwB/SLmwJclsisAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTQtMDYtMTVUMDk6MDI6MTYtMDc6MDAhb+VcAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE0LTA2LTEyVDExOjA4OjE5LTA3OjAwi613rgAAABZ0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMDvo9WkAAAAASUVORK5CYII=","$Meta":{"Type":"ActionTemplate"}},{"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"}},{"Id":"143ba6fd-968f-4f24-980b-49e47aa98f71","Name":"Azure Web App - Disable app_offline","Description":"This step template will remove an app_offline file from an Azure WebApp to safely bring the app domain online following a 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:52:46.792Z","ActionType":"Octopus.Script","Author":"harrisonmeister","Packages":[],"Parameters":[{"Id":"b847fd97-bc71-4c89-99fb-bd5c2327027a","Name":"AzWebApp.DisableAppOffline.AzWebAppName","Label":"Azure Web App name","HelpText":"Provide the Azure Web App name.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"0b2edf69-da0d-4750-882a-4036c67f0129","Name":"AzWebApp.DisableAppOffline.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.DisableAppOffline.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.DisableAppOffline.WebAppName}`.","DefaultValue":"$#{AzWebApp.DisableAppOffline.WebAppName}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"1c18f666-c91d-411c-a86b-b92d0bddc4ed","Name":"AzWebApp.DisableAppOffline.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.DisableAppOffline.Deployment.KuduRestApiUrl","Label":"Deployment REST API Url","HelpText":"*Optional:* Provide a custom deployment REST API URL. Default is: `https://#{AzWebApp.DisableAppOffline.AzWebAppName}.scm.azurewebsites.net/api/vfs`.","DefaultValue":"https://#{AzWebApp.DisableAppOffline.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$AzWebAppName = $OctopusParameters[\"AzWebApp.DisableAppOffline.AzWebAppName\"]\n$Filename = $OctopusParameters[\"AzWebApp.DisableAppOffline.Filename\"]\n$DeployUsername = $OctopusParameters[\"AzWebApp.DisableAppOffline.Deployment.Username\"]\n$DeployPassword = $OctopusParameters[\"AzWebApp.DisableAppOffline.Deployment.Password\"]\n$DeploymentUrl = $OctopusParameters[\"AzWebApp.DisableAppOffline.Deployment.KuduRestApiUrl\"]\n\n# Validation\nif ([string]::IsNullOrWhiteSpace($AzWebAppName)) {\n throw \"Required parameter AzWebApp.DisableAppOffline.AzWebAppName not specified\"\n}\n\nif ([string]::IsNullOrWhiteSpace($Filename)) {\n throw \"Required parameter AzWebApp.DisableAppOffline.Filename not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($DeployUsername)) {\n throw \"Required parameter AzWebApp.DisableAppOffline.Deployment.Username not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($DeployPassword)) {\n throw \"Required parameter AzWebApp.DisableAppOffline.Deployment.Password not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($DeploymentUrl)) {\n throw \"Required parameter AzWebApp.DisableAppOffline.Deployment.KuduRestApiUrl not specified\"\n}\n\n$DeploymentUrl = $DeploymentUrl.TrimEnd('/')\n\n# Local variables\n$StepName = $OctopusParameters[\"Octopus.Step.Name\"]\n\nWrite-Verbose \"AzWebApp.DisableAppOffline.AzWebAppName: $AzWebAppName\"\nWrite-Verbose \"AzWebApp.DisableAppOffline.Filename: $FileName\"\nWrite-Verbose \"AzWebApp.DisableAppOffline.Deployment.Username: $DeployUsername\"\nWrite-Verbose \"AzWebApp.DisableAppOffline.Deployment.Password: ********\"\nWrite-Verbose \"AzWebApp.DisableAppOffline.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 $filePathUri = \"$DeploymentUrl/site/wwwroot/$filename\"\n Write-Host \"Invoking Delete request for '$filePathUri'\"\n $response = Invoke-RestMethod -Method Delete -Uri $filePathUri -Headers $headers\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/azure-web-app-disable-appoffline.json","Website":"/step-templates/143ba6fd-968f-4f24-980b-49e47aa98f71","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"}},{"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/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"}},{"Id":"f87564d3-50e0-4265-8ed7-d95e3e21f869","Name":"Azure Web App - Get Deployment User","Description":"This step template will retrieve a set of [deployment credentials](https://docs.microsoft.com/en-gb/azure/app-service/deploy-configure-credentials) for an Azure Web App.\n\nIt will create two Octopus [sensitive output variables](https://octopus.com/docs/projects/variables/output-variables#sensitive-output-variables) for use in other deployment or runbook steps. They will be named:\n\n- `userName` - the username from the provided deployment credentials.\n- `userPwd` - the password from the provided deployment credentials.\n\n**Required:** \n- An azure account with permissions to retrieve deployment credentials for the named Azure Web App.\n- The Azure CLI (`az`) is required to run this script. If running on a worker or deployment target, ensure this is installed.\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:13:19.362Z","ActionType":"Octopus.AzurePowerShell","Author":"adamoctoclose","Packages":[],"Parameters":[{"Id":"7f36b854-6cc8-4a64-a7b4-c3110044cd4b","Name":"AzWebApp.DeploymentCreds.AzWebAppName","Label":"Azure Web App name","HelpText":"Provide the Azure Web App name.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"41c6ca57-2078-4cbb-8e92-26c2207a3ef7","Name":"AzWebApp.DeploymentCreds.AzResourceGroup","Label":"Azure Resource Group","HelpText":"Provide Azure resource group.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"149ef6c1-716c-4738-9985-ea47e5fc6e9b","Name":"AzWebApp.DeploymentCreds.AzAccount","Label":"Azure Account","HelpText":"Provide Azure Account.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"9ac94483-5e3b-49b3-9014-eb4875b95798","Name":"AzWebApp.DeploymentCreds.PublishCredentialType","Label":"Deployment credential type","HelpText":"Choose type of Deployment credentials should be retrieved. Default is: `MSDeploy`\n\nAvailable options are:\n\n- `MSDeploy`\n- `FTP`\n- `ZipDeploy`","DefaultValue":"MSDeploy","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"MSDeploy|MSDeploy\nFTP|FTP\nZipDeploy|ZipDeploy"}}],"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$resourceGroupName = $OctopusParameters[\"AzWebApp.DeploymentCreds.AzResourceGroup\"]\n$WebAppName = $OctopusParameters[\"AzWebApp.DeploymentCreds.AzWebAppName\"]\n$PublishCredentialType = $OctopusParameters[\"AzWebApp.DeploymentCreds.PublishCredentialType\"]\n$StepName = $OctopusParameters[\"Octopus.Step.Name\"]\n\n# Validation\nif ([string]::IsNullOrWhiteSpace($resourceGroupName)) {\n throw \"Required parameter AzWebApp.DeploymentCreds.AzResourceGroup not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($WebAppName)) {\n throw \"Required parameter AzWebApp.DeploymentCreds.AzWebAppName not specified\"\n}\nif ([string]::IsNullOrWhiteSpace($PublishCredentialType)) {\n throw \"Required parameter AzWebApp.DeploymentCreds.PublishCredentialType not specified\"\n}\n \nWrite-Verbose \"Azure Resource Group Name: $resourceGroupName\"\nWrite-Verbose \"Azure Web App Name: $WebAppName\"\nWrite-Verbose \"Publish Credential Type: $PublishCredentialType\"\n\nWrite-Host \"Getting $PublishCredentialType publish profile deployment credentials...\"\n\n$profiles = az webapp deployment list-publishing-profiles --resource-group $resourceGroupName --name $WebAppName | ConvertFrom-Json | where { $_.publishMethod -ieq $PublishCredentialType } \n\nSet-OctopusVariable -name \"userName\" -value $profiles.userName -Sensitive\nWrite-Highlight \"Created output variable: ##{Octopus.Action[$StepName].Output.userName}\"\nSet-OctopusVariable -name \"userPWD\" -value $profiles.userPWD -Sensitive\nWrite-Highlight \"Created output variable: ##{Octopus.Action[$StepName].Output.userPWD}\"\n\nWrite-Host \"Output variables generated for deployment credentials!\"","Octopus.Action.Azure.AccountId":"#{AzWebApp.DeploymentCreds.AzAccount}","OctopusUseBundledTooling":"False"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-web-app-get-deployment-user.json","Website":"/step-templates/f87564d3-50e0-4265-8ed7-d95e3e21f869","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"}},{"Id":"1f40e418-17bf-4b3e-bbe7-c6d41cbded93","Name":"Azure Web App - Restart","Description":"Restarts an azure web app.\n
\n\n*Note This template is designed to run against an azure web app octopus target
*\n*Depends on Azure CLI and powershell to be installed on the running machine
*","Version":2,"ExportedAt":"2022-05-17T10:59:12.694Z","ActionType":"Octopus.AzurePowerShell","Author":"zogamorph","Packages":[],"Parameters":[{"Id":"e732ddaa-a43b-4369-8813-065286069d65","Name":"azWebApp.AzureAcct","Label":"Azure Account","HelpText":"The azure account that has access to the web app","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"901ec60b-0ffd-4d08-be6f-fa9e8aec457a","Name":"azWebApp.StartIfStopped","Label":"Start if stopped","HelpText":"If the web app is stopped, start it","DefaultValue":"False","DisplaySettings":{"Octopus.ControlType":"Checkbox"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","OctopusUseBundledTooling":"False","Octopus.Action.Azure.AccountId":"#{azWebApp.AzureAcct}","Octopus.Action.Script.ScriptBody":"try {az --version}\ncatch\n{\n throw \"az CLI not installed\"\n}\n\n$webApp = $OctopusParameters[\"Octopus.Action.Azure.WebAppName\"]\n$resourceGroup = $OctopusParameters[\"Octopus.Action.Azure.ResourceGroupName\"]\n$startIfStopped = $OctopusParameters[\"azWebApp.StartIfStopped\"]\n\nWrite-Host \"Checking webapp $webApp status in resource group $resourceGroup\"\n\n$appState = az webapp list --resource-group $resourceGroup --query \"[?name=='$webApp'].{state: state, hostName: defaultHostName}\" | ConvertFrom-Json\nif($appState.state -eq \"stopped\")\n{\n if($startIfStopped -eq 'true')\n {\n Write-Host \"Webapp is not running. Starting...\" -NoNewline\n \taz webapp start --name $webApp --resource-group $resourceGroup\n Write-Host \"Done\"\n }\n else\n {\n Throw \"Webapp is not running.\"\n }\n}\n\nWrite-Host \"Webapp running, restarting\"\n\nelse\n{\n\tWrite-Host \"Restarting $webApp in resource group $resourceGroup\"\n\taz webapp restart --name $webApp --resource-group $resourceGroup\n}\n\nStart-Sleep -s 5\n\n$appState = az webapp list --resource-group $resourceGroup --query \"[?name=='$webApp'].{state: state, hostName: defaultHostName}\" | ConvertFrom-Json\n\nif($appState.state -ne \"running\")\n{\n\tThrow \"Webapp failed to start. Check the app's activity/error log\"\n}\n\nwrite-host \"Webapp $webApp running. Check at: $($appState.hostName)\"\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-web-app-restart.json","Website":"/step-templates/1f40e418-17bf-4b3e-bbe7-c6d41cbded93","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"}},{"Id":"43cfc12d-5ae9-425d-ab01-7124ffdd9ee6","Name":"Azure Web App - Rolling Restart","Description":"Performs a delayed rolling restart of all instances within an Azure Web App\n
\n\n*Note This template is designed to run against an azure web app octopus target
*\n*Depends on Azure CLI and powershell to be installed on the running machine
*","Version":1,"ExportedAt":"2021-04-08T20:19:36.856Z","ActionType":"Octopus.AzurePowerShell","Author":"tekguy","Packages":[],"Parameters":[{"Id":"6670dc01-4323-41b8-87f4-a824608bad71","Name":"azWebApp.AzureAcct","Label":"Azure Account","HelpText":"The azure account that has access to the web app","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"56dc3fcb-237d-4618-944a-441bd3d089c5","Name":"azWebApp.WebAppName","Label":"App Service Name","HelpText":"The azure web app name","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"7fc59af9-00cf-4e3f-995d-1ccca3057324","Name":"azWebApp.ResourceGroup","Label":"Azure Resource Group","HelpText":"The azure resource group","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"8fda8110-e3bb-4881-89dc-c148a7bd1943","Name":"azWebApp.RestartDelay","Label":"Restart Delay","HelpText":"Delay between instance restart","DefaultValue":"30","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","OctopusUseBundledTooling":"False","Octopus.Action.Azure.AccountId":"#{azWebApp.AzureAcct}","Octopus.Action.Script.ScriptBody":"try {az --version}\ncatch\n{\n throw \"az CLI not installed\"\n}\n\n$webAppName = $OctopusParameters[\"azWebApp.WebAppName\"]\n$resourceGroup = $OctopusParameters[\"azWebApp.ResourceGroup\"]\n$restartDelay = $OctopusParameters[\"azWebApp.RestartDelay\"]\n\n\n\nWrite-Host \"Web App Name: $webAppName\"\nWrite-Host \"Resource Group: $resourceGroup\"\nWrite-Host \"Restart Delay: $restartDelay\"\n\nWrite-Host \"Checking $webAppName status in resource group $resourceGroup\"\n\n$appState = az webapp list --resource-group $resourceGroup --query \"[?name=='$webAppName'].{state: state, hostName: defaultHostName}\" | ConvertFrom-Json\n\n# only execute if running\nif($appState.state -eq \"running\")\n{\n $appInstances = az webapp list-instances -n $webAppName --resource-group $resourceGroup --query '[].{Id: id}' | ConvertFrom-Json\n Write-Host \"\" $appInstances.Count \"Instance(s) found`r`n\" -ForegroundColor Green\n\n if($appInstances.count -gt 0){\n foreach ($instance in $appInstances){\n Write-Host \"Restarting Instance: $instance\"\n az webapp restart --ids $instance.Id\n Write-Host \"Pausing $restartDelay second(s)`r`n\" -ForegroundColor Yellow\n Start-Sleep -Seconds $restartDelay\n }\n }\n}\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-web-app-rolling-restart.json","Website":"/step-templates/43cfc12d-5ae9-425d-ab01-7124ffdd9ee6","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"}},{"Id":"850667b2-567d-46ba-a87d-d85dc31ebc83","Name":"Azure Web App - Set App Settings","Description":"Sets the Azure web app settings of a targeted Azure web app deployment target. Will use the deployment slot if defined.\n
\n\n*Note This template is designed to run against an azure web app octopus target
*\n*Depends on Azure CLI and powershell to be installed on the worker
*","Version":1,"ExportedAt":"2020-06-30T15:48:06.905Z","ActionType":"Octopus.AzurePowerShell","Author":"xtreampb","Packages":[],"Parameters":[{"Id":"598025e6-2d89-49bf-8abb-fda6da181de5","Name":"azureWebAppSettings.azAccount","Label":"Azure Account","HelpText":"An Azure account with permissions to the subscription and web app being modified","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"5d232cfd-8e9f-4b3e-8c4e-7bf3a75ced19","Name":"azureWebAppSettings.settings","Label":"Web App Settings","HelpText":"The web app settings to append or update. Each new setting should be on a new line as a key value pair using the template `key=value`","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"9bbee2cf-c57c-45db-8a7f-62a752779b56","Name":"azureWebAppSettings.isSlotSettings","Label":"Is Slot Settings","HelpText":"This is used to distinguish what settings are slot specific and which one are not. Slot setting do not follow the deployed app when the slot is swapped.","DefaultValue":"false","DisplaySettings":{"Octopus.ControlType":"Checkbox"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Azure.AccountId":"#{azureWebAppSettings.azAccount}","Octopus.Action.Script.ScriptBody":"$webAppName = $OctopusParameters[\"Octopus.Action.Azure.WebAppName\"]\n$rg = $OctopusParameters[\"Octopus.Action.Azure.ResourceGroupName\"]\n$slot = $OctopusParameters[\"Octopus.Action.Azure.DeploymentSlot\"]\n$isSlotSettings = $OctopusParameters[\"azureWebAppSettings.isSlotSettings\"]\n\n$settingsType = \"settings\"\n\n$appSettings = $OctopusParameters[\"azureWebAppSettings.settings\"]\n\n$settings = \"\"\n\nWrite-Host \"Parsing Settings\"\n\n$appSettings -split \"`n\" | ForEach-Object { $settings += \"$_ \"}\n\n$settings = $settings.TrimEnd(' ')\n\n$cmdArgs = \"--name $webAppName --resource-group $rg\"\n\nif(![string]::IsNullOrEmpty($slot))\n{\n\tif($isSlotSettings -eq 'true')\n {\n \t$settingsType = \"slot-settings\"\n }\n \n\t$settings += \" --slot $slot\"\n}\n\n$settingsArgs = \" --$settingsType $settings\"\n\nWrite-Host \"Setting app settings\"\n\n$cmd = \"az webapp config appsettings set $cmdArgs $settingsArgs\"\n\nwrite-verbose \"command to execute: $cmd\"\n\nInvoke-Expression $cmd\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-web-app-set-app-settings.json","Website":"/step-templates/850667b2-567d-46ba-a87d-d85dc31ebc83","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"}},{"Id":"36791d2d-aa55-4bc7-bee4-a0d12d73f78e","Name":"Azure Web App - Set Traffic","Description":"Sets the traffic distribution between multiple web app slots.\n
\n\n*Note This template is designed to run against an azure web app octopus target, but will not use the slot defined.
*\n*Depends on Azure CLI and powershell to be installed on the worker
*","Version":1,"ExportedAt":"2020-06-29T16:52:24.007Z","ActionType":"Octopus.AzurePowerShell","Author":"xtreampb","Packages":[],"Parameters":[{"Id":"53d1306d-691c-4739-a09a-8fc9d66c60d3","Name":"azWebAppSetTraffic.AzureAcct","Label":"Azure Account","HelpText":"An Azure account with permissions to the subscription and web app being modified","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"1f788822-9980-44cc-9e9c-f87db5998dd5","Name":"azWebAppSetTraffic.trafficDistro","Label":"Traffic Distribution","HelpText":"\nThe distribution of traffic in percent (0-100). Each web app slot should be defined on a separate line. Any remaining percentage will automatically be applied to production.\n
\n*Example*\n```\nmyOtherSlot=10\nstage=30\n```\n
","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Azure.AccountId":"#{azWebAppSetTraffic.AzureAcct}","Octopus.Action.Script.ScriptBody":"$webAppName = $OctopusParameters[\"Octopus.Action.Azure.WebAppName\"]\n$rg = $OctopusParameters[\"Octopus.Action.Azure.ResourceGroupName\"]\n\n$trafficDistro = $OctopusParameters[\"azWebAppSetTraffic.trafficDistro\"]\n\n$cmdArgs = \"--name $webAppName --resource-group $rg\" \n\n$cmdAction = \"clear\"\n\nwrite-host \"Checking distribution\"\nif(![string]::IsNullOrEmpty($trafficDistro))\n{\n\t$distribution = \"\"\n\n\t$trafficDistro -split \"`n\" | ForEach-Object { $distribution += \"$_ \"}\n\n\t$distribution = $distribution.TrimEnd(' ')\n \n $cmdArgs += \" --distribution $distribution\"\n \n $cmdAction = \"set\"\n}\n\n\n$cmd = \"az webapp traffic-routing $cmdAction $cmdArgs\"\n\nwrite-verbose \"cmd to invoke: $cmd\"\n\nwrite-host \"setting distributions\"\ninvoke-expression $cmd\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-web-app-set-traffic.json","Website":"/step-templates/36791d2d-aa55-4bc7-bee4-a0d12d73f78e","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"}},{"Id":"f256502a-4143-4d29-914e-80e541b05783","Name":"Azure Web App - Slot Swap","Description":"Swaps an azure web app slot. Defaults to the deployment slot defined in the web app target.\n
\n\n*Note This template is designed to run against an azure web app octopus target
*\n*Depends on Azure CLI and powershell to be installed on the running machine
*","Version":3,"ExportedAt":"2020-06-25T15:05:37.259Z","ActionType":"Octopus.AzurePowerShell","Author":"harrisonmeister","Packages":[],"Parameters":[{"Id":"a204505b-f995-40ff-95b3-300638d9b9df","Name":"azureWebAppSwap.AzAccount","Label":"Azure Account","HelpText":null,"DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"0b3383f9-31ae-402c-af57-be3b82a3d5b9","Name":"azWebAppSwap.targetSlot","Label":"Target Slot","HelpText":null,"DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"7e4ed213-d5bb-4725-b13f-78e366535479","Name":"azWebAppSwap.sourceSlot","Label":"Source Slot","HelpText":null,"DefaultValue":"#{Octopus.Action.Azure.DeploymentSlot}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"$rg = $OctopusParameters[\"Octopus.Action.Azure.ResourceGroupName\"]\n$webAppName = $OctopusParameters[\"Octopus.Action.Azure.WebAppName\"]\n$destinationSlot = $OctopusParameters[\"azWebAppSwap.targetSlot\"]\n$sourceSlot = $OctopusParameters[\"azWebAppSwap.sourceSlot\"]\n\nif([string]::IsNullOrEmpty($sourceSlot))\n{\n\tthrow \"value for source slot must be provided\"\n}\n\n$cmdArgs = \"-g $rg -n $webAppName -s $sourceSlot\"\n\nif(![string]::IsNullOrEmpty($destinationSlot)) {$cmdArgs += \" --target-slot $destinationSlot\"}\n\n$cmd = \"az webapp deployment slot swap $cmdArgs\"\n\nwrite-verbose \"command being invoked: $cmd\"\n\nInvoke-Expression $cmd","Octopus.Action.Azure.AccountId":"#{azureWebAppSwap.AzAccount}"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-web-app-slot-swap.json","Website":"/step-templates/f256502a-4143-4d29-914e-80e541b05783","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"}},{"Id":"96ce9c63-91b5-4773-9511-830a2e106083","Name":"Azure Web App - Start","Description":"Starts an azure web app.\n
\n\n*Note This template is designed to run against an azure web app octopus target
*\n*Depends on Azure CLI and powershell to be installed on the running machine
*","Version":1,"ExportedAt":"2020-06-08T18:36:48.569Z","ActionType":"Octopus.AzurePowerShell","Author":"xtreampb","Packages":[],"Parameters":[{"Id":"bcb5fe61-4f02-44af-85b9-8c9197567d50","Name":"azWebApp.AzureAcct","Label":"Azure Account","HelpText":"The azure account that has access to the web app","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","OctopusUseBundledTooling":"False","Octopus.Action.Azure.AccountId":"#{azWebApp.AzureAcct}","Octopus.Action.Script.ScriptBody":"try\n{\n\taz --version\n}\n\ncatch\n{\n\tthrow \"az cli not installed\"\n}\n\n$webApp = $OctopusParameters[\"Octopus.Action.Azure.WebAppName\"]\n$resourceGroup = $OctopusParameters[\"Octopus.Action.Azure.ResourceGroupName\"]\n\n$appState = az webapp list --resource-group $resourceGroup --query \"[?name=='$webApp'].{state: state, hostName: defaultHostName}\" | ConvertFrom-Json\n\nif($appState.state -eq 'running')\n{\n\tWrite-Host \"Web App $webApp already running\"\n return \n}\n\nWrite-Host \"Starting web app $webApp in resource group $resourceGroup\"\naz webapp start --name $webApp --resource-group $resourceGroup\n\nStart-Sleep -s 5\n\n$appState = az webapp list --resource-group $resourceGroup --query \"[?name=='$webApp'].{state: state, hostName: defaultHostName}\" | ConvertFrom-Json\n\nif($appState.state -ne \"running\")\n{\n\tThrow \"Webapp failed to start. Check the app's activity/error log\"\n}\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-web-app-start.json","Website":"/step-templates/96ce9c63-91b5-4773-9511-830a2e106083","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"}},{"Id":"5178ba6d-e0b9-4176-8487-148060ed3a70","Name":"Azure Web App - Stop","Description":"Stops an azure web app.\n
\n\n*Note This template is designed to run against an azure web app octopus target
*\n*Depends on Azure CLI and powershell to be installed on the running machine
*","Version":1,"ExportedAt":"2020-06-08T18:36:07.610Z","ActionType":"Octopus.AzurePowerShell","Author":"xtreampb","Packages":[],"Parameters":[{"Id":"bcb5fe61-4f02-44af-85b9-8c9197567d50","Name":"azWebApp.AzureAcct","Label":"Azure Account","HelpText":"The azure account that has access to the web app","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","OctopusUseBundledTooling":"False","Octopus.Action.Azure.AccountId":"#{azWebApp.AzureAcct}","Octopus.Action.Script.ScriptBody":"try\n{\n\taz --version\n}\n\ncatch\n{\n\tthrow \"az cli not installed\"\n}\n\n$webApp = $OctopusParameters[\"Octopus.Action.Azure.WebAppName\"]\n$resourceGroup = $OctopusParameters[\"Octopus.Action.Azure.ResourceGroupName\"]\n\n$appState = az webapp list --resource-group $resourceGroup --query \"[?name=='$webApp'].{state: state, hostName: defaultHostName}\" | ConvertFrom-Json\n\nif($appState.state -eq 'stopped')\n{\n\tWrite-Host \"Web App $webApp already stopped\"\n return\n}\n\nWrite-Host \"Stopping webapp $webApp in group $resourceGroup\"\naz webapp stop --name $webApp --resource-group $resourceGroup\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-web-app-stop.json","Website":"/step-templates/5178ba6d-e0b9-4176-8487-148060ed3a70","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"}},{"Id":"140d22e8-abe9-4a32-aab7-20af667c6255","Name":"Azure Website - Load App Settings From File (Geta)","Description":"Loads app settings from a json file (e.g. local.settings.json) which is also json-transformed to inject environment-specific values.","Version":7,"ExportedAt":"2019-01-22T09:58:08.811Z","ActionType":"Octopus.AzurePowerShell","Author":"sarbis","Packages":[{"Id":"31f79f978a2e46f9b3add02f695e672b","Name":"LoadAppSettingsFromFile.Package","PackageId":"#{Parameters.PackageId}","FeedId":null,"AcquisitionLocation":"Server","Properties":{"Extract":"True"}}],"Parameters":[{"Id":"e21c4265-7e92-4893-a359-3d8c4b0223c2","Name":"Parameters.ResourceGroup.Name","Label":"Resource group name","HelpText":"Name of the target resource group.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"4485ab2e-2003-4fab-814f-90ce9a338cce","Name":"Parameters.WebApp.Name","Label":"Webapp / function name","HelpText":"Name of the target webapp.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"f589143a-3f46-4a2b-b14f-02469ed80c19","Name":"Parameters.SettingsFile.Path","Label":"Settings file path","HelpText":"Path of the JSON settings file relative to script directory. Or in most of the cases easiest is to use Octopus Action variable for the extract path: `#{Octopus.Action.Package[LoadAppSettingsFromFile.Package].ExtractedPath}`","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"fb46e50c-283a-4d7d-b4ec-2a171f76d8c4","Name":"Parameters.DeploySlot.Name","Label":"Deploy slot name","HelpText":"Name of the deploy slot. Production slot will be updated if left blank.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"81b491a9-e1f5-4b22-b9d2-22df2bb60686","Name":"Parameters.PackageId","Label":"Package Id","HelpText":"Id of the referenced package which when extracted might contain the settings file.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Azure.AccountId":"#{Azure.Subscription.Name}","Octopus.Action.Package.JsonConfigurationVariablesEnabled":"True","Octopus.Action.EnabledFeatures":"Octopus.Features.JsonConfigurationVariables","Octopus.Action.Package.JsonConfigurationVariablesTargets":"#{Parameters.SettingsFile.Path}","Octopus.Action.Script.ScriptFileName":null,"Octopus.Action.Package.PackageId":"#{Utilities.PackageId}","Octopus.Action.Package.FeedId":"feeds-builtin","Octopus.Action.Package.DownloadOnTentacle":"False","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"Function Get-Parameter($Name, $Required, $Default, [switch]$FailOnValidate) {\n $result = $null\n $errMessage = [string]::Empty\n\n If ($null -ne $OctopusParameters) {\n $result = $OctopusParameters[$Name]\n Write-Host (\"Octopus parameter value for \" + $Name + \": \" + $result)\n }\n\n If ($null -eq $result) {\n $variable = Get-Variable $Name -EA SilentlyContinue\n if ($null -ne $variable) {\n $result = $variable.Value\n }\n }\n\n If ($null -eq $result) {\n If ($Required) {\n $errMessage = \"Mandatory parameter '$Name' not specified\"\n }\n Else {\n $result = $Default\n }\n } \n\n If (-Not [string]::IsNullOrEmpty($errMessage)) {\n If ($FailOnValidate) {\n Throw $errMessage\n }\n Else {\n Write-Warning $errMessage\n }\n }\n\n return $result\n}\n\nFunction Main(\n [Parameter(Mandatory = $true)][string] $azureResourceGroupName,\n [Parameter(Mandatory = $true)][string] $azureWebAppName,\n [Parameter(Mandatory = $true)][string] $azureSettingsFilePath,\n [Parameter(Mandatory = $false)][string] $azureDeploySlotName = $null\n) {\n Write-Host \"Start AzureLoadAppSettingsFromFile\"\n\n If ((Test-Path $azureSettingsFilePath) -ne $true) {\n Write-Warning \"Settings file '$azureSettingsFilePath' not found!\"\n Exit 0\n }\n\n $settingsJson = Get-Content -Raw -Path $azureSettingsFilePath | ConvertFrom-Json\n\n If (($settingsJson -eq $null) -or ($settingsJson.Values -eq $null)) {\n Write-Warning \"Settings file '$azureSettingsFilePath' doesn't contain Values object. Unable to load app settings!\"\n Exit 0\n }\n\n # Parse app settings into a hashtable object\n\n $settingsValues = $settingsJson.Values\n\n $appSettings = @{}\n $settingsValues.psobject.properties | Foreach { $appSettings[$_.Name] = $_.Value }\n\n # Set app settings for either slot or a webapp\n\n If ([string]::IsNullOrEmpty($azureDeploySlotName)) {\n Set-AzureRmWebApp -Name $azureWebAppName -ResourceGroupName $azureResourceGroupName -AppSettings $appSettings\n } Else {\n Set-AzureRmWebAppSlot -Name $azureWebAppName -ResourceGroupName $azureResourceGroupName -AppSettings $appSettings -Slot $azureDeploySlotName\n }\n\n Write-Host \"End AzureLoadAppSettingsFromFile\"\n}\n\n& Main `\n -azureResourceGroupName (Get-Parameter \"Parameters.ResourceGroup.Name\" $true \"\" $true) `\n -azureWebAppName (Get-Parameter \"Parameters.WebApp.Name\" $true \"\" $true) `\n -azureSettingsFilePath (Get-Parameter \"Parameters.SettingsFile.Path\" $true \"\" $true) `\n -azureDeploySlotName (Get-Parameter \"Parameters.DeploySlot.Name\" $false \"\" $true)"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-load-appsettings-from-file.json","Website":"/step-templates/140d22e8-abe9-4a32-aab7-20af667c6255","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"}},{"Id":"07b23f27-e76a-4b4b-acb1-017006a83269","Name":"Azure Windows - Install Octopus Tentacle","Description":"This step template will install the latest tentacle on an Azure hosted, Windows virtual machine. This will also open the firewall for inbound traffic on port 10933 on both the NSG and the the vm.\n
\n*note: expects the Azure CLI to be installed on the worker running this task*","Version":4,"ExportedAt":"2022-02-09T15:56:03.173Z","ActionType":"Octopus.AzurePowerShell","Author":"harrisonmeister","Packages":[],"Parameters":[{"Id":"dea51842-271f-48fa-901e-243488049f97","Name":"installWinTentacle.AzureAccount","Label":"Azure Account","HelpText":"Azure account with permissions to the virtual machine in which to install the tentacle on","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"6a97548c-3b97-4a19-8b9a-45aa58ac62d9","Name":"installWinTentacle.azRgName","Label":"Azure Resource Group","HelpText":"The name of the resource group housing the NSG and VM","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"d9efb017-65c0-4010-b09f-0a6a34fc009f","Name":"installWinTentacle.azNsgName","Label":"NSG Name","HelpText":"The name of the azure network security group to create ","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"36c6d441-9fe8-4ea2-957a-2135aa9d1687","Name":"installWinTentacle.azNsgRulePriority","Label":"Azure NSG Rule Priority","HelpText":"the priority to assign to the NSG rule created for the octopus tentacle. Defaults to 400","DefaultValue":"400","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"e4358aec-2798-412a-bcd2-1c7e41a0728d","Name":"installWinTentacle.azVmName","Label":"VM Name","HelpText":"The name of the virtual machine to target when ","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"8dbe0a29-4e0f-43f8-8ef2-ae23a2884e85","Name":"installWinTentacle.octoServerThumb","Label":"Server Thumbprint","HelpText":"The Thumbprint of the octopus server","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"a0859551-6c84-45d1-af2b-c57becb4e8ef","Name":"installWinTentacle.octoApiKey","Label":"API Key","HelpText":"The API key used to configure the tentacle.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"dd07815d-bfb7-43b9-90f8-21ec5a2d2953","Name":"installWinTentacle.octopusRoles","Label":"Roles","HelpText":"Roles to assign to this tentacle installation.
\n*Note: Each role should be on it's own line*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"d3ffb38e-7fcf-4547-be9a-6cd8e46f8e5e","Name":"installWinTentacle.octopusEnvironments","Label":"Environments","HelpText":"Environments to assign this tentacle installation to.
\n*Note: Each environment should be on its own line*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"}},{"Id":"15150827-7bd3-4146-a798-66344851f602","Name":"instrallTentacle.octoServerUrl","Label":"Server Url","HelpText":"The server url to register the tentacle with. Defaults to the base url","DefaultValue":"#{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"9bcd6bb5-2db3-453f-b4f6-6a78f3c39b59","Name":"installWinTentacle.tentacleType","Label":"Tentacle Type","HelpText":"Select between a listing or polling tentacle","DefaultValue":"TentaclePassive","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"TentaclePassive|Listening\nTentacleActive|Polling"}},{"Id":"6bb98570-fe3e-4ab7-adfb-79ef7ce5c2ce","Name":"installWinTentacle.tentacleHostName","Label":"Tentacle Host Name","HelpText":"The host name to register the listening tentacles with. Octopus deploy server uses this value to reach out to the vm.
\n*Note: Leave blank to automatically use assigned public IP address.*","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"7cbbafc4-5eed-41bd-ad9d-c1e67567a469","Name":"installWinTentacle.portNumber","Label":"Port Number","HelpText":"Port number used when installing and registering the tentacle. This port is also opened when installing a listening tentacle","DefaultValue":"10933","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Azure.AccountId":"#{installWinTentacle.AzureAccount}","Octopus.Action.Script.ScriptBody":"$nsgName = $OctopusParameters[\"installWinTentacle.azNsgName\"]\n$resourceGroup = $OctopusParameters[\"installWinTentacle.azRgName\"]\n$nsgRulePriority = $OctopusParameters[\"installWinTentacle.azNsgRulePriority\"]\n$vmName = $OctopusParameters[\"installWinTentacle.azVmName\"]\n$serverUri = $OctopusParameters[\"instrallTentacle.octoServerUrl\"]\n$apiKey = $OctopusParameters[\"installWinTentacle.octoApiKey\"]\n$rolesRaw = $OctopusParameters[\"installWinTentacle.octopusRoles\"]\n$enviroRaw = $OctopusParameters[\"installWinTentacle.octopusEnvironments\"]\n$octoThumb = $OctopusParameters[\"installWinTentacle.octoServerThumb\"]\n$comStyle = $OctopusParameters[\"installWinTentacle.tentacleType\"]\n$hostname = $OctopusParameters[\"installWinTentacle.tentacleHostName\"]\n$portNumber = $OctopusParameters[\"installWinTentacle.portNumber\"]\n\nWrite-Host \"Parsing Parameters\"\n\nif([string]::IsNullOrEmpty($rolesRaw))\n{\n\tthrow \"At least one role must be defined\"\n}\n\nif([string]::IsNullOrEmpty($enviroRaw))\n{\n\tthrow \"At least one environment must be defined\"\n}\n\n$roles = \"\"\n$rolesRaw -split \"`n\" | ForEach-Object { $roles += \"--role $_ \"}\n$roles = $roles.TrimEnd(' ')\n\n$environments = \"\"\n$enviroRaw -split \"`n\" | ForEach-Object { $environments += \"--environment $_ \"}\n$environments = $environments.TrimEnd(' ')\n\nif($comStyle -eq \"TentaclePassive\")\n{\n\tif([string]::IsNullOrEmpty($hostname))\n {\n \t$hostname = az vm show -d -g $resourceGroup -n $vmName --query publicIps -o tsv\n $hostname = $hostname.Trim(\"`n\")\n }\n \n $noListen = \"--port $portNumber --noListen `\"false`\"\"\n $comStyle += \" --publicHostName=`\"$hostname`\"\"\n $openFirewall = 'true'\n}\nelse\n{\n\t$noListen = \"--noListen `\"true`\"\"\n $openFirewall = 'false'\n}\n\nif($openFirewall -eq 'true')\n{\n\tWrite-Host \"Creating NSG Rule\"\n\taz network nsg rule create --name \"OctopusTentacle\" --nsg-name $nsgName --priority $nsgRulePriority --resource-group $resourceGroup --direction Inbound --destination-port-ranges $portNumber\n}\n\n$remoteScript = @\"\n`$msiLocation = \"`$env:TEMP\\`$(new-guid).msi\"\n\nif(`$env:PROCESSOR_ARCHITECTURE -eq \"x86\") \n{\n `$downloadPath = \"http://octopus.com/downloads/latest/OctopusTentacle\"\n}\nelse\n{\n `$downloadPath = \"http://octopus.com/downloads/latest/OctopusTentacle64\"\n}\n\nInvoke-WebRequest -Uri `$downloadPath -OutFile `$msiLocation -UseBasicParsing\n\nStart-Process `$msiLocation /quiet -Wait\n\nRemove-Item `$msiLocation\n\n\"@\n\nWrite-Host \"Installing tentacle on remote machine\"\n\nSet-Content -Value $remoteScript -Path \".\\script.ps1\"\n\n$result = az vm run-command invoke --command-id RunPowerShellScript --name $vmName -g $resourceGroup --scripts \"@script.ps1\"\n\n$result\n\n$msg = (($result | convertfrom-json).value | where {$_.code -eq \"componentstatus/stderr/succeeded\"}).message\n\nif(![string]::IsNullOrEmpty($msg))\n{\n\tthrow $msg\n}\n\nWrite-Verbose \"hostname: $hostname`noListen: $noListen\"\n\n$remoteScript = @\"\n\ncd \"C:\\Program Files\\Octopus Deploy\\Tentacle\"\n\n.\\Tentacle.exe create-instance --instance \"Tentacle\" --config \"C:\\Octopus\\Tentacle.config\" --console\n.\\Tentacle.exe new-certificate --instance \"Tentacle\" --if-blank --console\n.\\Tentacle.exe configure --instance \"Tentacle\" --reset-trust --console\n.\\Tentacle.exe configure --instance \"Tentacle\" --home \"C:\\Octopus\" --app \"C:\\Octopus\\Applications\" $noListen --console\n.\\Tentacle.exe configure --instance \"Tentacle\" --trust \"$octoThumb\" --console\nif('$openFirewall' -eq 'true'){\n\tNew-NetFirewallRule -DisplayName \"Octopus Tentacle\" -Direction Inbound -LocalPort $portNumber -Protocol TCP -Action Allow\n}\n.\\Tentacle.exe register-with --instance \"Tentacle\" --server \"$serverUri\" --apiKey=$apiKey $roles $environments --comms-style $comStyle --force --console\n.\\Tentacle.exe service --instance \"Tentacle\" --install --start --console\n\n\"@\n\nWrite-Host \"Configuring tentacle on remote machine\"\n\nSet-Content -Value $remoteScript -Path \".\\script.ps1\"\n\n$result = az vm run-command invoke --command-id RunPowerShellScript --name $vmName -g $resourceGroup --scripts \"@script.ps1\"\n\n$result\n\n$msg = (($result | convertfrom-json).value | where {$_.code -eq \"componentstatus/stderr/succeeded\"}).message\n\nif(![string]::IsNullOrEmpty($msg))\n{\n\tthrow $msg\n}\n"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/azure-install-windows-tentacle.json","Website":"/step-templates/07b23f27-e76a-4b4b-acb1-017006a83269","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"}},{"Id":"633e7b90-7025-45d4-b16f-f92d6cf25c9e","Name":"Backup Azure Database To Azure Storage","Description":"Create a backup of SQL Azure Database and store it in Azure Blob Storage. Requires Azure PowerShell to be installed on Tentacle machine.","Version":7,"ExportedAt":"2015-03-25T08:48:19.055+00:00","ActionType":"Octopus.Script","Author":"trailmax","Parameters":[{"Name":"DatabaseServerName","Label":"Database Server Name","HelpText":"Azure SQL Server name, i.e. \"d340fe8ok\". Not a full name, just the machine name","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"DatabaseName","Label":"Database Name","HelpText":"Name of the database to be backed-up","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"DatabasePassword","Label":"Database Password","HelpText":"SQL Server Password to access the database","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Name":"DatabaseUsername","Label":"Database Username","HelpText":"SQL Server Username to access the database","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"StorageName","Label":"Storage Name","HelpText":"Name of the storage account where the backup should go","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Name":"StorageKey","Label":"Storage Key","HelpText":"Access key to the storage account","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Name":"StorageContainerName","Label":"Storage Container Name","HelpText":"Name of the container where the backup should go","DefaultValue":null,"DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptBody":"# Check if Windows Azure Powershell is avaiable \ntry{ \n Import-Module Azure -ErrorAction Stop\n}catch{\n throw \"Windows Azure Powershell not found! Please make sure to install them from http://www.windowsazure.com/en-us/downloads/#cmd-line-tools\" \n}\n\n\n$dateTime = get-date -Format u\n$blobName = \"Deployment-Backup/$DatabaseName/$dateTime.bacpac\"\nWrite-Host \"Using blobName: $blobName\"\n\n# Create Database Connection\n$securedPassword = ConvertTo-SecureString -String $DatabasePassword -asPlainText -Force\n$serverCredential = new-object System.Management.Automation.PSCredential($DatabaseUsername, $securedPassword) \n$databaseContext = New-AzureSqlDatabaseServerContext -ServerName $DatabaseServerName -Credential $serverCredential\n\n# Create Storage Connection\n$storageContext = New-AzureStorageContext -StorageAccountName $StorageName -StorageAccountKey $StorageKey\n\n# Initiate the Export\n$operationStatus = Start-AzureSqlDatabaseExport -StorageContext $storageContext -SqlConnectionContext $databaseContext -BlobName $blobName -DatabaseName $DatabaseName -StorageContainerName $StorageContainerName\n\n# Wait for the operation to finish\ndo{\n $status = Get-AzureSqlDatabaseImportExportStatus -Request $operationStatus \n Start-Sleep -s 3\n $progress =$status.Status.ToString()\n Write-Host \"Waiting for database export completion. Operation status: $progress\" \n}until ($status.Status -eq \"Completed\")\nWrite-Host \"Database export is complete\"","Octopus.Action.Script.Syntax":"PowerShell"},"Category":"Azure","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/backup-azure-database-to-azure-storage.json","Website":"/step-templates/633e7b90-7025-45d4-b16f-f92d6cf25c9e","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"}},{"Id":"78a182b3-5369-4e13-9292-b7f991295ad1","Name":"Block Release Progression","Description":"Step template to block the release progression of an Octopus Deploy release so it cannot be promoted beyond the current environment.","Version":1,"ExportedAt":"2021-09-13T16:14:01.845Z","ActionType":"Octopus.Script","Author":"bobjwalker","Packages":[],"Parameters":[{"Id":"fc366d69-e56b-476b-8005-5431f1ce8c05","Name":"Block.Octopus.Url","Label":"Octopus Url","HelpText":"The base url (`https://samples.octopus.app`) of your Octopus Server. Defaults to `Octopus.Web.BaseUrl`.","DefaultValue":"#{Octopus.Web.BaseUrl}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"f03e6e96-f1d5-4b91-9ae6-f67fd8ba043c","Name":"Block.Octopus.Api.Key","Label":"Octopus API Key","HelpText":"The API key of a user who has permission to block releases.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"cdcbd826-e075-476c-b67a-ddf0e75a576c","Name":"Block.Octopus.Previous.Release.Id","Label":"Release Id to Block","HelpText":"The Octopus ID (`Releases-123`) of the release to block. Defaults to `Octopus.Release.CurrentForEnvironment.Id`","DefaultValue":"#{Octopus.Release.CurrentForEnvironment.Id}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"5c9c1d6a-ec08-4d79-b442-180f9d0460c6","Name":"Block.Octopus.Reason","Label":"Reason","HelpText":"The reason why this release is being blocked.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.RunOnServer":"true","Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"$apiKey = $OctopusParameters[\"Block.Octopus.Api.Key\"]\n$previousReleaseId = $OctopusParameters[\"Block.Octopus.Previous.Release.Id\"]\n$reason = $OctopusParameters[\"Block.Octopus.Reason\"]\n$octopusBaseUrl = $OctopusParameters[\"Block.Octopus.Url\"]\n$spaceId = $OctopusParameters[\"Octopus.Space.Id\"]\n\n$body = @{\n\tDescription = $reason\n}\n$bodyAsJson = $body | ConvertTo-JSON -Depth 10\n\n$headers = @{\"X-Octopus-ApiKey\"=\"$apiKey\"}\n \nWrite-Host \"Blocking the release $previousReleaseId from progressing\"\nInvoke-RestMethod -Uri \"$($octopusBaseUrl)/api/$($spaceId)/releases/$($previousReleaseId)/defects\" -Method POST -Headers $headers -Body $bodyAsJSON -ContentType 'application/json; charset=utf-8'"},"Category":"Octopus","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/block-progression.json","Website":"/step-templates/78a182b3-5369-4e13-9292-b7f991295ad1","Logo":"iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1QTFRFT6Tl////L5Pg8vj9Y67omsvwPJrisdfzfbzs5fL7y+T32Ov5isLucLXqvt31CJPHWwAABMJJREFUeNrs3deW4jAMAFDF3U75/89dlp0ZhiU4blJEjvQ8hYubLJsA00UCBCIQgQhEIAIRiEAEIhCBCEQgAhGIQAQiEIEIhD8kJm+t+QprfdKfB9HbYpx6CWfspj8HMi+gMgHL/AmQA8W3JTKH+ALFvzCeL0RbpyoCPE9IJeNOSQwh5Z3qd6yRGWQ2qi2cZQWxqj1WzQYSjeoJmJlAklOd4VlArOqPhQEkqBERToeMcfRJBkC0Uep8CfBpjz4JsHJ0zF3dkEWNje0kiB/sUC6eApndaIiCMyAa1PiwJ0AWhRGJHJJQHG2dC7h1rNbO1QOxSA7lNCkkKrQIpJCAB1GREILYIC1NAiwbpKFJgGWDNExcwGstfExcZBCHC6nOglshHtmhViLIig1RNBCN7qjtW8C0Z1UvJcC1Z9XmwMBzzvobmgAyEzgq91dtEEsBsQSQQAFZCSBAATEEEApHZbrVBIkkEIUPSVeB+KtALA0kXQUSrwKZBCIQBnk8Y4i5CsReBeKvkqLM+BCSDWJlrZFvGk9SRTHshkgjZCGAaArIxm3H3grhVzFlW2msfl1ca79UJ1bofYvsDHHlNdTZnlh5MghuPd5NdBDUNZHyCkfktIh03XzALGRPlBDPac7qgWjHZzWcmF5zmmkhidMQ6boKiDXcDTUEaylZqCGJ0Vjvu/fLJtHqhSANEvqb2OYqkOUqEHuVMbJcZdZCGiPhKhC4yjqiIjEE7XThMp8fAWII3mY3kUIQD+AMKQTzPiBhgQ63HlT/KSvgtoi0dq5mCPah1UIE0eh3sT0NhOByvKeAkFzi8PgQomumFhsyOxpIzZN4gLOj5plVwNpR0b2AuePWKBEHQu24pSsJA+LVCeHHQxZ1SiyDIdqok8IOhSSnTottHEQTdyt4ettAj4KkzA4dMikk2Dht2S5ptm1vswnPDxn0YyDZ5oDM3iToo2T5voWaYe+Q+vdjH80QyAzZhCgcDtLMI1Tmtz9w++XHgziHQHJJu/OZ3bs9Xn8gQ72NcP3dKqEfkp10F51xhoIi2I91R+LurXV/5q7pH+wx061CzO16oSQleMyr8fXvwMA0Pro8432DPD/ySx8XrHfSuDAM8n6UhnjQabaiXf5Bq/lREHvEeNtn1rJ08+C/uXkQZHeguxAPC3UvtcJYUogLzZX5hhZZvS6onG5lxXtzWGaygwb79vT/IXhdlNibwlKYOR6T8xjI7W8n+xV7T+GH4tMzWwR+lZhRkJYSsC0thpmCYqyngOz3rN2FLBZ2wZflBCggUHF0Vnp88JKienzIXLSEZCZqU7IKr/gQW9yx3pzV7Y9kvWZWTRRIqDmTtRUnU7b2lLcTYmoqHqnmiO1poER0SPkAeZMAZxaJx0Y3TCdAclsIqDz03ALcyxfTCZBsthoGXWmigGyVhWPLFJJfuuKQWycoEFdXbH4dJJoJxNR1eD/kshz6yn48cF8yW8sFoitflB1w6Q8n+/15Za7oA17/pYNmYgP5fmWm8L1NOHPWgK8kuFew1/JXtOA0yJCv7ah7X8ObUuT5kObU30+fDZm8+zqP+HTIpK0xQ796b5Kv2hSIQAQiEIEIRCACEYhABCIQgQhEIAIRiEAEIpBf8UeAAQAEjtYmlDTcCgAAAABJRU5ErkJggg==","$Meta":{"Type":"ActionTemplate"}},{"Id":"d166457a-1421-4731-b143-dd6766fb95d5","Name":"Calculate Deployment Mode","Description":"This step uses Octopus [System Variables](https://octopus.com/docs/projects/variables/system-variables) to calculate the deployment mode. \n\n# Deployment Mode\nThe potential modes are:\n- **Deploy**: A newer version is being deployed to the target environment. For example, `2021.1.4` is being deployed to **Production** to replace `2021.0.5`.\n- **Rollback**: An older version is being deployed to the target environment. For example, `2021.0.5` is being deployed to **Production** to replace `2021.1.4`.\n- **Redeploy**: The same version is being deployed to the target environment. For example, `2021.1.4` is being deployed to **Production** which already has `2021.1.4`.\n\n**Please note**: This step template uses the release numbers to calculate the deployment mode. It doesn't look at any packages.\n\n# Version Difference\nAfter calculating the deployment mode, the step template will calculate the version difference. The potential options are:\n- **Identical**: No differences between the previous release and the current release were found.\n- **Major**: The first number (2021 in 2021.1.2.10) is different between the previous release and the current release.\n- **Minor**: The second number (1 in 2021.1.2.10) is different between the previous release and the current release.\n- **Build**: The third number (2 in 2021.1.2.10) is different between the previous release and the current release.\n- **Revision**: The fourth number (10 in 2021.1.2.10) is different between the previous release and the current release.\n\n# Manual or Automatic Trigger\nThe step template will also determine if the deployment was caused by a trigger or is a manual deployment. Potential values are `True` (caused by a trigger) or `False` (manual deployment).\n\n# Output Variables\n\nThe following output variables will be set:\n- **DeploymentMode**: Will either be `Deploy`, `Rollback` or `Redeploy`.\n- **Trigger**: Will either be `True` or `False`. Indicates if this deployment was caused by a trigger (scheduled or deployment target).\n- **VersionChange**: Will either be `Identical`, `Major`, `Minor`, `Build`, or `Revision`.\n\n## Variable Run Condition Output Variables\nTo make it easier to use, the step template will set a number of run condition output variables. \n\n### Variable Run Condition Usage\nVariable Run Conditions will _always_ be evaluated. Even if there is an error. If the run condition comes back as **Truthy** it will run the step. \n\nTo limit when the step runs, wrap the output variable with an if/then or unless clause:\n- **Always Run**: `#{Octopus.Action[Calculate Deployment Mode].Output.RunOnDeploy}` \n- **Success**: Only run when previous steps succeeds `#{unless Octopus.Deployment.Error}#{Octopus.Action[Calculate Deployment Mode].Output.RunOnDeploy}#{/unless}`\n- **Failure**: Only run when previous steps fail `#{if Octopus.Deployment.Error}#{Octopus.Action[Calculate Deployment Mode].Output.RunOnDeploy}#{/if}`\n\n**Hint:** Replace **RunOnDeploy** from the above examples with one of the variables from below.\n\n### Deployment Mode Run Conditions\n- **RunOnDeploy**: Only run the step when the **DeploymentMode** is `Deploy`.\n- **RunOnRollback**: Only run the step when the **DeploymentMode** is `Rollback`.\n- **RunOnRedeploy**: Only run the step when the **DeploymentMode** is `Redeploy`.\n- **RunOnDeployOrRollback**: Only run the step when the **DeploymentMode** is`Deploy` or `Rollback`.\n- **RunOnDeployOrRedeploy**: Only run the step when the **DeploymentMode** is`Deploy` or `Redeploy`.\n- **RunOnRedeployOrRollback**: Only run the step when the **DeploymentMode** is `Redeploy` or `Rollback`.\n\n### Version Change Run Conditions\n- **RunOnMajorVersionChange**: Only run the step when the **VersionChange** is `Major`.\n- **RunOnMinorVersionChange**: Only run the step when the **VersionChange** is `Minor`.\n- **RunOnMajorOrMinorVersionChange**: Only run the step when the **VersionChange** is `Major` or `Minor`.\n- **RunOnBuildVersionChange**: Only run the step when the **VersionChange** is `Build`.\n- **RunOnRevisionVersionChange**: Only run the step when the **VersionChange** is `Revision`.\n\n# Usage \n\n**Important:** This step template is designed for deployment processes only. Runbooks have no concept of deployments, redeployments, or rollbacks.\n\nThis step was designed to run on a worker (or the Octopus Server). It can run on targets, but the output variables will all be the same; running on targets will do nothing but waste compute cycles.","Version":5,"ExportedAt":"2021-11-02T13:48:09.120Z","ActionType":"Octopus.Script","Author":"BobJWalker","Packages":[],"Parameters":[],"Properties":{"Octopus.Action.RunOnServer":"true","Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"$currentReleaseNumber = $OctopusParameters[\"Octopus.Release.Number\"]\n$previousReleaseNumber = $OctopusParameters[\"Octopus.Release.CurrentForEnvironment.Number\"]\n$lastAttemptedReleaseNumber = $OctopusParameters[\"Octopus.Release.PreviousForEnvironment.Number\"]\n$stepName = $OctopusParameters[\"Octopus.Action.StepName\"]\n$triggerName = $OctopusParameters[\"Octopus.Deployment.Trigger.Name\"]\n\nWrite-Host \"The current release number is $currentReleaseNumber\"\nWrite-Host \"The last succesful release to this environment was $previousReleaseNumber\"\nWrite-Host \"The last release that was attempted on this environment was $lastAttemptedReleaseNumber\"\nWrite-Host \"The deployment name is $deploymentName\"\n\nif ($previousReleaseNumber -like \"*-*\")\n{\n\t$previousReleaseNumber = $previousReleaseNumber.SubString(0, $previousReleaseNumber.IndexOf(\"-\"))\n}\n\nif ($currentReleaseNumber -like \"*-*\")\n{\n\t$currentReleaseNumber = $currentReleaseNumber.SubString(0, $currentReleaseNumber.IndexOf(\"-\"))\n}\n\nif ($lastAttemptedReleaseNumber -like \"*-*\")\n{\n\t$lastAttemptedReleaseNumber = $lastAttemptedReleaseNumber.SubString(0, $lastAttemptedReleaseNumber.IndexOf(\"-\"))\n}\n\nWrite-Host \"The non-pre release tag previous version for the environment was $previousReleaseNumber\"\nWrite-Host \"The non-pre release tag current release number is $currentReleaseNumber\"\nWrite-Host \"The non-pre release tag of the last attempted version for the environment was $lastAttemptedReleaseNumber\"\n\n$currentVersion = [System.Version]$currentReleaseNumber\n$previousVersion = [System.Version]$previousReleaseNumber\n$lastAttemptedVersion = [System.Version]$lastAttemptedReleaseNumber\n\n$differentVersions = $false\n$versionToCompare = $previousVersion\nif ($currentVersion -gt $previousVersion)\n{\n\tWrite-Host \"The current release number $currentReleaseNumber is greater than the previous successful release number $previousReleaseNumber.\"\n\tif ($currentVersion -lt $lastAttemptedVersion)\n {\n \tWrite-Host \"The current release number $currentReleaseNumber is less than the last attempted release number $lastAttemptedReleaseNumber. Setting deployment mode to rollback.\"\n\t $deploymentMode = \"Rollback\"\n $versionToCompare = $lastAttemptedVersion\n }\n else\n {\n \tWrite-Host \"The current release number $curentReleaseNumber is greater than the last attempted release number $lastAttemptedReleaseNumber. Setting deployment mode to deploy.\"\n $deploymentMode = \"Deploy\"\n }\n}\nelseif ($currentVersion -lt $previousVersion)\n{\n\tWrite-Host \"The current release number $currentReleaseNumber is less than the previous successful release number $previousReleaseNumber. Setting deployment mode to rollback.\"\n $deploymentMode = \"Rollback\"\n $differentVersions = $true\n}\nelseif ($currentVersion -lt $lastAttemptedVersion)\n{\n\tWrite-Host \"The current release number $currentReleaseNumber is less than the last attempted release number $lastAttemptedReleaseNumber. Setting the deployment mode to rollback.\"\n $deploymentMode = \"Rollback\"\n $differentVersions = $true\n $versionToCompare = $lastAttemptedVersion\n}\nelse\n{\n\tWrite-Host \"The current release number $currentReleaseNumber matches the previous release number $previousReleaseNumber. Setting deployment mode to redeployment.\"\n $deploymentMode = \"Redeploy\"\n}\n\n$differenceKind = \"Identical\"\nif ($differentVersions)\n{\n\tif ($currentVersion.Major -ne $versionToCompare.Major)\n {\n \tWrite-Host \"$currentReleaseNumber is a major version change from $versionToCompare\"\n \t$differenceKind = \"Major\"\n }\n elseif ($currentVersion.Minor -ne $versionToCompare.Minor)\n {\n \tWrite-Host \"$currentReleaseNumber is a minor version change from $versionToCompare\"\n \t$differenceKind = \"Minor\"\n }\n elseif ($currentVersion.Build -ne $versionToCompare.Build)\n {\n \tWrite-Host \"$currentReleaseNumber is a build version change from $versionToCompare\"\n \t$differenceKind = \"Build\"\n }\n elseif ($currentVersion.Revision -ne $versionToCompare.Revision)\n {\n \tWrite-Host \"$currentReleaseNumber is a revision version change from $versionToCompare\"\n \t$differenceKind = \"Revision\"\n }\n}\n\n$trigger = $false\nif ([string]::IsNullOrWhiteSpace($triggerName) -eq $false)\n{\n\tWrite-Host \"This task was created by trigger $triggerName.\"\n $trigger = $true\n}\n\nSet-OctopusVariable -Name \"DeploymentMode\" -Value $deploymentMode\nSet-OctopusVariable -Name \"VersionChange\" -Value $differenceKind\nSet-OctopusVariable -Name \"Trigger\" -Value $trigger\n\nWrite-Highlight @\"\nOutput Variables Created:\n \t- Octopus.Action[$($stepName)].Output.DeploymentMode - Set to '$deploymentMode'\n - Octopus.Action[$($stepName)].Output.VersionChange - Set to '$differenceKind'\n - Octopus.Action[$($stepName)].Output.Trigger - Set to '$trigger'\n\nDeployment Mode Run Conditions Output Variables:\n \t- Octopus.Action[$($stepName)].Output.RunOnRollback\n - Octopus.Action[$($stepName)].Output.RunOnDeploy\n - Octopus.Action[$($stepName)].Output.RunOnRedeploy\n - Octopus.Action[$($stepName)].Output.RunOnDeployOrRollback\n - Octopus.Action[$($stepName)].Output.RunOnDeployOrRedeploy\n - Octopus.Action[$($stepName)].Output.RunOnRollbackOrRedeploy\n\nVersion Change Run Conditions Output Variables:\n \t- Octopus.Action[$($stepName)].Output.RunOnMajorVersionChange\n - Octopus.Action[$($stepName)].Output.RunOnMinorVersionChange\n - Octopus.Action[$($stepName)].Output.RunOnMajorOrMinorVersionChange\n - Octopus.Action[$($stepName)].Output.RunOnBuildVersionChange\n - Octopus.Action[$($stepName)].Output.RunOnRevisionVersionChange\n \nVariable run conditions are always evaluated, even if there is an error. Use the following examples to control when your step runs. Replace RunOnDeploy from below examples with one of the variables from above. \n- Always Run: `#{Octopus.Action[$stepName].Output.RunOnDeploy}` \n- Success: Only run when previous steps succeeds `##{unless Octopus.Deployment.Error}#{Octopus.Action[$stepName].Output.RunOnDeploy}##{/unless}`\n- Failure: Only run when previous steps fail `##{if Octopus.Deployment.Error}#{Octopus.Action[$stepName].Output.RunOnDeploy}##{/if}`\n\n\"@\n\n$runOnRollback = \"#{if Octopus.Action[$($stepName)].Output.DeploymentMode == \"\"Rollback\"\"}True#{else}False#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnRollback' so you can use it as a run condition\"\nWrite-Verbose $runOnRollback\nSet-OctopusVariable -Name \"RunOnRollback\" -Value $runOnRollback\n\n$runOnDeploy = \"#{if Octopus.Action[$($stepName)].Output.DeploymentMode == \"\"Deploy\"\"}True#{else}False#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnDeploy' so you can use it as a run condition\"\nWrite-Verbose $runOnDeploy\nSet-OctopusVariable -Name \"RunOnDeploy\" -Value $runOnDeploy\n\n$runOnRedeploy = \"#{if Octopus.Action[$($stepName)].Output.DeploymentMode == \"\"Redeploy\"\"}True#{else}False#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnRedeploy' so you can use it as a run condition\"\nWrite-Verbose $runOnRedeploy\nSet-OctopusVariable -Name \"RunOnRedeploy\" -Value $runOnRedeploy\n\n$runOnDeployOrRollback = \"#{if Octopus.Action[$($stepName)].Output.DeploymentMode != \"\"Redeploy\"\"}True#{else}False#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnDeployOrRollback' so you can use it as a run condition\"\nWrite-Verbose $runOnDeployOrRollback\nSet-OctopusVariable -Name \"RunOnDeployOrRollback\" -Value $runOnDeployOrRollback\n\n$runOnDeployOrRedeploy = \"#{if Octopus.Action[$($stepName)].Output.DeploymentMode != \"\"Rollback\"\"}True#{else}False#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnDeployOrRedeploy' so you can use it as a run condition\"\nWrite-Verbose $runOnDeployOrRedeploy\nSet-OctopusVariable -Name \"RunOnDeployOrRedeploy\" -Value $runOnDeployOrRedeploy\n\n$runOnRedeployOrRollback = \"#{if Octopus.Action[$($stepName)].Output.DeploymentMode != \"\"Deploy\"\"}True#{else}False#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnRedeployOrRollback' so you can use it as a run condition\"\nWrite-Verbose $runOnRedeployOrRollback\nSet-OctopusVariable -Name \"RunOnRedeployOrRollback\" -Value $runOnRedeployOrRollback\n\n$runOnMajorVersionChange = \"#{if Octopus.Action[$($stepName)].Output.VersionChange == \"\"Major\"\"}True#{else}False#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnMajorVersionChange' so you can use it as a run condition\"\nWrite-Verbose $runOnMajorVersionChange\nSet-OctopusVariable -Name \"RunOnMajorVersionChange\" -Value $runOnMajorVersionChange\n\n$runOnMinorVersionChange = \"#{if Octopus.Action[$($stepName)].Output.VersionChange == \"\"Minor\"\"}True#{else}False#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnMinorVersionChange' so you can use it as a run condition\"\nWrite-Verbose $runOnMinorVersionChange\nSet-OctopusVariable -Name \"RunOnMinorVersionChange\" -Value $runOnMinorVersionChange\n\n$runOnMajorOrMinorVersionChange = \"#{if Octopus.Action[$stepName].Output.VersionChange == \"\"Major\"\"}True#{else}#{if Octopus.Action[$stepName].Output.VersionChange == \"\"Minor\"\"}True#{else}False#{/if}#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnMajorOrMinorVersionChange' so you can use it as a run condition\"\nWrite-Verbose $runOnMajorOrMinorVersionChange\nSet-OctopusVariable -Name \"RunOnMajorOrMinorVersionChange\" -Value $runOnMajorOrMinorVersionChange\n\n$runOnBuildVersionChange = \"#{if Octopus.Action[$($stepName)].Output.VersionChange == \"\"Build\"\"}True#{else}False#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnBuildVersionChange' so you can use it as a run condition\"\nWrite-Verbose $runOnBuildVersionChange\nSet-OctopusVariable -Name \"RunOnBuildVersionChange\" -Value $runOnBuildVersionChange\n\n$runOnRevisionVersionChange = \"#{if Octopus.Action[$($stepName)].Output.VersionChange == \"\"Revision\"\"}True#{else}False#{/if}\"\nWrite-Host \"Setting the output variable 'Octopus.Action[$($stepName)].Output.RunOnRevisionVersionChange' so you can use it as a run condition\"\nWrite-Verbose $runOnRevisionVersionChange\nSet-OctopusVariable -Name \"RunOnRevisionVersionChange\" -Value $runOnRevisionVersionChange"},"Category":"Octopus","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/calculate-deployment-mode.json","Website":"/step-templates/d166457a-1421-4731-b143-dd6766fb95d5","Logo":"iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1QTFRFT6Tl////L5Pg8vj9Y67omsvwPJrisdfzfbzs5fL7y+T32Ov5isLucLXqvt31CJPHWwAABMJJREFUeNrs3deW4jAMAFDF3U75/89dlp0ZhiU4blJEjvQ8hYubLJsA00UCBCIQgQhEIAIRiEAEIhCBCEQgAhGIQAQiEIEIhD8kJm+t+QprfdKfB9HbYpx6CWfspj8HMi+gMgHL/AmQA8W3JTKH+ALFvzCeL0RbpyoCPE9IJeNOSQwh5Z3qd6yRGWQ2qi2cZQWxqj1WzQYSjeoJmJlAklOd4VlArOqPhQEkqBERToeMcfRJBkC0Uep8CfBpjz4JsHJ0zF3dkEWNje0kiB/sUC6eApndaIiCMyAa1PiwJ0AWhRGJHJJQHG2dC7h1rNbO1QOxSA7lNCkkKrQIpJCAB1GREILYIC1NAiwbpKFJgGWDNExcwGstfExcZBCHC6nOglshHtmhViLIig1RNBCN7qjtW8C0Z1UvJcC1Z9XmwMBzzvobmgAyEzgq91dtEEsBsQSQQAFZCSBAATEEEApHZbrVBIkkEIUPSVeB+KtALA0kXQUSrwKZBCIQBnk8Y4i5CsReBeKvkqLM+BCSDWJlrZFvGk9SRTHshkgjZCGAaArIxm3H3grhVzFlW2msfl1ca79UJ1bofYvsDHHlNdTZnlh5MghuPd5NdBDUNZHyCkfktIh03XzALGRPlBDPac7qgWjHZzWcmF5zmmkhidMQ6boKiDXcDTUEaylZqCGJ0Vjvu/fLJtHqhSANEvqb2OYqkOUqEHuVMbJcZdZCGiPhKhC4yjqiIjEE7XThMp8fAWII3mY3kUIQD+AMKQTzPiBhgQ63HlT/KSvgtoi0dq5mCPah1UIE0eh3sT0NhOByvKeAkFzi8PgQomumFhsyOxpIzZN4gLOj5plVwNpR0b2AuePWKBEHQu24pSsJA+LVCeHHQxZ1SiyDIdqok8IOhSSnTottHEQTdyt4ettAj4KkzA4dMikk2Dht2S5ptm1vswnPDxn0YyDZ5oDM3iToo2T5voWaYe+Q+vdjH80QyAzZhCgcDtLMI1Tmtz9w++XHgziHQHJJu/OZ3bs9Xn8gQ72NcP3dKqEfkp10F51xhoIi2I91R+LurXV/5q7pH+wx061CzO16oSQleMyr8fXvwMA0Pro8432DPD/ySx8XrHfSuDAM8n6UhnjQabaiXf5Bq/lREHvEeNtn1rJ08+C/uXkQZHeguxAPC3UvtcJYUogLzZX5hhZZvS6onG5lxXtzWGaygwb79vT/IXhdlNibwlKYOR6T8xjI7W8n+xV7T+GH4tMzWwR+lZhRkJYSsC0thpmCYqyngOz3rN2FLBZ2wZflBCggUHF0Vnp88JKienzIXLSEZCZqU7IKr/gQW9yx3pzV7Y9kvWZWTRRIqDmTtRUnU7b2lLcTYmoqHqnmiO1poER0SPkAeZMAZxaJx0Y3TCdAclsIqDz03ALcyxfTCZBsthoGXWmigGyVhWPLFJJfuuKQWycoEFdXbH4dJJoJxNR1eD/kshz6yn48cF8yW8sFoitflB1w6Q8n+/15Za7oA17/pYNmYgP5fmWm8L1NOHPWgK8kuFew1/JXtOA0yJCv7ah7X8ObUuT5kObU30+fDZm8+zqP+HTIpK0xQ796b5Kv2hSIQAQiEIEIRCACEYhABCIQgQhEIAIRiEAEIpBf8UeAAQAEjtYmlDTcCgAAAABJRU5ErkJggg==","$Meta":{"Type":"ActionTemplate"}},{"Id":"8ab26143-22d7-4e2f-83a8-f0e2d74a4de2","Name":"Cassandra - Create database if not exists","Description":"This template creates a keyspace on a Cassandra server if it doesn't already exist. **Note** this template is written in Python and requires that `pip` is installed to function correctly.,","Version":2,"ExportedAt":"2021-10-19T18:44:17.629Z","ActionType":"Octopus.Script","Author":"twerthi","Packages":[],"Parameters":[{"Id":"93076332-862f-44c5-b003-f8d6c9138d2b","Name":"Cassandra.Server.Name","Label":"Server Name","HelpText":"Hostname or IP address of the Cassandra database server.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"8abf47c6-eec5-428d-be90-4b4443295867","Name":"Cassandra.Server.Port","Label":"Port","HelpText":"Port number that the Cassandra server is listening on.","DefaultValue":"9042","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"5630dc27-80d2-421c-bb99-a61b2e6bd439","Name":"Cassandra.User.Name","Label":"(Optional) Username","HelpText":"Username of the account that can create databases. Leave blank if not using Username/Password authentication.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"1e7e73db-ca36-4bd6-9c5a-3f49506c7adf","Name":"Cassandra.User.Password","Label":"(Optional) Password","HelpText":"Password for the user account that can create databases. Leave blank if not using Username/Password authentication.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"484d22fc-4a84-4459-ac4e-166731432709","Name":"Cassandra.Server.Mode","Label":"Server mode","HelpText":"The mode in which the Cassandra server is operating.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"NetworkTopologyStrategy|Network Topology Strategy\nSimpleStrategy|Simple Strategy"}},{"Id":"b2c433be-66bb-4ee0-9246-59e62818b7bb","Name":"Cassandra.Keyspace.Name","Label":"Keyspace","HelpText":"Name of the Keyspace to create.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"73a696ca-26e3-4069-852a-3be63d5bd090","Name":"Cassandra.Replicas.Number","Label":"Number of replicas","HelpText":"The number of replicas to create.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}}],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"Python","Octopus.Action.Script.ScriptBody":"# Import subprocess \nimport subprocess\n\n# Define function to install specified package\ndef install(package):\n subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", package])\n\n# Check to see if cassandra-module is installed\nprint('Checking for Cassandra module ...')\nif 'cassandra-driver' not in sys.modules:\n # Install the cassandra-driver module\n print('Installing cassandra-driver module ...')\n install('cassandra-driver')\nelse:\n print('cassandra-driver module is present ...')\n\n# Import cassandra modules\nfrom cassandra.cluster import Cluster\nfrom cassandra.auth import PlainTextAuthProvider\n\n# Set username/password authentication provider\nauth_provider = PlainTextAuthProvider(\n username='#{Cassandra.User.Name}', password='#{Cassandra.User.Password}')\n\n# Connect to server\nprint('Connecting to server ...')\ncluster = None\n\nif '#{Cassandra.User.Name}' != '' and '#{Cassandra.User.Password}' != '':\n\tcluster = Cluster(['#{Cassandra.Server.Name}'], auth_provider=auth_provider, port=#{Cassandra.Server.Port})\nelse:\n\tcluster = Cluster(['#{Cassandra.Server.Name}'], port=#{Cassandra.Server.Port})\n \n# Conect to cluster\nsession = cluster.connect()\nrows = session.execute(\"SELECT keyspace_name FROM system_schema.keyspaces;\")\nkeyspace = next((x for x in rows if x.keyspace_name == '#{Cassandra.Keyspace.Name}'), None)\n\nif keyspace == None:\n # Create json document\n strategyjson = None\n if '#{Cassandra.Server.Mode}' == \"SimpleStrategy\":\n strategyjson = { 'class' : '#{Cassandra.Server.Mode}', 'replication_factor': '#{Cassandra.Replicas.Number}' }\n\n if '#{Cassandra.Server.Mode}' == \"NetworkTopologyStrategy\":\n strategyjson = { 'class' : '#{Cassandra.Server.Mode}', '#{Cassandra.Server.Name}' : '#{Cassandra.Replicas.Number}'}\n\n # Create keyspace\n print('Creating keyspace #{Cassandra.Keyspace.Name} ...')\n session.execute(\"CREATE KEYSPACE IF NOT EXISTS #{Cassandra.Keyspace.Name} WITH REPLICATION = {0};\".format(strategyjson))\n\n # Verify keyspace was created\n rows = session.execute(\"SELECT keyspace_name FROM system_schema.keyspaces;\")\n\n keyspace = next((x for x in rows if x.keyspace_name == '#{Cassandra.Keyspace.Name}'), None)\n\n if keyspace != None:\n print('#{Cassandra.Keyspace.Name} created successfully!')\n else:\n print('#{Cassandra.Keyspace.Name} was not created!')\n exit(1)\nelse:\n print('Keyspace #{Cassandra.Keyspace.Name} already exists.')"},"Category":"Cassandra","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/cassandra-create-keyspace.json","Website":"/step-templates/8ab26143-22d7-4e2f-83a8-f0e2d74a4de2","Logo":"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","$Meta":{"Type":"ActionTemplate"}},{"Id":"18392835-d50e-4ce9-9065-8e15a3c30954","Name":"Chain Deployment","Description":"Triggers a deployment of another project in Octopus","Version":24,"ExportedAt":"2021-09-13T13:29:57.957Z","ActionType":"Octopus.Script","Author":"harrisonmeister","Packages":[],"Parameters":[{"Id":"61bffab9-bb89-4107-a5e0-79d69eaf8f2a","Name":"Chain_ApiKey","Label":"API Key","HelpText":"An Octopus API Key with appropriate permissions to perform the deployment","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"},"Links":{}},{"Id":"a37cac4d-8fd3-4d58-bfda-45a436be8dd5","Name":"Chain_ProjectName","Label":"Project Name","HelpText":"Name of the Octopus project that should be deployed","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"4fd440af-70fe-41ca-bec3-074f05155e81","Name":"Chain_Channel","Label":"Channel Name","HelpText":"The project channel to use when finding or [creating](https://octopus.com/docs/key-concepts/projects/channels#Channels-CreatingReleases) the release to deploy\n\n_Leave blank to use the default channel_","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"78739052-438d-4dc7-862a-d4567eafc5df","Name":"Chain_ReleaseNum","Label":"Release Number","HelpText":"Release number to use for the deployment\n\n_Leave blank to use the latest release in the channel_","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"fd2c3474-7187-4356-aaec-96f4910bb9c5","Name":"Chain_CreateOption","Label":"Create new release?","HelpText":"If a release should be created as part of this deployment\n\n\nThe release is created using either the **Release Number** if specified, or from the project release version template / donor package step if not specified\n\nA release will not be created if it is found to already exist","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Checkbox"},"Links":{}},{"Id":"f648fa0c-b271-4e4a-b4f2-7a88db6b605c","Name":"Chain_SnapshotVariables","Label":"Update Variable Snapshot?","HelpText":"Should variables in the release be updated before deploying?\n\nBy updating the variables, the current snapshot will be discarded, and the latest variables (as seen on the Variables tab) will be imported","DefaultValue":"False","DisplaySettings":{"Octopus.ControlType":"Checkbox"},"Links":{}},{"Id":"80634b3b-3171-4643-b164-a5077c6d387b","Name":"Chain_DeployTo","Label":"Environment Name","HelpText":"The name of an environment to deploy to\n\nMultiple environments can be deployed to by entering the name of a [lifecycle phase](https://octopus.com/docs/key-concepts/lifecycles#Lifecycles-LifecyclePhases)","DefaultValue":"#{Octopus.Environment.Name}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"1334093d-0be4-4115-bb93-d752171a19d8","Name":"Chain_Tenants","Label":"Tenants","HelpText":"_Leave blank to perform an untenanted deployment_\n\nA list of [tenants & tenant tags](https://octopus.com/docs/key-concepts/tenants) to deploy. Tenant Tags are specified in [Canonical Name](https://octopus.com/docs/key-concepts/tenants/tenant-tags#TenantTags-Referencingtenanttags) format:\n\n Tag Set Name/Tag Name\n\nIndividual tenants can be listed in addition to tags\n\n Tenant Name","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"},"Links":{}},{"Id":"83d9d973-7a72-4f71-a890-8f19d955bc37","Name":"Chain_FormValues","Label":"Form Values","HelpText":"Provide values for [prompted variables](https://octopus.com/docs/deploying-applications/variables/prompted-variables) to use in the deployment\n\nVariables should be listed one per line using the format\n\n VariableName = Value","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"},"Links":{}},{"Id":"6522ca29-898a-4da6-b0c3-da52991e6812","Name":"Chain_StepsToSkip","Label":"Steps To Skip","HelpText":"A list of steps which should be skipped in the deployment\n\nSteps should be listed one per line, and specified using either the step number (as per the deployment plan) or by the step name","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"},"Links":{}},{"Id":"acb2cd0e-fc53-42a7-95da-089955ea1870","Name":"Chain_GuidedFailure","Label":"Failure Handling","HelpText":"Determines how deployment failures & [guided failure mode](https://octopus.com/docs/deploying-applications/guided-failures) should be handled for the deployment\n\nAutomatic failure handling is performed by using [guided failure](https://octopus.com/docs/deploying-applications/guided-failures) and submitting an appropriate action\n\nThe number of retry attempts can be customised by [setting the following variables in indexer notion](https://octopus.com/docs/deploying-applications/variables/system-variables#Systemvariables-Action)\n- Octopus.Action.StepRetryCount\n- Octopus.Action.DeploymentRetryCount","DefaultValue":"Default","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"Default|Default - Guided Failure is inherited from this deployment\nEnabled|Enable - Guided Failure is enabled\nDisabled|Disable - Guided Failure is disabled\nRetryIgnore|Retry & Ignore - Automatically retry a failing step, a second failure is ignored\nRetryAbort|Retry & Abort - Automatically retry a failing step, and abort on a second failure\nIgnore|Ignore - Automatically ignore any step failures\nRetryDeployment|Retry Deployment - Automatically retry the entire deployment on failure"},"Links":{}},{"Id":"73a80735-4ca0-4c12-9fa3-f0123db6349f","Name":"Chain_DeploySchedule","Label":"Scheduling","HelpText":"Defines how the deployment should be scheduled & run\n\n_Note: Automated failure handling & post-deploy script functionality is only available when the **Wait For Deployment** option is selected_\n\nA user defined schedule can be set with the **Use a custom expression** option\nFor an exact date & time use the following format, the day is optional and the time is in 24-hour format\n\n [Mon/Tue/Wed/Thu/Fri/Sat/Sun] @ HH:MM\n\nTo schedule a deployment a relative number of hours & minutes in the future use\n\n + MMM\n + HHH:MM\n\n_Note: Reoccurring deployments & automatic retry of failed deployment are possible using a scheduled deployment and the [Always Run or On Failure run conditions](https://octopus.com/docs/deploying-applications#Deployingapplications-Conditions)_","DefaultValue":"WaitForDeployment","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"WaitForDeployment|Wait For Deployment\nNoWait|Queue Immediately\n+ 5|Deploy in 5 minutes\n+ 15|Deploy in 15 minutes\n+ 1:00|Deploy in 1 hour\n+ 24:00|Deploy in 24 hours\n@ 00:00|Deploy At Midnight\n@ 00:00 + 12:00|Deploy At Noon Tomorrow\nMon @ 08:00|Deploy At 8am On Monday\nSat @ 00:00 + 168:00|Deploy the following Saturday at Midnight"},"Links":{}},{"Id":"7e7f9ac5-8674-4a91-a94a-896a3ee1334d","Name":"Chain_PostDeploy","Label":"Post-Deploy Script","HelpText":"A PowerShell script which should be run after a successful deployment\n\nVariables are replaced in the script using the resultant **Manifest VariableSet** from the deployment in the [binding syntax](https://octopus.com/docs/deploying-applications/variables/binding-syntax) format\n\nVariables are not available if they are:\n- [Sensitive](https://octopus.com/docs/deploying-applications/variables/sensitive-variables)\n- Action scoped\n- Machine scoped\n- Role scoped\n\n\nWhen performing a tenanted deployment the script will be run once for each tenant using the specific variables from their deployment","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"MultiLineText"},"Links":{}}],"Properties":{"Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.RunOnServer":"true","Octopus.Action.Script.ScriptBody":"<#\n----- Chain Deployment -----\nAuthors & Credits\n Paul Marston @paulmarsy (paul@marston.me)\n Joe Waid @joewaid\n Henrik Andersson @alfhenrik\n Damian Brady @Damovisa\n Aaron Burke @aburke-incomm (aburke@incomm.com)\nLinks\n https://library.octopus.com/step-templates/18392835-d50e-4ce9-9065-8e15a3c30954\n https://github.com/OctopusDeploy/Library/commits/master/step-templates/octopus-chain-deployment.json\n\n----- Advanced Configuration Settings -----\nVariable names can use either of the following two formats: \n Octopus.Action. - will apply to all steps in the deployment, e.g.\n Octopus.Action.DebugLogging\n Octopus.Action[Step Name]. - will apply to 'step name' alone, e.g.\n Octopus.Action[Provision Virtual Machine].DeploymentRetryCount\n\nAvailable Settings:\n - DebugLogging - set to 'True' or 'False' to log all GET web requests\n - GuidedFailureMessage - will change the note used when submitting guided failure actions, the following variables will be replaced in the text:\n #{GuidedFailureActionIndex} - The current count of interrupts for that step e.g. 1\n #{GuidedFailureAction} - The action being submitted by the step e.g. Retry\n - DeploymentRetryCount - will override the number of times a deployment will be retried when unsuccessful and enable retrying when the failure option is set for a different option, default is 1\n - StepRetryCount - will override the number of times a deployment step will be retried before before submitting Ignore or Abort, default is 1\n - RetryWaitPeriod - an additional delay in seconds wait before retrying a failed step/deployment, default is 0\n - QueueTimeout - when scheduling a deployment for later a timeout must be provided, this allows a custom value, default is 30:00, format is hh:mm\n - OctopusServerUrl - will override the base url used for all webrequests, making it possible to chain deployments on a different Octopus instance/server, or as a workaround for misconfigured node settings\n\n----- Changelog -----\n24. Sept 13, 2021 - Mark Harrison @harrisonmeister\n - Fixed issue where the Invoke-OctopusApi function would error with 404: NotFound when running Chain deployment on an Octopus instance \n that runs under either a \"virtual directory\" / route prefix other than the route e.g https://my.octopus.app/octo/\n23. Aug 23rd, 2021 - Ben Macpherson benjimac93\n - Use Octopus.Web.ServerUri in place of Octopus.Web.BaseUrl if present.\n22. Dec 31, 2020 - Josh Slaughter @joshgk00\n\t- Fixed an issue where the script was unable to create a release if Chained project contained a step with multiple package references\n20. Sept 3, 2020 - Mark Harrison @harrisonmeister\n\t- Included setting to TLS 1.2. \n19. July 17, 2020 - Aaron Burke @aburke-incomm\n\t- Update script handle Regex for Channel Tags in the CreateRelease Function\n17. December 18, 2018 - Jim Burger @burgomg\n\t- Added Spaces compatibility\n16. November 22, 2018 - Patrick Kearney @patrickkearney\n - Fixed an issue where the step was unable to pass a form variable containing an \"=\" in the value.\n15. July 17, 2017 - Robert Glickman @robertglickman\n - Fixed an issue where the step would fail in Octopus 3.15+ due to templated URIs not being handled\n14. May 5, 2017 - Paul Marston @paulmarsy (paul@marston.me)\n - Improved step parameter metadata & validation\n - Added changelog, documentation of advanced settings\n - Supports deploying to multiple environments in one step by specifying a lifecycle phase name e.g. 'Dev'\n - Automated retry of the entire deployment as an additional failure handling option\n - Number of step/deployment retries is configurable using a settings variable\n - Supports Octopus scheduled deployments (can be used for reoccuring scheduled deploys, or autonomous deployment retry)\n - Individual tenants as well as tenant tags can be deployed to\n - Fixing a bug where Guided Failure is always evaluated to true\n - Improved identification of valid environment&tenant promotions by using the 'deployment template' api\n - If a release version has already been created, it will be used rather than erroring trying to recreate it\n - Using 'Fail-Step' for better error logging\n - Fixed a bug where log messages with an identical timestamp were repeatedly reported\n - Added an option to wait before retrying a step/deployment\n - A release's channel is taken into account when checking if an existing release version can be used\n13. Apr 21, 2017 - Paul Marston @paulmarsy (paul@marston.me)\n - Complete step template rewrite\n - Improved logging\n * Logs only written when chained deployment changes\n * Progress of deployment step states is reported\n * Errors & warnings are reported without interpretation in parent deployment\n * Manual intervention & guided failure events are reported\n * Queue position reported before deployment starts\n * Verbose logging of useful API urls\n - Multi-tenancy support and handling multiple tenant deploys from one chain step\n - Support for skipping steps\n - Support for prompted form variables\n - Create release functionality supports using the version from the incremented version template or donor package\n - Ability to snapshot update variables of a release before deploying\n - Automated handling of guided failure scenarios e.g. retry on step failure, then abort if it errors a second time\n - Transient Octopus API request failures are handled (e.g. we saw many deployments failing because of a request timeout)\n - Post-deploy script support with variable substitution performed using the manifest variable set of the chained deployment with appropriate scoping applied (though not advanced scope specificity)\n - Defaulting channel to a blank value which looks for one with 'IsDefault' set true\n - Create release performs a simplified package version lookup to populate the 'SelectedPackages' field\n12. Mar 30, 2017 - Joe Waid @joewaid\n - Pass the Environments \"Guided Failure\" setting\n - Check status after deployment when Chain_WaitForDeployment is true\n11. Nov 21, 2016 - Henrik Andersson @alfhenrik\n - Add Wait for deployment option to chain deployment step template\n10. May 2, 2016 - Damian Brady @Damovisa\n - Add Chained Deployment step template\n#>\n#Requires -Version 5\n$ErrorActionPreference = 'Stop'\n$ProgressPreference = 'SilentlyContinue'\n\n[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12\n\nfunction Test-String {\n param([Parameter(Position = 0)]$InputObject, [switch]$ForAbsence)\n\n $hasNoValue = [System.String]::IsNullOrWhiteSpace($InputObject)\n if ($ForAbsence) { $hasNoValue }\n else { -not $hasNoValue }\n}\n\nfunction Get-OctopusSetting {\n param([Parameter(Position = 0, Mandatory)][string]$Name, [Parameter(Position = 1, Mandatory)]$DefaultValue)\n $formattedName = 'Octopus.Action.{0}' -f $Name\n if ($OctopusParameters.ContainsKey($formattedName)) {\n $value = $OctopusParameters[$formattedName]\n if ($DefaultValue -is [int]) { return ([int]::Parse($value)) }\n if ($DefaultValue -is [bool]) { return ([System.Convert]::ToBoolean($value)) }\n if ($DefaultValue -is [array] -or $DefaultValue -is [hashtable] -or $DefaultValue -is [pscustomobject]) { return (ConvertFrom-Json -InputObject $value) }\n return $value\n }\n else { return $DefaultValue }\n}\n\n# Write functions are re-defined using octopus service messages to preserve formatting of log messages received from the chained deployment and avoid errors being twice wrapped in an ErrorRecord\nfunction Write-Fatal($message, $exitCode = -1) {\n if (Test-Path Function:\\Fail-Step) {\n Fail-Step $message\n }\n else {\n Write-Host (\"##octopus[stdout-error]`n{0}\" -f $message)\n Exit $exitCode\n }\n}\nfunction Write-Error($message) { Write-Host (\"##octopus[stdout-error]`n{0}`n##octopus[stdout-default]\" -f $message) }\nfunction Write-Warning($message) { Write-Host (\"##octopus[stdout-warning]`n{0}`n##octopus[stdout-default]\" -f $message) }\nfunction Write-Verbose($message) { Write-Host (\"##octopus[stdout-verbose]`n{0}`n##octopus[stdout-default]\" -f $message) }\n\n$DefaultUrl = $OctopusParameters['#{if Octopus.Web.ServerUri}#{Octopus.Web.ServerUri}#{else}#{Octopus.Web.BaseUrl}#{/if}']\n# Use \"Octopus.Web.ServerUri\" if it is available\nif ($OctopusParameters['Octopus.Web.ServerUri']) {\n $DefaultUrl = $OctopusParameters['Octopus.Web.ServerUri']\n}\n\n$Chain_BaseUrl = (Get-OctopusSetting OctopusServerUrl $DefaultUrl).Trim('/')\nif (Test-String $Chain_ApiKey -ForAbsence) {\n Write-Fatal \"The step parameter 'API Key' was not found. This step requires an API Key to function, please provide one and try again.\"\n}\n$DebugLogging = Get-OctopusSetting DebugLogging $false\n\n# Replace any \"virtual directory\" or route prefix e.g from the Links collection used\n# with the api e.g. /api\nfunction Format-LinksUri {\n param(\n [Parameter(Position = 0, Mandatory)]\n $Uri\n )\n $Uri = $Uri -replace '.*/api', '/api'\n Return $Uri\n}\n# Replace any \"virtual directory\" or route prefix e.g from the Links collection used\n# with the web app e.g. /app\nfunction Format-WebLinksUri {\n param(\n [Parameter(Position = 0, Mandatory)]\n $Uri\n )\n $Uri = $Uri -replace '.*/app', '/app'\n Return $Uri\n}\n\nfunction Invoke-OctopusApi {\n param(\n [Parameter(Position = 0, Mandatory)]$Uri,\n [ValidateSet('Get', 'Post', 'Put')]$Method = 'Get',\n $Body,\n [switch]$GetErrorResponse\n )\n # Replace query string example parameters e.g. {?skip,take,partialName} \n # Replace any \"virtual directory\" or route prefix e.g from the Links collection.\n $Uri = $Uri -replace '{.*?}', '' -replace '.*/api', '/api'\n $requestParameters = @{\n Uri = ('{0}/{1}' -f $Chain_BaseUrl, $Uri.TrimStart('/'))\n Method = $Method\n Headers = @{ 'X-Octopus-ApiKey' = $Chain_ApiKey }\n UseBasicParsing = $true\n }\n if ($Method -ne 'Get' -or $DebugLogging) {\n Write-Verbose ('{0} {1}' -f $Method.ToUpperInvariant(), $requestParameters.Uri)\n }\n if ($null -ne $Body) {\n $requestParameters.Add('Body', (ConvertTo-Json -InputObject $Body -Depth 10))\n Write-Verbose $requestParameters.Body\n }\n \n $wait = 0\n $webRequest = $null\n while ($null -eq $webRequest) {\t\n try {\n $webRequest = Invoke-WebRequest @requestParameters\n }\n catch {\n if ($_.Exception -is [System.Net.WebException] -and $null -ne $_.Exception.Response) {\n $errorResponse = [System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream()).ReadToEnd()\n Write-Verbose (\"Error Response:`n{0}\" -f $errorResponse)\n if ($GetErrorResponse) {\n return ($errorResponse | ConvertFrom-Json)\n }\n if ($_.Exception.Response.StatusCode -in @([System.Net.HttpStatusCode]::NotFound, [System.Net.HttpStatusCode]::InternalServerError, [System.Net.HttpStatusCode]::BadRequest, [System.Net.HttpStatusCode]::Unauthorized)) {\n Write-Fatal $_.Exception.Message\n }\n }\n if ($wait -eq 120) {\n Write-Fatal (\"Octopus web request ({0}: {1}) failed & the maximum number of retries has been exceeded:`n{2}\" -f $Method.ToUpperInvariant(), $requestParameters.Uri, $_.Exception.Message) -43\n }\n $wait = switch ($wait) {\n 0 { 30 }\n 30 { 60 }\n 60 { 120 }\n }\n Write-Warning (\"Octopus web request ({0}: {1}) failed & will be retried in $wait seconds:`n{2}\" -f $Method.ToUpperInvariant(), $requestParameters.Uri, $_.Exception.Message)\n Start-Sleep -Seconds $wait\n }\n }\n $webRequest.Content | ConvertFrom-Json | Write-Output\n}\n\nfunction Test-SpacesApi {\n Write-Verbose \"Checking API compatibility\";\n $rootDocument = Invoke-OctopusApi \"api/\";\n if ($null -ne $rootDocument.Links -and $null -ne $rootDocument.Links.Spaces) {\n Write-Verbose \"Spaces API found\"\n return $true;\n }\n Write-Verbose \"Pre-spaces API found\"\n return $false;\n}\n\n$Chain_BaseApiUrl = \"/api\"\nif (Test-SpacesApi) {\n $spaceId = $OctopusParameters['Octopus.Space.Id'];\n if ([string]::IsNullOrWhiteSpace($spaceId)) {\n throw \"This step needs to be run in a context that provides a value for the 'Octopus.Space.Id' system variable. In this case, we received a blank value, which isn't expected - please reach out to our support team at https://help.octopus.com if you encounter this error.\";\n }\n $Chain_BaseApiUrl = \"/api/$spaceId\" ;\n}\n\nenum GuidedFailure {\n Default\n Enabled\n Disabled\n RetryIgnore\n RetryAbort\n Ignore\n RetryDeployment\n}\n\nclass DeploymentContext {\n hidden $BaseUrl\n hidden $BaseApiUrl\n DeploymentContext($baseUrl, $baseApiUrl) {\n $this.BaseUrl = $baseUrl\n $this.BaseApiUrl = $baseApiUrl\n }\n\n hidden $Project\n hidden $Lifecycle\n [void] SetProject($projectName) {\n $this.Project = Invoke-OctopusApi \"$($this.BaseApiUrl)/projects/all\" | Where-Object Name -eq $projectName\n if ($null -eq $this.Project) {\n Write-Fatal \"Project $projectName not found\"\n }\n Write-Host \"Project: $($this.Project.Name)\"\n Write-Verbose \"`t$($this.BaseUrl)$(Format-LinksUri -Uri $this.Project.Links.Self)\"\n \n $this.Lifecycle = Invoke-OctopusApi (\"$($this.BaseApiUrl)/lifecycles/{0}\" -f $this.Project.LifecycleId)\n Write-Host \"Project Lifecycle: $($this.Lifecycle.Name)\"\n Write-Verbose \"`t$($this.BaseUrl)$(Format-LinksUri -Uri $this.Lifecycle.Links.Self)\"\n }\n \n hidden $Channel\n [void] SetChannel($channelName) {\n $useDefaultChannel = Test-String $channelName -ForAbsence\n $this.Channel = Invoke-OctopusApi (Format-LinksUri -Uri $this.Project.Links.Channels) | ForEach-Object Items | Where-Object { $useDefaultChannel -and $_.IsDefault -or $_.Name -eq $channelName }\n if ($null -eq $this.Channel) {\n Write-Fatal \"$(if ($useDefaultChannel) { 'Default channel' } else { \"Channel $channelName\" }) not found\"\n }\n Write-Host \"Channel: $($this.Channel.Name)\"\n Write-Verbose \"`t$($this.BaseUrl)$(Format-LinksUri -Uri $this.Channel.Links.Self)\"\n\n if ($null -ne $this.Channel.LifecycleId) {\n $this.Lifecycle = Invoke-OctopusApi (\"$($this.BaseApiUrl)/lifecycles/{0}\" -f $this.Channel.LifecycleId)\n Write-Host \"Channel Lifecycle: $($this.Lifecycle.Name)\"\n Write-Verbose \"`t$($this.BaseUrl)$(Format-LinksUri -Uri $this.Lifecycle.Links.Self)\" \n }\n }\n\n hidden $Release\n [void] SetRelease($releaseVersion) {\n if (Test-String $releaseVersion) {\n $this.Release = Invoke-OctopusApi (\"$($this.BaseApiUrl)/projects/{0}/releases/{1}\" -f $this.Project.Id, $releaseVersion) -GetErrorResponse\n if ($null -ne $this.Release.ErrorMessage) {\n Write-Fatal $this.Release.ErrorMessage\n }\n }\n else {\n $this.Release = Invoke-OctopusApi (Format-LinksUri -Uri $this.Channel.Links.Releases) | ForEach-Object Items | Select-Object -First 1\n if ($null -eq $this.Release) {\n Write-Fatal \"There are no releases for channel $($this.Channel.Name)\"\n }\n }\n Write-Host \"Release: $($this.Release.Version)\"\n Write-Verbose \"`t$($this.BaseUrl)$($this.BaseApiUrl)/releases/$($this.Release.Id)\"\n }\n [void] CreateRelease($releaseVersion) {\n $template = Invoke-OctopusApi ('{0}/template?channel={1}' -f (Format-LinksUri -Uri $this.Project.Links.DeploymentProcess), $this.Channel.Id)\n $selectedPackages = @()\n Write-Host 'Resolving package versions...'\n $template.Packages | ForEach-Object {\n $preReleaseTag = $this.Channel.Rules | Where-Object Actions -contains $_.StepName | Where-Object { $null -ne $_ } | ForEach-Object { '&preReleaseTag={0}' -f $([System.Net.WebUtility]::UrlEncode($_.Tag)) }\n $versionRange = $this.Channel.Rules | Where-Object Actions -contains $_.StepName | Where-Object { $null -ne $_ } | ForEach-Object { '&versionRange={0}' -f $([System.Net.WebUtility]::UrlEncode($_.VersionRange)) }\n\n $package = Invoke-OctopusApi (\"$($this.BaseApiUrl)/feeds/{0}/packages?packageId={1}&partialMatch=false&includeMultipleVersions=false&includeNotes=false&includePreRelease=true&take=1{2}{3}\" -f $_.FeedId, $_.PackageId, $preReleaseTag, $versionRange)\n $packageDesc = \"$($package.Title) @ $($package.Version) for step $($_.StepName)\"\n if ( $_.PackageReferenceName ) {\n $packageDesc += \"/$($_.PackageReferenceName)\"\n }\n Write-Host \"Found $packageDesc\"\n \n $selectedPackages += @{\n StepName = $_.StepName\n ActionName = $_.ActionName\n PackageReferenceName = $_.PackageReferenceName\n Version = $package.Version\n }\n\n if ( (Test-String $releaseVersion -ForAbsence) -and ($_.StepName -eq $template.VersioningPackageStepName) ) {\n Write-Host \"Release will be created using the version number from package step $($template.VersioningPackageStepName): $($package.Version)\"\n $releaseVersion = $package.Version\n }\n }\n if (Test-String $releaseVersion) {\n $this.Release = Invoke-OctopusApi (\"$($this.BaseApiUrl)/projects/{0}/releases/{1}\" -f $this.Project.Id, $releaseVersion) -GetErrorResponse\n if ( ($null -eq $this.Release.ErrorMessage) -and ($this.Release.Version -ieq $releaseVersion) -and ($this.Release.ChannelId -eq $this.Channel.Id) ) {\n Write-Host \"Release version $($this.Release.Version) has already been created, selecting it for deployment\"\n Write-Verbose \"`t$($this.BaseUrl)$($this.BaseApiUrl)/releases/$($this.Release.Id)\"\n return\n }\n }\n else {\n Write-Host \"Release will be created using the incremented release version: $($template.NextVersionIncrement)\"\n $releaseVersion = $template.NextVersionIncrement\n }\n\n $this.Release = Invoke-OctopusApi \"$($this.BaseApiUrl)/releases?ignoreChannelRules=false\" -Method Post -Body @{\n ProjectId = $this.Project.Id\n ChannelId = $this.Channel.Id \n Version = $releaseVersion\n SelectedPackages = $selectedPackages\n } -GetErrorResponse\n if ($null -ne $this.Release.ErrorMessage) {\n Write-Fatal \"$($this.Release.ErrorMessage)`n$($this.Release.Errors -join \"`n\")\"\n }\n Write-Host \"Release $($this.Release.Version) has been successfully created\"\n Write-Verbose \"`t$($this.BaseUrl)$($this.BaseApiUrl)/releases/$($this.Release.Id)\"\n }\n\n [void] UpdateVariableSnapshot() {\n $this.Release = Invoke-OctopusApi (Format-LinksUri -Uri $this.Release.Links.SnapshotVariables) -Method Post\n Write-Host 'Variables snapshot update performed. The release now references the latest variables.'\n }\n\n hidden $DeploymentTemplate\n [void] GetDeploymentTemplate() {\n Write-Host 'Getting deployment template for release...'\n $this.DeploymentTemplate = Invoke-OctopusApi (Format-LinksUri -Uri $this.Release.Links.DeploymentTemplate)\n }\n\n hidden [bool]$UseGuidedFailure\n hidden [string[]]$GuidedFailureActions\n hidden [string]$GuidedFailureMessage\n hidden [int]$DeploymentRetryCount\n [void] SetGuidedFailure([GuidedFailure]$guidedFailure, $guidedFailureMessage) {\n $this.UseGuidedFailure = switch ($guidedFailure) {\n ([GuidedFailure]::Default) { [System.Convert]::ToBoolean($global:OctopusUseGuidedFailure) }\n ([GuidedFailure]::Enabled) { $true }\n ([GuidedFailure]::Disabled) { $false }\n ([GuidedFailure]::RetryIgnore) { $true }\n ([GuidedFailure]::RetryAbort) { $true }\n ([GuidedFailure]::Ignore) { $true } \n ([GuidedFailure]::RetryDeployment) { $false }\n }\n Write-Host \"Setting Guided Failure: $($this.UseGuidedFailure)\"\n \n $retryActions = @(1..(Get-OctopusSetting StepRetryCount 1) | ForEach-Object { 'Retry' })\n $this.GuidedFailureActions = switch ($guidedFailure) {\n ([GuidedFailure]::Default) { $null }\n ([GuidedFailure]::Enabled) { $null }\n ([GuidedFailure]::Disabled) { $null }\n ([GuidedFailure]::RetryIgnore) { $retryActions + @('Ignore') }\n ([GuidedFailure]::RetryAbort) { $retryActions + @('Abort') }\n ([GuidedFailure]::Ignore) { @('Ignore') }\n ([GuidedFailure]::RetryDeployment) { $null }\n }\n if ($null -ne $this.GuidedFailureActions) {\n Write-Host \"Automated Failure Guidance: $($this.GuidedFailureActions -join '; ') \"\n }\n $this.GuidedFailureMessage = $guidedFailureMessage\n \n $defaultRetries = if ($guidedFailure -eq [GuidedFailure]::RetryDeployment) { 1 } else { 0 }\n $this.DeploymentRetryCount = Get-OctopusSetting DeploymentRetryCount $defaultRetries\n if ($this.DeploymentRetryCount -ne 0) {\n Write-Host \"Failed Deployments will be retried #$($this.DeploymentRetryCount) times\"\n }\n }\n \n [bool]$WaitForDeployment\n hidden [datetime]$QueueTime\n hidden [datetime]$QueueTimeExpiry\n [void] SetSchedule($deploySchedule) {\n if (Test-String $deploySchedule -ForAbsence) {\n Write-Fatal 'The deployment schedule step parameter was not found.'\n }\n if ($deploySchedule -eq 'WaitForDeployment') {\n $this.WaitForDeployment = $true\n Write-Host 'Deployment will be queued to start immediatley...'\n return\n }\n $this.WaitForDeployment = $false\n if ($deploySchedule -eq 'NoWait') {\n Write-Host 'Deployment will be queued to start immediatley...'\n return\n }\n <#\n ^(?i) - Case-insensitive matching\n (?:\n (?MON|TUE|WED|THU|FRI|SAT|SUN)? - Capture an optional day\n \\s*@\\s* - '@' indicates deploying at a specific time\n (?(?:[01]?[0-9]|2[0-3]):[0-5][0-9]) - Captures the time of day, in 24 hour format\n )? - Day & TimeOfDay are optional\n \\s*\n (?:\n \\+\\s* - '+' indicates deploying after a length of tie\n (?\n \\d{1,3} - Match 1 to 3 digits\n (?::[0-5][0-9])? - Optionally match a colon and 00 to 59, this denotes if the previous 1-3 digits are hours or minutes\n )\n )?$ - TimeSpan is optional\n #>\n $parsedSchedule = [regex]::Match($deploySchedule, '^(?i)(?:(?MON|TUE|WED|THU|FRI|SAT|SUN)?\\s*@\\s*(?(?:[01]?[0-9]|2[0-3]):[0-5][0-9]))?\\s*(?:\\+\\s*(?\\d{1,3}(?::[0-5][0-9])?))?$')\n if (!$parsedSchedule.Success) {\n Write-Fatal \"The deployment schedule step parameter contains an invalid value. Valid values are 'WaitForDeployment', 'NoWait' or a schedule in the format '[[DayOfWeek] @ HH:mm] [+ ]'\" \n }\n $this.QueueTime = Get-Date\n if ($parsedSchedule.Groups['Day'].Success) {\n Write-Verbose \"Parsed Day: $($parsedSchedule.Groups['Day'].Value)\"\n while (!$this.QueueTime.DayOfWeek.ToString().StartsWith($parsedSchedule.Groups['Day'].Value)) {\n $this.QueueTime = $this.QueueTime.AddDays(1)\n }\n }\n if ($parsedSchedule.Groups['TimeOfDay'].Success) {\n Write-Verbose \"Parsed Time Of Day: $($parsedSchedule.Groups['TimeOfDay'].Value)\"\n $timeOfDay = [datetime]::ParseExact($parsedSchedule.Groups['TimeOfDay'].Value, 'HH:mm', $null)\n $this.QueueTime = $this.QueueTime.Date + $timeOfDay.TimeOfDay\n }\n if ($parsedSchedule.Groups['TimeSpan'].Success) {\n Write-Verbose \"Parsed Time Span: $($parsedSchedule.Groups['TimeSpan'].Value)\"\n $timeSpan = $parsedSchedule.Groups['TimeSpan'].Value.Split(':')\n $hoursToAdd = if ($timeSpan.Length -eq 2) { $timeSpan[0] } else { 0 }\n $minutesToAdd = if ($timeSpan.Length -eq 2) { $timeSpan[1] } else { $timeSpan[0] }\n $this.QueueTime = $this.QueueTime.Add((New-TimeSpan -Hours $hoursToAdd -Minutes $minutesToAdd))\n }\n Write-Host \"Deployment will be queued to start at: $($this.QueueTime.ToLongDateString()) $($this.QueueTime.ToLongTimeString())\"\n Write-Verbose \"Local Time: $($this.QueueTime.ToLocalTime().ToString('r'))\"\n Write-Verbose \"Universal Time: $($this.QueueTime.ToUniversalTime().ToString('o'))\"\n $this.QueueTimeExpiry = $this.QueueTime.Add([timespan]::ParseExact((Get-OctopusSetting QueueTimeout '00:30'), \"hh\\:mm\", $null))\n Write-Verbose \"Queued deployment will expire on: $($this.QueueTimeExpiry.ToUniversalTime().ToString('o'))\"\n }\n\n hidden $Environments\n [void] SetEnvironment($environmentName) {\n $lifecyclePhaseEnvironments = $this.Lifecycle.Phases | Where-Object Name -eq $environmentName | ForEach-Object {\n $_.AutomaticDeploymentTargets\n $_.OptionalDeploymentTargets\n }\n $this.Environments = $this.DeploymentTemplate.PromoteTo | Where-Object { $_.Id -in $lifecyclePhaseEnvironments -or $_.Name -ieq $environmentName }\n if ($null -eq $this.Environments) {\n Write-Fatal \"The specified environment ($environmentName) was not found or not eligible for deployment of the release ($($this.Release.Version)). Verify that the release has been deployed to all required environments before it can be promoted to this environment. Once you have corrected these problems you can try again.\" \n }\n Write-Host \"Environments: $(($this.Environments | ForEach-Object Name) -join ', ')\"\n }\n \n [bool] $IsTenanted\n hidden $Tenants\n [void] SetTenants($tenantFilter) {\n $this.IsTenanted = Test-String $tenantFilter\n if (!$this.IsTenanted) {\n return\n }\n $tenantPromotions = $this.DeploymentTemplate.TenantPromotions | ForEach-Object Id\n $this.Tenants = $tenantFilter.Split(\"`n\") | ForEach-Object { [uri]::EscapeUriString($_.Trim()) } | ForEach-Object {\n $criteria = if ($_ -like '*/*') { 'tags' } else { 'name' }\n \n $tenantResults = Invoke-OctopusApi (\"$($this.BaseApiUrl)/tenants/all?projectId={0}&{1}={2}\" -f $this.Project.Id, $criteria, $_) -GetErrorResponse\n if ($tenantResults -isnot [array] -and $tenantResults.ErrorMessage) {\n Write-Warning \"Full Exception: $($tenantResults.FullException)\"\n Write-Fatal $tenantResults.ErrorMessage\n }\n $tenantResults\n } | Where-Object Id -in $tenantPromotions\n\n if ($null -eq $this.Tenants) {\n Write-Fatal \"No eligible tenants found for deployment of the release ($($this.Release.Version)). Verify that the tenants have been associated with the project.\"\n }\n Write-Host \"Tenants: $(($this.Tenants | ForEach-Object Name) -join ', ')\"\n }\n\n [DeploymentController[]] GetDeploymentControllers() {\n Write-Verbose 'Determining eligible environments & tenants. Retrieving deployment previews...'\n $deploymentControllers = @()\n foreach ($environment in $this.Environments) {\n $envPrefix = if ($this.Environments.Count -gt 1) { $environment.Name }\n if ($this.IsTenanted) {\n foreach ($tenant in $this.Tenants) {\n $tenantPrefix = if ($this.Tenants.Count -gt 1) { $tenant.Name }\n if ($this.DeploymentTemplate.TenantPromotions | Where-Object Id -eq $tenant.Id | ForEach-Object PromoteTo | Where-Object Id -eq $environment.Id) {\n $logPrefix = ($envPrefix, $tenantPrefix | Where-Object { $null -ne $_ }) -join '::'\n $deploymentControllers += [DeploymentController]::new($this, $logPrefix, $environment, $tenant)\n }\n }\n }\n else {\n $deploymentControllers += [DeploymentController]::new($this, $envPrefix, $environment, $null)\n }\n }\n return $deploymentControllers\n }\n}\n\nclass DeploymentController {\n hidden [string]$BaseUrl\n hidden [DeploymentContext]$DeploymentContext\n hidden [string]$LogPrefix\n hidden [object]$Environment\n hidden [object]$Tenant\n hidden [object]$DeploymentPreview\n hidden [int]$DeploymentRetryCount\n hidden [int]$DeploymentAttempt\n \n DeploymentController($deploymentContext, $logPrefix, $environment, $tenant) {\n $this.BaseUrl = $deploymentContext.BaseUrl\n $this.DeploymentContext = $deploymentContext\n if (Test-String $logPrefix) {\n $this.LogPrefix = \"[${logPrefix}] \"\n }\n $this.Environment = $environment\n $this.Tenant = $tenant\n if ($tenant) {\n $this.DeploymentPreview = Invoke-OctopusApi (\"$($this.DeploymentContext.BaseApiUrl)/releases/{0}/deployments/preview/{1}/{2}\" -f $this.DeploymentContext.Release.Id, $this.Environment.Id, $this.Tenant.Id)\n }\n else {\n $this.DeploymentPreview = Invoke-OctopusApi (\"$($this.DeploymentContext.BaseApiUrl)/releases/{0}/deployments/preview/{1}\" -f $this.DeploymentContext.Release.Id, $this.Environment.Id)\n }\n $this.DeploymentRetryCount = $deploymentContext.DeploymentRetryCount\n $this.DeploymentAttempt = 0\n }\n\n hidden [string[]]$SkipActions = @()\n [void] SetStepsToSkip($stepsToSkip) {\n $comparisonArray = $stepsToSkip.Split(\"`n\") | ForEach-Object Trim\n $this.SkipActions = $this.DeploymentPreview.StepsToExecute | Where-Object {\n $_.CanBeSkipped -and ($_.ActionName -in $comparisonArray -or $_.ActionNumber -in $comparisonArray)\n } | ForEach-Object {\n $logMessage = \"Skipping Step $($_.ActionNumber): $($_.ActionName)\"\n if ($this.LogPrefix) { Write-Verbose \"$($this.LogPrefix)$logMessage\" }\n else { Write-Host $logMessage }\n $_.ActionId\n }\n }\n\n hidden [hashtable]$FormValues\n [void] SetFormValues($formValuesToSet) {\n $this.FormValues = @{}\n $this.DeploymentPreview.Form.Values | Get-Member -MemberType NoteProperty | ForEach-Object {\n $this.FormValues.Add($_.Name, $this.DeploymentPreview.Form.Values.$($_.Name))\n }\n\n $formValuesToSet.Split(\"`n\") | ForEach-Object {\n $entry = $_.Split('=') | ForEach-Object Trim\n $entryName, $entryValues = $entry\n $entry = @($entryName, $($entryValues -join \"=\"))\n $this.DeploymentPreview.Form.Elements | Where-Object { $_.Control.Name -ieq $entry[0] } | ForEach-Object {\n $logMessage = \"Setting Form Value '$($_.Control.Label)' to: $($entry[1])\"\n if ($this.LogPrefix) { Write-Verbose \"$($this.LogPrefix)$logMessage\" }\n else { Write-Host $logMessage }\n $this.FormValues[$_.Name] = $entry[1]\n }\n }\n }\n\t\n [ServerTask]$Task\n [void] Start() {\n $request = @{\n ReleaseId = $this.DeploymentContext.Release.Id\n EnvironmentId = $this.Environment.Id\n SkipActions = $this.SkipActions\n FormValues = $this.FormValues\n UseGuidedFailure = $this.DeploymentContext.UseGuidedFailure\n }\n if ($this.DeploymentContext.QueueTime -ne [datetime]::MinValue) { $request.Add('QueueTime', $this.DeploymentContext.QueueTime.ToUniversalTime().ToString('o')) }\n if ($this.DeploymentContext.QueueTimeExpiry -ne [datetime]::MinValue) { $request.Add('QueueTimeExpiry', $this.DeploymentContext.QueueTimeExpiry.ToUniversalTime().ToString('o')) }\n if ($this.Tenant) { $request.Add('TenantId', $this.Tenant.Id) }\n\n $deployment = Invoke-OctopusApi \"$($this.DeploymentContext.BaseApiUrl)/deployments\" -Method Post -Body $request -GetErrorResponse\n if ($deployment.ErrorMessage) { Write-Fatal \"$($deployment.ErrorMessage)`n$($deployment.Errors -join \"`n\")\" }\n Write-Host \"Queued $($deployment.Name)...\"\n Write-Host \"`t$($this.BaseUrl)$(Format-WebLinksUri -Uri $deployment.Links.Web)\"\n Write-Verbose \"`t$($this.BaseUrl)$(Format-LinksUri -Uri $deployment.Links.Self)\"\n Write-Verbose \"`t$($this.BaseUrl)$($this.DeploymentContext.BaseApiUrl)/deploymentprocesses/$($deployment.DeploymentProcessId)\"\n Write-Verbose \"`t$($this.BaseUrl)$(Format-LinksUri -Uri $deployment.Links.Variables)\"\n Write-Verbose \"`t$($this.BaseUrl)$(Format-LinksUri -Uri $deployment.Links.Task)/details\"\n\n $this.Task = [ServerTask]::new($this.DeploymentContext, $deployment, $this.LogPrefix)\n }\n\n [bool] PollCheck() {\n $this.Task.Poll()\n if ($this.Task.IsCompleted -and !$this.Task.FinishedSuccessfully -and $this.DeploymentAttempt -lt $this.DeploymentRetryCount) {\n $retryWaitPeriod = New-TimeSpan -Seconds (Get-OctopusSetting RetryWaitPeriod 0)\n $waitText = if ($retryWaitPeriod.TotalSeconds -gt 0) {\n $minutesText = if ($retryWaitPeriod.Minutes -gt 1) { \" $($retryWaitPeriod.Minutes) minutes\" } elseif ($retryWaitPeriod.Minutes -eq 1) { \" $($retryWaitPeriod.Minutes) minute\" }\n $secondsText = if ($retryWaitPeriod.Seconds -gt 1) { \" $($retryWaitPeriod.Seconds) seconds\" } elseif ($retryWaitPeriod.Seconds -eq 1) { \" $($retryWaitPeriod.Seconds) second\" }\n \"Waiting${minutesText}${secondsText} before \"\n }\n $this.DeploymentAttempt++\n Write-Error \"$($this.LogPrefix)Deployment failed. ${waitText}Queuing retry #$($this.DeploymentAttempt) of $($this.DeploymentRetryCount)...\"\n if ($retryWaitPeriod.TotalSeconds -gt 0) {\n Start-Sleep -Seconds $retryWaitPeriod.TotalSeconds\n }\n $this.Start()\n return $true\n }\n return !$this.Task.IsCompleted\n }\n}\n\nclass ServerTask {\n hidden [DeploymentContext]$DeploymentContext\n hidden [object]$Deployment\n hidden [string]$LogPrefix\n\n hidden [bool] $IsCompleted = $false\n hidden [bool] $FinishedSuccessfully\n hidden [string] $ErrorMessage\n \n hidden [int]$PollCount = 0\n hidden [bool]$HasInterruptions = $false\n hidden [hashtable]$State = @{}\n hidden [System.Collections.Generic.HashSet[string]]$Logs\n \n ServerTask($deploymentContext, $deployment, $logPrefix) {\n $this.DeploymentContext = $deploymentContext\n $this.Deployment = $deployment\n $this.LogPrefix = $logPrefix\n $this.Logs = [System.Collections.Generic.HashSet[string]]::new()\n }\n \n [void] Poll() {\t\n if ($this.IsCompleted) { return }\n\n $details = Invoke-OctopusApi (\"$($this.DeploymentContext.BaseApiUrl)/tasks/{0}/details?verbose=false&tail=30\" -f $this.Deployment.TaskId)\n $this.IsCompleted = $details.Task.IsCompleted\n $this.FinishedSuccessfully = $details.Task.FinishedSuccessfully\n $this.ErrorMessage = $details.Task.ErrorMessage\n\n $this.PollCount++\n if ($this.PollCount % 10 -eq 0) {\n $this.Verbose(\"$($details.Task.State). $($details.Task.Duration), $($details.Progress.EstimatedTimeRemaining)\")\n }\n \n if ($details.Task.HasPendingInterruptions) { $this.HasInterruptions = $true }\n $this.LogQueuePosition($details.Task)\n $activityLogs = $this.FlattenActivityLogs($details.ActivityLogs) \n $this.WriteLogMessages($activityLogs)\n }\n\n hidden [bool] IfNewState($firstKey, $secondKey, $value) {\n $key = '{0}/{1}' -f $firstKey, $secondKey\n $containsKey = $this.State.ContainsKey($key)\n if ($containsKey) { return $false }\n $this.State[$key] = $value\n return $true\n }\n\n hidden [bool] HasChangedState($firstKey, $secondKey, $value) {\n $key = '{0}/{1}' -f $firstKey, $secondKey\n $hasChanged = if (!$this.State.ContainsKey($key)) { $true } else { $this.State[$key] -ne $value }\n if ($hasChanged) {\n $this.State[$key] = $value\n }\n return $hasChanged\n }\n\n hidden [object] GetState($firstKey, $secondKey) { return $this.State[('{0}/{1}' -f $firstKey, $secondKey)] }\n\n hidden [void] ResetState($firstKey, $secondKey) { $this.State.Remove(('{0}/{1}' -f $firstKey, $secondKey)) }\n\n hidden [void] Error($message) { Write-Error \"$($this.LogPrefix)${message}\" }\n hidden [void] Warn($message) { Write-Warning \"$($this.LogPrefix)${message}\" }\n hidden [void] Host($message) { Write-Host \"$($this.LogPrefix)${message}\" } \n hidden [void] Verbose($message) { Write-Verbose \"$($this.LogPrefix)${message}\" }\n\n hidden [psobject[]] FlattenActivityLogs($ActivityLogs) {\n $flattenedActivityLogs = { @() }.Invoke()\n $this.FlattenActivityLogs($ActivityLogs, $null, $flattenedActivityLogs)\n return $flattenedActivityLogs\n }\n\n hidden [void] FlattenActivityLogs($ActivityLogs, $Parent, $flattenedActivityLogs) {\n foreach ($log in $ActivityLogs) {\n $log | Add-Member -MemberType NoteProperty -Name Parent -Value $Parent\n $insertBefore = $null -eq $log.Parent -and $log.Status -eq 'Running'\t\n if ($insertBefore) { $flattenedActivityLogs.Add($log) }\n foreach ($childLog in $log.Children) {\n $this.FlattenActivityLogs($childLog, $log, $flattenedActivityLogs)\n }\n if (!$insertBefore) { $flattenedActivityLogs.Add($log) }\n }\n }\n\n hidden [void] LogQueuePosition($Task) {\n if ($Task.HasBeenPickedUpByProcessor) {\n $this.ResetState($Task.Id, 'QueuePosition')\n return\n }\n\t\t\n $queuePosition = (Invoke-OctopusApi (\"$($this.DeploymentContext.BaseApiUrl)/tasks/{0}/queued-behind\" -f $this.Deployment.TaskId)).Items.Count\n if ($this.HasChangedState($Task.Id, 'QueuePosition', $queuePosition) -and $queuePosition -ne 0) {\n $this.Host(\"Queued behind $queuePosition tasks...\")\n }\n }\n\n hidden [void] WriteLogMessages($ActivityLogs) {\n $interrupts = if ($this.HasInterruptions) {\n Invoke-OctopusApi (\"$($this.DeploymentContext.BaseApiUrl)/interruptions?regarding={0}\" -f $this.Deployment.TaskId) | ForEach-Object Items\n }\n foreach ($activity in $ActivityLogs) {\n $correlatedInterrupts = $interrupts | Where-Object CorrelationId -eq $activity.Id \n $correlatedInterrupts | Where-Object IsPending -eq $false | ForEach-Object { $this.LogInterruptMessages($activity, $_) }\n\n $this.LogStepTransition($activity) \n $this.LogErrorsAndWarnings($activity)\n $correlatedInterrupts | Where-Object IsPending -eq $true | ForEach-Object { \n $this.LogInterruptMessages($activity, $_)\n $this.HandleInterrupt($_)\n }\n }\n }\n\n hidden [void] LogStepTransition($ActivityLog) {\n if ($ActivityLog.ShowAtSummaryLevel -and $ActivityLog.Status -ne 'Pending') {\n $existingState = $this.GetState($ActivityLog.Id, 'Status')\n if ($this.HasChangedState($ActivityLog.Id, 'Status', $ActivityLog.Status)) {\n $existingStateText = if ($existingState) { \"$existingState -> \" }\n $this.Host(\"$($ActivityLog.Name) ($existingStateText$($ActivityLog.Status))\")\n }\n }\n }\n\n hidden [void] LogErrorsAndWarnings($ActivityLog) {\n foreach ($logEntry in $ActivityLog.LogElements) {\n if ($logEntry.Category -eq 'Info') { continue }\n if ($this.Logs.Add(($ActivityLog.Id, $logEntry.OccurredAt, $logEntry.MessageText -join '/'))) {\n switch ($logEntry.Category) {\n 'Fatal' {\n if ($ActivityLog.Parent) {\n $this.Error(\"FATAL: During $($ActivityLog.Parent.Name)\")\n $this.Error(\"FATAL: $($logEntry.MessageText)\")\n }\n }\n 'Error' { $this.Error(\"[$($ActivityLog.Parent.Name)] $($logEntry.MessageText)\") }\n 'Warning' { $this.Warn(\"[$($ActivityLog.Parent.Name)] $($logEntry.MessageText)\") }\n }\n }\n }\n }\n\n hidden [void] LogInterruptMessages($ActivityLog, $Interrupt) {\n $message = $Interrupt.Form.Elements | Where-Object Name -eq Instructions | ForEach-Object Control | ForEach-Object Text\n if ($Interrupt.IsPending -and $this.HasChangedState($Interrupt.Id, $ActivityLog.Parent.Name, $message)) {\n $this.Warn(\"Deployment is paused at '$($ActivityLog.Parent.Name)' for manual intervention: $message\")\n }\n if ($null -ne $Interrupt.ResponsibleUserId -and $this.HasChangedState($Interrupt.Id, 'ResponsibleUserId', $Interrupt.ResponsibleUserId)) {\n $user = Invoke-OctopusApi (Format-LinksUri -Uri $Interrupt.Links.User)\n $emailText = if (Test-String $user.EmailAddress) { \" ($($user.EmailAddress))\" }\n $this.Warn(\"$($user.DisplayName)$emailText has taken responsibility for the manual intervention\")\n }\n $manualAction = $Interrupt.Form.Values.Result\n if ((Test-String $manualAction) -and $this.HasChangedState($Interrupt.Id, 'Action', $manualAction)) {\n $this.Warn(\"Manual intervention action '$manualAction' submitted with notes: $($Interrupt.Form.Values.Notes)\")\n }\n $guidanceAction = $Interrupt.Form.Values.Guidance\n if ((Test-String $guidanceAction) -and $this.HasChangedState($Interrupt.Id, 'Action', $guidanceAction)) {\n $this.Warn(\"Failure guidance to '$guidanceAction' submitted with notes: $($Interrupt.Form.Values.Notes)\")\n }\n }\n\n hidden [void] HandleInterrupt($Interrupt) {\n $isGuidedFailure = $null -ne ($Interrupt.Form.Elements | Where-Object Name -eq Guidance)\n if (!$isGuidedFailure -or !$this.DeploymentContext.GuidedFailureActions -or !$Interrupt.IsPending) {\n return\n }\n $this.IfNewState($Interrupt.CorrelationId, 'ActionIndex', 0)\n if ($Interrupt.CanTakeResponsibility -and $null -eq $Interrupt.ResponsibleUserId) {\n Invoke-OctopusApi (Format-LinksUri -Uri $Interrupt.Links.Responsible) -Method Put\n }\n if ($Interrupt.HasResponsibility) {\n $guidanceIndex = $this.GetState($Interrupt.CorrelationId, 'ActionIndex')\n $guidance = $this.DeploymentContext.GuidedFailureActions[$guidanceIndex]\n $guidanceIndex++\n \n $retryWaitPeriod = New-TimeSpan -Seconds (Get-OctopusSetting RetryWaitPeriod 0)\n if ($guidance -eq 'Retry' -and $retryWaitPeriod.TotalSeconds -gt 0) {\n $minutesText = if ($retryWaitPeriod.Minutes -gt 1) { \" $($retryWaitPeriod.Minutes) minutes\" } elseif ($retryWaitPeriod.Minutes -eq 1) { \" $($retryWaitPeriod.Minutes) minute\" }\n $secondsText = if ($retryWaitPeriod.Seconds -gt 1) { \" $($retryWaitPeriod.Seconds) seconds\" } elseif ($retryWaitPeriod.Seconds -eq 1) { \" $($retryWaitPeriod.Seconds) second\" }\n $this.Warn(\"Waiting${minutesText}${secondsText} before submitting retry failure guidance...\")\n Start-Sleep -Seconds $retryWaitPeriod.TotalSeconds\n }\n Invoke-OctopusApi (Format-LinksUri -Uri $Interrupt.Links.Submit) -Body @{\n Notes = $this.DeploymentContext.GuidedFailureMessage.Replace('#{GuidedFailureActionIndex}', $guidanceIndex).Replace('#{GuidedFailureAction}', $guidance)\n Guidance = $guidance\n } -Method Post\n\n $this.HasChangedState($Interrupt.CorrelationId, 'ActionIndex', $guidanceIndex)\n }\n }\n}\n\nfunction Show-Heading {\n param($Text)\n $padding = ' ' * ((80 - 2 - $Text.Length) / 2)\n Write-Host \" `n\"\n Write-Host (@(\"`t\", ([string][char]0x2554), (([string][char]0x2550) * 80), ([string][char]0x2557)) -join '')\n Write-Host \"`t$(([string][char]0x2551))$padding $Text $padding$([string][char]0x2551)\" \n Write-Host (@(\"`t\", ([string][char]0x255A), (([string][char]0x2550) * 80), ([string][char]0x255D)) -join '')\n Write-Host \" `n\"\n}\n\nif ($OctopusParameters['Octopus.Action.RunOnServer'] -ieq 'False') {\n Write-Warning \"For optimal performance use 'Run On Server' for this action\"\n}\n\n$deploymentContext = [DeploymentContext]::new($Chain_BaseUrl, $Chain_BaseApiUrl)\n\nif ($Chain_CreateOption -ieq 'True') {\n Show-Heading 'Creating Release'\n}\nelse {\n Show-Heading 'Retrieving Release'\n}\n$deploymentContext.SetProject($Chain_ProjectName)\n$deploymentContext.SetChannel($Chain_Channel)\nWrite-Host \"`t$Chain_BaseUrl$(Format-WebLinksUri -Uri $deploymentContext.Project.Links.Web)\"\n\nif ($Chain_CreateOption -ieq 'True') {\n $deploymentContext.CreateRelease($Chain_ReleaseNum)\n}\nelse {\n $deploymentContext.SetRelease($Chain_ReleaseNum)\n}\nWrite-Host \"`t$Chain_BaseUrl$(Format-WebLinksUri -Uri $deploymentContext.Release.Links.Web)\"\nif ($Chain_SnapshotVariables -ieq 'True') {\n $deploymentContext.UpdateVariableSnapshot()\n}\n\nShow-Heading 'Configuring Deployment'\n$deploymentContext.GetDeploymentTemplate()\n$email = if (Test-String $OctopusParameters['Octopus.Deployment.CreatedBy.EmailAddress']) { \"($($OctopusParameters['Octopus.Deployment.CreatedBy.EmailAddress']))\" }\n$guidedFailureMessage = Get-OctopusSetting GuidedFailureMessage @\"\nAutomatic Failure Guidance will #{GuidedFailureAction} (Failure ###{GuidedFailureActionIndex})\nInitiated by $($OctopusParameters['Octopus.Deployment.Name']) of $($OctopusParameters['Octopus.Project.Name']) release $($OctopusParameters['Octopus.Release.Number'])\nCreated By: $($OctopusParameters['Octopus.Deployment.CreatedBy.DisplayName']) $email\n${Chain_BaseUrl}$($OctopusParameters['Octopus.Web.DeploymentLink'])\n\"@\n$deploymentContext.SetGuidedFailure($Chain_GuidedFailure, $guidedFailureMessage)\n$deploymentContext.SetSchedule($Chain_DeploySchedule)\n\n$deploymentContext.SetEnvironment($Chain_DeployTo)\n$deploymentContext.SetTenants($Chain_Tenants)\n\n$deploymentControllers = $deploymentContext.GetDeploymentControllers()\nif (Test-String $Chain_StepsToSkip) {\n $deploymentControllers | ForEach-Object { $_.SetStepsToSkip($Chain_StepsToSkip) }\n}\nif (Test-String $Chain_FormValues) {\n $deploymentControllers | ForEach-Object { $_.SetFormValues($Chain_FormValues) }\n}\n\nShow-Heading 'Queue Deployment'\nif ($deploymentContext.IsTenanted) {\n Write-Host 'Queueing tenant deployments...'\n}\nelse {\n Write-Host 'Queueing untenanted deployment...'\n}\n$deploymentControllers | ForEach-Object Start\n\nif (!$deploymentContext.WaitForDeployment) {\n Write-Host 'Deployments have been queued, proceeding to the next step...'\n return\n}\n\nShow-Heading 'Waiting For Deployment'\ndo {\n Start-Sleep -Seconds 1\n $tasksStillRunning = $false\n foreach ($deployment in $deploymentControllers) {\n if ($deployment.PollCheck()) {\n $tasksStillRunning = $true\n }\n }\n} while ($tasksStillRunning)\n\nif ($deploymentControllers | ForEach-Object Task | Where-Object FinishedSuccessfully -eq $false) {\n Show-Heading 'Deployment Failed!'\n Write-Fatal (($deploymentControllers | ForEach-Object Task | ForEach-Object ErrorMessage) -join \"`n\")\n}\nelse {\n Show-Heading 'Deployment Successful!'\n}\n\nif (Test-String $Chain_PostDeploy -ForAbsence) {\n return \n}\n\nShow-Heading 'Post-Deploy Script'\n$rawPostDeployScript = Invoke-OctopusApi (\"$Chain_BaseApiUrl/releases/{0}\" -f $OctopusParameters['Octopus.Release.Id']) |\n ForEach-Object { Invoke-OctopusApi (Format-LinksUri -Uri $_.Links.ProjectDeploymentProcessSnapshot) } |\n ForEach-Object Steps | Where-Object Id -eq $OctopusParameters['Octopus.Step.Id'] |\n ForEach-Object Actions | Where-Object Id -eq $OctopusParameters['Octopus.Action.Id'] |\n ForEach-Object { $_.Properties.Chain_PostDeploy }\nWrite-Verbose \"Raw Post-Deploy Script:`n$rawPostDeployScript\"\n\nAdd-Type -Path (Get-WmiObject Win32_Process | Where-Object ProcessId -eq $PID | ForEach-Object { Get-Process -Id $_.ParentProcessId } | ForEach-Object { Join-Path (Split-Path -Path $_.Path -Parent) 'Octostache.dll' })\n\n$deploymentControllers | ForEach-Object {\n $deployment = $_.Task.Deployment\n $tenant = $_.Tenant\n $variablesDictionary = [Octostache.VariableDictionary]::new()\n Invoke-OctopusApi (\"$Chain_BaseApiUrl/variables/{0}\" -f $deployment.ManifestVariableSetId) | ForEach-Object Variables | Where-Object {\n ($_.IsSensitive -eq $false) -and `\n ($_.Scope.Private -ne 'True') -and `\n ($null -eq $_.Scope.Action) -and `\n ($null -eq $_.Scope.Machine) -and `\n ($null -eq $_.Scope.TargetRole) -and `\n ($null -eq $_.Scope.Role) -and `\n ($null -eq $_.Scope.Tenant -or $_.Scope.Tenant -contains $tenant.Id) -and `\n ($null -eq $_.Scope.TenantTag -or (Compare-Object $_.Scope.TenantTag $tenant.TenantTags -ExcludeDifferent -IncludeEqual)) -and `\n ($null -eq $_.Scope.Environment -or $_.Scope.Environment -contains $deployment.EnvironmentId) -and `\n ($null -eq $_.Scope.Channel -or $_.Scope.Channel -contains $deployment.ChannelId) -and `\n ($null -eq $_.Scope.Project -or $_.Scope.Project -contains $deployment.ProjectId)\n } | ForEach-Object { $variablesDictionary.Set($_.Name, $_.Value) }\n $postDeployScript = $variablesDictionary.Evaluate($rawPostDeployScript)\n Write-Host \"$($_.LogPrefix)Evaluated Post-Deploy Script:\"\n Write-Host $postDeployScript\n Write-Host 'Script output:'\n [scriptblock]::Create($postDeployScript).Invoke()\n}"},"Category":"Octopus","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/octopus-chain-deployment.json","Website":"/step-templates/18392835-d50e-4ce9-9065-8e15a3c30954","Logo":"iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1QTFRFT6Tl////L5Pg8vj9Y67omsvwPJrisdfzfbzs5fL7y+T32Ov5isLucLXqvt31CJPHWwAABMJJREFUeNrs3deW4jAMAFDF3U75/89dlp0ZhiU4blJEjvQ8hYubLJsA00UCBCIQgQhEIAIRiEAEIhCBCEQgAhGIQAQiEIEIhD8kJm+t+QprfdKfB9HbYpx6CWfspj8HMi+gMgHL/AmQA8W3JTKH+ALFvzCeL0RbpyoCPE9IJeNOSQwh5Z3qd6yRGWQ2qi2cZQWxqj1WzQYSjeoJmJlAklOd4VlArOqPhQEkqBERToeMcfRJBkC0Uep8CfBpjz4JsHJ0zF3dkEWNje0kiB/sUC6eApndaIiCMyAa1PiwJ0AWhRGJHJJQHG2dC7h1rNbO1QOxSA7lNCkkKrQIpJCAB1GREILYIC1NAiwbpKFJgGWDNExcwGstfExcZBCHC6nOglshHtmhViLIig1RNBCN7qjtW8C0Z1UvJcC1Z9XmwMBzzvobmgAyEzgq91dtEEsBsQSQQAFZCSBAATEEEApHZbrVBIkkEIUPSVeB+KtALA0kXQUSrwKZBCIQBnk8Y4i5CsReBeKvkqLM+BCSDWJlrZFvGk9SRTHshkgjZCGAaArIxm3H3grhVzFlW2msfl1ca79UJ1bofYvsDHHlNdTZnlh5MghuPd5NdBDUNZHyCkfktIh03XzALGRPlBDPac7qgWjHZzWcmF5zmmkhidMQ6boKiDXcDTUEaylZqCGJ0Vjvu/fLJtHqhSANEvqb2OYqkOUqEHuVMbJcZdZCGiPhKhC4yjqiIjEE7XThMp8fAWII3mY3kUIQD+AMKQTzPiBhgQ63HlT/KSvgtoi0dq5mCPah1UIE0eh3sT0NhOByvKeAkFzi8PgQomumFhsyOxpIzZN4gLOj5plVwNpR0b2AuePWKBEHQu24pSsJA+LVCeHHQxZ1SiyDIdqok8IOhSSnTottHEQTdyt4ettAj4KkzA4dMikk2Dht2S5ptm1vswnPDxn0YyDZ5oDM3iToo2T5voWaYe+Q+vdjH80QyAzZhCgcDtLMI1Tmtz9w++XHgziHQHJJu/OZ3bs9Xn8gQ72NcP3dKqEfkp10F51xhoIi2I91R+LurXV/5q7pH+wx061CzO16oSQleMyr8fXvwMA0Pro8432DPD/ySx8XrHfSuDAM8n6UhnjQabaiXf5Bq/lREHvEeNtn1rJ08+C/uXkQZHeguxAPC3UvtcJYUogLzZX5hhZZvS6onG5lxXtzWGaygwb79vT/IXhdlNibwlKYOR6T8xjI7W8n+xV7T+GH4tMzWwR+lZhRkJYSsC0thpmCYqyngOz3rN2FLBZ2wZflBCggUHF0Vnp88JKienzIXLSEZCZqU7IKr/gQW9yx3pzV7Y9kvWZWTRRIqDmTtRUnU7b2lLcTYmoqHqnmiO1poER0SPkAeZMAZxaJx0Y3TCdAclsIqDz03ALcyxfTCZBsthoGXWmigGyVhWPLFJJfuuKQWycoEFdXbH4dJJoJxNR1eD/kshz6yn48cF8yW8sFoitflB1w6Q8n+/15Za7oA17/pYNmYgP5fmWm8L1NOHPWgK8kuFew1/JXtOA0yJCv7ah7X8ObUuT5kObU30+fDZm8+zqP+HTIpK0xQ796b5Kv2hSIQAQiEIEIRCACEYhABCIQgQhEIAIRiEAEIpBf8UeAAQAEjtYmlDTcCgAAAABJRU5ErkJggg==","$Meta":{"Type":"ActionTemplate"}},{"Id":"cb0ca23c-524d-44a9-86e0-2ae05989d6a0","Name":"Check for Pending Restart and Restart if required","Description":"Checks if Server is pending a reboot, and reboots if it needs it.","Version":0,"ExportedAt":"2020-01-14T08:41:32.508Z","ActionType":"Octopus.Script","Author":"DevOpsDerek","Packages":[],"Parameters":[],"Properties":{"Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptBody":"# Sourced from https://github.com/adbertram/Random-PowerShell-Work/blob/master/Random%20Stuff/Test-PendingReboot.ps1\n# Script will run only on the server with the Tentacle installed\n\nfunction Test-RegistryKey($Key) {\n if (Get-Item -Path $Key -ErrorAction Ignore) {\n return $true\n }\n return $false\n}\n\nfunction Test-RegistryValue($Key, $Value) {\n if (Get-ItemProperty -Path $Key -Name $Value -ErrorAction Ignore) {\n return $true\n }\n return $false\n}\n\nfunction Test-RegistryValueNotNull($Key, $Value) {\n if (($regVal = Get-ItemProperty -Path $Key -Name $Value -ErrorAction Ignore) -and $regVal.($Value)) {\n return $true\n }\n return $false\n}\n\n$IsPendingReboot = $false\n\n# Testing Registry keys for Restarts\n# an exception is thrown when Get-ItemProperty or Get-ChildItem are passed a nonexistant key path\n$tests = @(\n { Test-RegistryKey -Key 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\RebootPending' }\n { Test-RegistryKey -Key 'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\RebootInProgress' }\n { Test-RegistryKey -Key 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\\RebootRequired' }\n { Test-RegistryKey -Key 'HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\PackagesPending' }\n { Test-RegistryKey -Key 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\\PostRebootReporting' }\n { Test-RegistryValueNotNull -Key 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager' -Value 'PendingFileRenameOperations' }\n { Test-RegistryValueNotNull -Key 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager' -Value 'PendingFileRenameOperations2' }\n { \n\t\t(Test-RegistryKey -Key 'HKLM:\\SOFTWARE\\Microsoft\\Updates') -and\n\t\t(Get-ItemProperty -Path 'HKLM:\\SOFTWARE\\Microsoft\\Updates' -Name 'UpdateExeVolatile' | Select-Object -ExpandProperty UpdateExeVolatile) -ne 0 \n\t}\n { Test-RegistryValue -Key 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce' -Value 'DVDRebootSignal' }\n { Test-RegistryKey -Key 'HKLM:\\SOFTWARE\\Microsoft\\ServerManager\\CurrentRebootAttemps' }\n { Test-RegistryValue -Key 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\Netlogon' -Value 'JoinDomain' }\n { Test-RegistryValue -Key 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\Netlogon' -Value 'AvoidSpnSet' }\n {\n (Get-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName').ComputerName -ne\n (Get-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName').ComputerName\n }\n {\n if (Get-ChildItem -Path 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Services\\Pending') {\n $true\n }\n }\n)\n\nWrite-Debug \"Running tests to checking for reboot pending\"\nforeach ($test in $tests) {\n if (& $test) {\n Write-Debug \"Test found reboot pending: $test\"\n $IsPendingReboot = $true\n break\n }\n}\n \n\nif($IsPendingReboot -eq $true) {\n Write-Host \"Restarting\"\n Restart-Computer -Force\n}\nif($IsPendingReboot -eq $false) {\n Write-Host \"No Restart required\"\n}\n"},"Category":"Windows","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/windows-restart-if-required.json","Website":"/step-templates/cb0ca23c-524d-44a9-86e0-2ae05989d6a0","Logo":"iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////Da3qSsLvhtb0wur6O7zuWcfxldv2aMzyK7ftpOD3s+X48Pr+0fD7d9HzHLLr4fX8xD/OcwAAAaNJREFUeNrs3cFygjAUQFECWott1f//2sJoW6kIKEzNs+euXOmcmSSGDa8oJEmSJEmSJGmsj1W1K9cpsGD1Vr2WdToVEPC+2lYvZfpVrEW0qZpF1F+MRdRugzoNlvkiarfBPk0pT8GhWUSX2yASpDlLr2+DEJBmEY1ug6whx7N0n2b30G1QlmmxHsRYp6X76yvF9vg5RYQczq8UVURI35UiFmTgShED0p6lI1eKzCHTrxS5Qk6PZ9PLDtJ9PIsJmXWlyAky6/dAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQMJCyjltF/iO3gpJUpD8s4OAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8T8itwwKyhbTdMr4ha8hXUwZqhICcOgyNOIkE+V5wo4MSgr1u/fp7poO+AL8K/gL8yw0UeyRB34m9iQ/pVD8L5JYTO3NI58R+AsiEEzsW5OfE3sUe/zRwYkeGnG2g2CPS7rhjF4GKP0ZwyoldxK37kFqEL/7wU0mSJEmSJOmJ+xRgAHxZTCXGdZkfAAAAAElFTkSuQmCC","$Meta":{"Type":"ActionTemplate"}},{"Id":"735d2f76-fdbb-4232-9f36-07020cad120d","Name":"Check SQL Server in High Availability Group","Description":"Checks for SQL Node currently being serving as primary on high availability group and sets Octopus variable : SQLIsOnSecondary to true if secondary is active in High Availability Group","Version":1,"ExportedAt":"2019-10-13T08:11:56.532Z","ActionType":"Octopus.Script","Author":"vasant-horapeti","Parameters":[{"Id":"afe518f5-5778-45b4-86c7-3715fa55b4d9","Name":"HAGroupSQLServer","Label":"Enter server name","HelpText":"SQL Server name used in connection string from website code","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}},{"Id":"c3c49b74-9982-400d-bc8f-b292ea7b2488","Name":"HAGroupPrimaryNode","Label":"Enter primary node","HelpText":"Enter primary SQL server name which serves traffic","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"},"Links":{}}],"Properties":{"Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.RunOnServer":"false","Octopus.Action.Script.ScriptBody":"function CheckSQLServerInAOAG($SqlServer, $PrimaryNode)\n{\n $serverConn = new-object ('Microsoft.SqlServer.Management.Common.ServerConnection') $SqlServer\n \n try{\n $serverConn.Connect();\n $server = new-object ('Microsoft.SqlServer.Management.Smo.Server') $serverConn \n if (!$server.IsHadrEnabled)\n {\n \t Write-Host \"The SQL Server [$SqlServer] is not configured with High Availability Group.\"\n }\n else\n {\n # Get SQL Availability Group\n $SQLAvailabilityGroup = $server.AvailabilityGroups[0]\n \n Write-Host \"Getting High Availability Group properties.\"\n \n # Get SQL Availability Groups Properties\n\t $SQLAvailabilityGroupName = $SQLAvailabilityGroup.Name;\n\t $SQLAvailabilityGroupID = $SQLAvailabilityGroup.Id;\n\t $SQLAvailabilityGroupGuid = $SQLAvailabilityGroup.UniqueId;\n\t $SQLLocalReplicaRole = $SQLAvailabilityGroup.LocalReplicaRole;\n\t $SQLPrimaryReplicaServerName = $SQLAvailabilityGroup.PrimaryReplicaServerName;\n\t \n\t Write-Host\t\"SQLAvailabilityGroupName : $SQLAvailabilityGroupName\"\n Write-Host\t\"SQLAvailabilityGroupID : $SQLAvailabilityGroupID\"\n Write-Host\t\"SQLAvailabilityGroupGuid : $SQLAvailabilityGroupGuid\"\n Write-Host\t\"SQLLocalReplicaRole : $SQLLocalReplicaRole\"\n Write-Host\t\"SQLPrimaryReplicaServerName : $SQLPrimaryReplicaServerName\" \n \n if ($SQLPrimaryReplicaServerName -eq $PrimaryNode)\n {\n \t Write-Host \"Setting Octopus variable SQLIsOnSecondary false\"\n Set-OctopusVariable -name \"SQLIsOnSecondary\" -value \"false\" \n }\n else \n {\n \t Write-Host \"Setting Octopus variable SQLIsOnSecondary true\"\n \t Set-OctopusVariable -name \"SQLIsOnSecondary\" -value \"true\"\n }\n }\n }\n catch\n {\n throw \"Could not connect to server $SqlServer. Exception is:`r`n$($_ | fl -force | out-string)\"\n }\n finally\n {\n $serverConn.Disconnect();\n }\n}\n\n[System.Reflection.Assembly]::LoadWithPartialName(\"Microsoft.SqlServer.SMO\") | out-null\n[System.Reflection.Assembly]::LoadWithPartialName(\"Microsoft.SqlServer.ConnectionInfo\") | out-null\nCheckSQLServerInAOAG $HAGroupSQLServer $HAGroupPrimaryNode","Octopus.Action.Script.ScriptFileName":null,"Octopus.Action.Package.FeedId":null,"Octopus.Action.Package.PackageId":null},"Category":"SQL Server","HistoryUrl":"https://github.com/OctopusDeploy/Library/commits/master/step-templates/sqlserver-high-availability-group.json","Website":"/step-templates/735d2f76-fdbb-4232-9f36-07020cad120d","Logo":"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","$Meta":{"Type":"ActionTemplate"}},{"Id":"e04c5cd8-0982-44b8-9cae-0a4b43676adc","Name":"Check VMSS Provision Status (Deployment Targets)","Description":"Use this step when leveraging Azure Virtual Machines Scale Sets (VMSS) with Octopus Deploy Deployment Targets.\n\n**Please run this on a worker or the Octopus Server.**\n\nThis step specifically targets Deployment Targets. It will:\n- Pause a runbook run or deployment until the VMSS has been provisioned\n- Pause a runbook run or deployment until all the VMs in a VMss have been provisioned\n- Reconcile the list of VMs in the VMSS with the list of VMs in Octopus Deploy. Any VMs in Octopus Deploy (based on role) not in the VMSS will be removed.\n- Set output variables of all the deployment targets found in the VMSS.\n\nThis step will set the following output variables:\n- `VMSSHasServersToDeployTo`: Indicates the VMSS has servers to deploy to. \n- `VMSSDeploymentTargetIds`: A comma-separated list of deployment target Ids you can use in later steps.\n- `VMSSDeploymentTargetNames`: A comma-separated list of deployment target names you can use in later steps.\n\n**Please Note**: Setting the parameter `Exclude Pre-Existing Servers from Output` to `Yes` will remove any servers prior to a scale event from being returned in the output variables. \n\nThis step makes the following assumptions:\n- The name of the machine registration in Octopus matches the computer name. Like matching is supported, for example, a match will be made in the case of Octopus has `p-app-server-01` and the computer name is `p-app-server-01.mydomain.com.` \n- You have the Azure Az PowerShell modules pre-installed on a worker or your Octopus Server.\n- This step is running in the same space/environment/tenant (optional) as the deployment targets.","Version":3,"ExportedAt":"2021-07-26T19:15:02.718Z","ActionType":"Octopus.AzurePowerShell","Author":"BobJWalker","Packages":[],"Parameters":[{"Id":"9f9bc9fb-fa96-41ab-aa06-ad0dd68ff038","Name":"VMSS.ScaleSet.Name","Label":"VMSS Name","HelpText":"**Required**\n\nThe name of the Azure Virtual Machine Scale Set","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"32939873-a965-46ae-915f-f94d93f94c0b","Name":"VMSS.ResourceGroup.Name","Label":"VMSS Resource Group Name","HelpText":"**Required**\n\nThe name of the resource group where the VMSS is located.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"571df393-6353-4f12-96cd-c92f3a5e1452","Name":"VMSS.Azure.Account","Label":"Azure Account","HelpText":"**Required**\n\nThe Azure Account to use when querying the VMSS.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"AzureAccount"}},{"Id":"b03d1bf3-76f8-4a3c-917a-60d5e19a15f4","Name":"VMSS.DeploymentTarget.Roles","Label":"Deployment Target Roles","HelpText":"**Required**\n\nA comma-separated list of deployment target roles to filter your deployment targets by. These roles are how this step will determine which machines to reconcile.\n\nIf you supply multiple roles, for example `todo-web-server,todo-virtual-machine-scale-set` the deployment targets have to be assigned `todo-web-server` AND `todo-virtual-machine-scaleset` roles for the target to be considered.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"757ca61b-d15b-4dbb-911a-b3f4dc0258b5","Name":"VMSS.Octopus.Url","Label":"Octopus URL","HelpText":"**Required**\n\nThe URL of the Octopus Server to query against. Example: `https://samples.octopus.app`.","DefaultValue":"#{Octopus.Web.ServerUri}","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"7b070182-e79b-48a0-966a-39d332802b60","Name":"VMSS.Octopus.ApiKey","Label":"Octopus API Key","HelpText":"**Required**\n\nAPI Key of a service account that has permissions to:\n- Query deployment targets, environments, and tenants. \n- Query events (audit history) \n- Delete deployment targets\n\nAssigning the service account to a team with `Project Viewer` and `Environment Manager` roles will work.","DefaultValue":"","DisplaySettings":{"Octopus.ControlType":"Sensitive"}},{"Id":"6e0f8635-70ba-4b8a-b5b4-909dba3f9fd8","Name":"VMSS.Timeout.Value","Label":"Timeout (In Minutes)","HelpText":"**Required**\n\nHow long this step will wait (in minutes) for the VMSS and VMs in the VMSS to finish being created.","DefaultValue":"30","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"0392f153-73b0-44d4-9181-4f366c9012f7","Name":"VMSS.Timeout.ErrorHandle","Label":"Timeout Error","HelpText":"**Required**\n\nWhat will happen when a timeout occurs.\n\n- `Proceed`: The script will reconcile the VMs it can and then finish. No error thrown. \n- `Error`: Will throw an error and it will stop the deployment from proceeding.\n\nThe default is `Proceed`","DefaultValue":"Proceed","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"Proceed|Proceed\nError|Error"}},{"Id":"80ef4fb9-c773-4d0a-82af-efdfb302e58f","Name":"VMSS.Duplicate.TimeInMinutes","Label":"Duplicate Run Time Allowance (in Minutes)","HelpText":"**Required**\n\nThis step is designed to wait for VMSS to finish scaling out. However, Octopus isn't aware of VMSS and may attempt to run the same deployment multiple times as new targets are \"discovered.\"\n\nTypically, when this happens, a deployment is queued within a few minutes of the previous one finishing. When that happens this step will treat that as a duplicate run. \n\nThis setting indicates the number of minutes that must pass before a duplicate run is found. The default is `3` minutes.","DefaultValue":"3","DisplaySettings":{"Octopus.ControlType":"SingleLineText"}},{"Id":"0eb3bed8-9259-440e-bff0-cb86af7da52e","Name":"VMSS.Duplicate.Handle","Label":"Duplicate Run Adjustment","HelpText":"**Required**\n\nWhat the step will do when a duplicate run is found. The two options are:\n\n- `Cancel`: cancel the current runbook run or deployment.\n- `Proceed`: continue on with the current runbook run or deployment.\n\nThe default is `Proceed`.","DefaultValue":"Proceed","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"Cancel|Cancel\nProceed|Proceed"}},{"Id":"adaf6a8c-453f-4b69-9ba6-f6a54b4f5bb9","Name":"VMSS.OldServers.ExcludeFromOutput","Label":"Exclude Pre-Existing Servers from Output","HelpText":"**Required**\n\nOld servers are any servers that existed prior to scaling out the VMSS. \n\nIf this step is run in a deployment target trigger it will pull back all the machines in a scale set and return them in an output variable. Depending on how you use that list, this could result in redeployment.\n\nYou can exclude pre-existing servers by setting this value to `Yes`. The default is `No`.","DefaultValue":"No","DisplaySettings":{"Octopus.ControlType":"Select","Octopus.SelectOptions":"No|No\nYes|Yes"}}],"Properties":{"OctopusUseBundledTooling":"False","Octopus.Action.Script.ScriptSource":"Inline","Octopus.Action.Script.Syntax":"PowerShell","Octopus.Action.Azure.AccountId":"#{VMSS.Azure.Account}","Octopus.Action.Script.ScriptBody":"$vmssScaleSetName = $OctopusParameters[\"VMSS.ScaleSet.Name\"]\n$vmssScaleSetResourceGroup = $OctopusParameters[\"VMSS.ResourceGroup.Name\"]\n$roleToSearchFor = $OctopusParameters[\"VMSS.DeploymentTarget.Roles\"]\n$apiKey = $OctopusParameters[\"VMSS.Octopus.ApiKey\"]\n$octopusUrl = $OctopusParameters[\"VMSS.Octopus.Url\"]\n$timeoutInMinutes = $OctopusParameters[\"VMSS.Timeout.Value\"]\n$timeoutErrorHandle = $OctopusParameters[\"VMSS.Timeout.ErrorHandle\"]\n$duplicateRunDetectionInMinutes = $OctopusParameters[\"VMSS.Duplicate.TimeInMinutes\"]\n$duplicateRunHandle = $OctopusParameters[\"VMSS.Duplicate.Handle\"]\n$excludeOldServers = $OctopusParameters[\"VMSS.OldServers.ExcludeFromOutput\"]\n\n$octopusSpaceId = $OctopusParameters[\"Octopus.Space.Id\"]\n$octopusEnvironmentId = $OctopusParameters[\"Octopus.Environment.Id\"]\n$octopusTenantId = $OctopusParameters[\"Octopus.Deployment.Tenant.Id\"]\n$octopusDeploymentId = $OctopusParameters[\"Octopus.Deployment.Id\"]\n$octopusTriggerId = $OctopusParameters[\"Octopus.Deployment.Trigger.Id\"]\n$octopusTaskId = $OctopusParameters[\"Octopus.Task.Id\"]\n$octopusRunbookRunId = $OctopusParameters[\"Octopus.RunbookRun.Id\"]\n\nfunction Invoke-OctopusApi\n{\n param\n (\n $octopusUrl,\n $endPoint,\n $spaceId,\n $apiKey,\n $method,\n $item \n )\n\n if ([string]::IsNullOrWhiteSpace($SpaceId))\n {\n $url = \"$OctopusUrl/api/$EndPoint\"\n }\n else\n {\n $url = \"$OctopusUrl/api/$spaceId/$EndPoint\" \n } \n\n try\n { \n if ($null -ne $item)\n {\n $body = $item | ConvertTo-Json -Depth 10\n Write-Verbose $body\n\n Write-Host \"Invoking $method $url\"\n return Invoke-RestMethod -Method $method -Uri $url -Headers @{\"X-Octopus-ApiKey\" = \"$ApiKey\" } -Body $body -ContentType 'application/json; charset=utf-8' \n }\n\n\t\tWrite-Verbose \"No data to post or put, calling bog standard invoke-restmethod for $url\"\n $result = Invoke-RestMethod -Method $method -Uri $url -Headers @{\"X-Octopus-ApiKey\" = \"$ApiKey\" } -ContentType 'application/json; charset=utf-8'\n\n return $result\n\n \n }\n catch\n {\n if ($null -ne $_.Exception.Response)\n {\n if ($_.Exception.Response.StatusCode -eq 401)\n {\n Write-Error \"Unauthorized error returned from $url, please verify API key and try again\"\n }\n elseif ($_.Exception.Response.statusCode -eq 403)\n {\n Write-Error \"Forbidden error returned from $url, please verify API key and try again\"\n }\n else\n { \n