diff --git a/Tasks/ServiceFabricComposeDeployV0/ServiceFabricComposeDeploy.ps1 b/Tasks/ServiceFabricComposeDeployV0/ServiceFabricComposeDeploy.ps1 index 656ebf3b52b0..1aacc89512c0 100644 --- a/Tasks/ServiceFabricComposeDeployV0/ServiceFabricComposeDeploy.ps1 +++ b/Tasks/ServiceFabricComposeDeployV0/ServiceFabricComposeDeploy.ps1 @@ -22,6 +22,7 @@ try $deployTimeoutSec = Get-VstsInput -Name deployTimeoutSec $removeTimeoutSec = Get-VstsInput -Name removeTimeoutSec $getStatusTimeoutSec = Get-VstsInput -Name getStatusTimeoutSec + $upgrade = (Get-VstsInput -Name upgrade) -eq "true" $apiVersion = '2.8' $regKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Service Fabric SDK\' -ErrorAction SilentlyContinue @@ -172,48 +173,102 @@ try $getStatusParameters['TimeoutSec'] = $getStatusTimeoutSec } + $upgrading = $false $existingApplication = Get-ServiceFabricComposeApplicationStatusHelper -ApiVersion $apiVersion -GetStatusParameters $getStatusParameters if ($existingApplication -ne $null) { - Write-Host (Get-VstsLocString -Key RemovingApplication -ArgumentList $applicationName) - - Remove-ServiceFabricComposeApplicationHelper -ApiVersion $apiVersion -RemoveParameters $removeParameters - do + if ($apiVersion -eq "2.8" -and $upgrade) { - Write-Host (Get-VstsLocString -Key CurrentStatus -ArgumentList $existingApplication.Status) - Start-Sleep -Seconds 3 - $existingApplication = Get-ServiceFabricComposeApplicationStatusHelper -ApiVersion $apiVersion -GetStatusParameters $getStatusParameters + $upgrading = $true } - while ($existingApplication -ne $null) - Write-Host (Get-VstsLocString -Key ApplicationRemoved) - } + else + { + Write-Host (Get-VstsLocString -Key RemovingApplication -ArgumentList $applicationName) - Write-Host (Get-VstsLocString -Key CreatingApplication) - New-ServiceFabricComposeApplicationHelper -ApiVersion $apiVersion -DeployParameters $deployParameters + Remove-ServiceFabricComposeApplicationHelper -ApiVersion $apiVersion -RemoveParameters $removeParameters + do + { + Write-Host (Get-VstsLocString -Key CurrentStatus -ArgumentList $existingApplication.Status) + Start-Sleep -Seconds 3 + $existingApplication = Get-ServiceFabricComposeApplicationStatusHelper -ApiVersion $apiVersion -GetStatusParameters $getStatusParameters + } + while ($existingApplication -ne $null) + Write-Host (Get-VstsLocString -Key ApplicationRemoved) + } + } - Write-Host (Get-VstsLocString -Key WaitingForDeploy) - $newApplication = Get-ServiceFabricComposeApplicationStatusHelper -ApiVersion $apiVersion -GetStatusParameters $getStatusParameters - while (($newApplication -eq $null) -or ` - ($newApplication.Status -eq 'Provisioning') -or ` - ($newApplication.Status -eq 'Creating')) + if ($upgrading) { - if ($newApplication -eq $null) + $upgradeParameters = New-Object 'System.Collections.Hashtable' $deployParameters + $upgradeParameters.Monitored = $True + $upgradeParameters.FailureAction = 'Rollback' + $upgradeParameters.ConsiderWarningAsError = $True + $upgradeParameters.Force = $True + + $upgradeStatus = Get-ServiceFabricComposeDeploymentUpgradeHelper -ApiVersion $apiVersion -GetUpgradeParameters $getStatusParameters + if (($upgradeStatus -ne $null) -and (IsUpgradeRunning $upgradeStatus.UpgradeState)) { - Write-Host (Get-VstsLocString -Key WaitingForDeploy) + Write-Error (Get-VstsLocString -Key UpgradeInProgress -ArgumentList $applicationName) } - else + + Write-Host (Get-VstsLocString -Key UpgradingApplication) + Start-ServiceFabricComposeDeploymentUpgradeHelper -ApiVersion $apiVersion -UpgradeParameters $upgradeParameters + + Write-Host (Get-VstsLocString -Key WaitingForUpgrade) + # Wait a minute before checking on the upgrade to avoid getting the status of the last upgrade. + Start-Sleep -Seconds 60 + $upgradeStatus = Get-ServiceFabricComposeDeploymentUpgradeHelper -ApiVersion $apiVersion -GetUpgradeParameters $getStatusParameters + while (($upgradeStatus -eq $null) -or (IsUpgradeRunning $upgradeStatus.UpgradeState)) + { + if ($upgradeStatus -eq $null) + { + Write-Host (Get-VstsLocString -Key WaitingForUpgrade) + } + else + { + Write-Host (Get-VstsLocString -Key CurrentStatus -ArgumentList $upgradeStatus.UpgradeState ) + } + Start-Sleep -Seconds 3 + + $upgradeStatus = Get-ServiceFabricComposeDeploymentUpgradeHelper -ApiVersion $apiVersion -GetUpgradeParameters $getStatusParameters + } + Write-Host (Get-VstsLocString -Key CurrentStatus -ArgumentList $upgradeStatus.UpgradeState) + + if ($upgradeStatus.UpgradeState -ne 'RollingForwardCompleted') { - Write-Host (Get-VstsLocString -Key CurrentStatus -ArgumentList $newApplication.Status) + Write-Error (Get-VstsLocString -Key UpgradeFailed -ArgumentList @($upgradeStatus.UpgradeState.ToString(), $upgradeStatus.UpgradeStatusDetails)) } - Start-Sleep -Seconds 3 - $newApplication = Get-ServiceFabricComposeApplicationStatusHelper -ApiVersion $apiVersion -GetStatusParameters $getStatusParameters } - Write-Host (Get-VstsLocString -Key CurrentStatus -ArgumentList $newApplication.Status) - - if ($newApplication.Status -ne 'Created' -and $newApplication.Status -ne 'Ready') + else { - Write-Error (Get-VstsLocString -Key DeployFailed -ArgumentList @($newApplication.Status.ToString(), $newApplication.StatusDetails)) + Write-Host (Get-VstsLocString -Key CreatingApplication) + New-ServiceFabricComposeApplicationHelper -ApiVersion $apiVersion -DeployParameters $deployParameters + + Write-Host (Get-VstsLocString -Key WaitingForDeploy) + $newApplication = Get-ServiceFabricComposeApplicationStatusHelper -ApiVersion $apiVersion -GetStatusParameters $getStatusParameters + while (($newApplication -eq $null) -or ` + ($newApplication.Status -eq 'Provisioning') -or ` + ($newApplication.Status -eq 'Creating')) + { + if ($newApplication -eq $null) + { + Write-Host (Get-VstsLocString -Key WaitingForDeploy) + } + else + { + Write-Host (Get-VstsLocString -Key CurrentStatus -ArgumentList $newApplication.Status) + } + Start-Sleep -Seconds 3 + $newApplication = Get-ServiceFabricComposeApplicationStatusHelper -ApiVersion $apiVersion -GetStatusParameters $getStatusParameters + } + Write-Host (Get-VstsLocString -Key CurrentStatus -ArgumentList $newApplication.Status) + + if ($newApplication.Status -ne 'Created' -and $newApplication.Status -ne 'Ready') + { + Write-Error (Get-VstsLocString -Key DeployFailed -ArgumentList @($newApplication.Status.ToString(), $newApplication.StatusDetails)) + } } + } finally { diff --git a/Tasks/ServiceFabricComposeDeployV0/Strings/resources.resjson/en-US/resources.resjson b/Tasks/ServiceFabricComposeDeployV0/Strings/resources.resjson/en-US/resources.resjson index 140dcd7d4aee..d19c526f0101 100644 --- a/Tasks/ServiceFabricComposeDeployV0/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/ServiceFabricComposeDeployV0/Strings/resources.resjson/en-US/resources.resjson @@ -23,6 +23,8 @@ "loc.input.help.registryPassword": "Password for the Docker registry. If the password is not encrypted, it is recommended that you use a custom release definition secret variable to store it.", "loc.input.label.passwordEncrypted": "Password Encrypted", "loc.input.help.passwordEncrypted": "It is recommended to encrypt your password using [Invoke-ServiceFabricEncryptText](https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-application-secret-management#encrypt-application-secrets). If you do not, and a certificate matching the Server Certificate Thumbprint in the Cluster Connection is installed on the build agent, it will be used to encrypt the password; otherwise an error will occur.", + "loc.input.label.upgrade": "Upgrade", + "loc.input.help.upgrade": "Upgrade an existing deployment rather than removing it.", "loc.input.label.deployTimeoutSec": "Deploy Timeout (s)", "loc.input.help.deployTimeoutSec": "Timeout in seconds for deploying the application.", "loc.input.label.removeTimeoutSec": "Remove Timeout (s)", @@ -39,11 +41,15 @@ "loc.messages.ApplicationRemoved": "Application removed.", "loc.messages.EncryptingPassword": "Encrypting the password with the Server Certificate.", "loc.messages.CreatingApplication": "Creating application", + "loc.messages.UpgradingApplication": "Upgrading application", "loc.messages.WaitingForDeploy": "Waiting for deploy...", + "loc.messages.WaitingForUpgrade": "Waiting for upgrade...", "loc.messages.CurrentStatus": "Current Status: {0}", "loc.messages.DeployFailed": "Deploy Failed\nStatus: {0}\nDetails: {1}", + "loc.messages.UpgradeFailed": "Upgrade Failed\nStatus: {0}\nDetails: {1}", "loc.messages.CheckingComposeFile": "Checking compose file", "loc.messages.UnsupportedAPIVersion": "Service Fabric SDK version {0} is not supported.", "loc.messages.UsingAPIVersion": "Using cmdlets for Service Fabric SDK version {0}.", - "loc.messages.InvalidApplicationNameWarning": "Latest Service Fabric has stopped supporting compose application name starting with 'fabric:/' and hence compose deployment might fail with ServiceDnsName error for application name '{0}'. You can provide a different application name and re-run if required." + "loc.messages.InvalidApplicationNameWarning": "Latest Service Fabric has stopped supporting compose application name starting with 'fabric:/' and hence compose deployment might fail with ServiceDnsName error for application name '{0}'. You can provide a different application name and re-run if required.", + "loc.messages.UpgradeInProgress": "An upgrade for the application '{0}' is already in progress." } \ No newline at end of file diff --git a/Tasks/ServiceFabricComposeDeployV0/Tests/Deploy.2.8.ps1 b/Tasks/ServiceFabricComposeDeployV0/Tests/Deploy.2.8.ps1 index fe141dad00ae..85bf09d16159 100644 --- a/Tasks/ServiceFabricComposeDeployV0/Tests/Deploy.2.8.ps1 +++ b/Tasks/ServiceFabricComposeDeployV0/Tests/Deploy.2.8.ps1 @@ -20,6 +20,7 @@ Register-Mock Get-VstsInput { $null } -Name deployTimeoutSec Register-Mock Get-VstsInput { $null } -Name removeTimeoutSec Register-Mock Get-VstsInput { $null } -Name getStatusTimeoutSec Register-Mock Get-VstsInput { "None" } -Name registryCredentials -Require +Register-Mock Get-VstsInput { "false" } -Name upgrade # Setup file resolution Register-Mock Find-VstsFiles { $composeFilePath } -- -LegacyPattern $composeFilePath diff --git a/Tasks/ServiceFabricComposeDeployV0/Tests/L0.ts b/Tasks/ServiceFabricComposeDeployV0/Tests/L0.ts index 5775a93d4d36..a68b3cdf61c3 100644 --- a/Tasks/ServiceFabricComposeDeployV0/Tests/L0.ts +++ b/Tasks/ServiceFabricComposeDeployV0/Tests/L0.ts @@ -36,6 +36,9 @@ describe('ServiceFabricComposeDeploy Suite', function () { it('Deploy Preview', (done) => { psr.run(path.join(__dirname, 'DeployPreview.ps1'), done); }) + it('Replace 2.8', (done) => { + psr.run(path.join(__dirname, 'Replace.2.8.ps1'), done); + }) it('Upgrade 2.7', (done) => { psr.run(path.join(__dirname, 'Upgrade.2.7.ps1'), done); }) diff --git a/Tasks/ServiceFabricComposeDeployV0/Tests/Replace.2.8.ps1 b/Tasks/ServiceFabricComposeDeployV0/Tests/Replace.2.8.ps1 new file mode 100644 index 000000000000..c532eaf28b23 --- /dev/null +++ b/Tasks/ServiceFabricComposeDeployV0/Tests/Replace.2.8.ps1 @@ -0,0 +1,148 @@ +[CmdletBinding()] +param() + +. $PSScriptRoot\..\..\..\Tests\lib\Initialize-Test.ps1 + +$serviceConnectionName = "random connection name" +$composeFilePath = "docker-compose.yml" +$deploymentName = "fabric:/Application1" +$applicationName = "fabric:/fabric:/Application1" +$serverCertThumbprint = "random thumbprint" +$userName = "random user" +$password = "random password" +$connectionEndpointFullUrl = "https://mycluster.com:19000" +$connectionEndpoint = ([System.Uri]$connectionEndpointFullUrl).Authority + +# Setup input arguments +Register-Mock Get-VstsInput { $serviceConnectionName } -Name serviceConnectionName -Require +Register-Mock Get-VstsInput { $composeFilePath } -Name composeFilePath -Require +Register-Mock Get-VstsInput { $deploymentName } -Name applicationName -Require +Register-Mock Get-VstsInput { $null } -Name deployTimeoutSec +Register-Mock Get-VstsInput { $null } -Name removeTimeoutSec +Register-Mock Get-VstsInput { $null } -Name getStatusTimeoutSec +Register-Mock Get-VstsInput { "None" } -Name registryCredentials -Require +Register-Mock Get-VstsInput { "false" } -Name upgrade + +# Setup file resolution +Register-Mock Find-VstsFiles { $composeFilePath } -- -LegacyPattern $composeFilePath + +Register-Mock Assert-VstsPath +Register-Mock Test-Path { $true } -- "HKLM:\SOFTWARE\Microsoft\Service Fabric SDK" + +# Setup mock VSTS service endpoint +$vstsEndpoint = @{ + "url" = $connectionEndpointFullUrl + "Auth" = @{ + "Scheme" = "UserNamePassword" + "Parameters" = @{ + "ServerCertThumbprint" = $serverCertThumbprint + "Username" = $userName + "Password" = $password + } + } +} +Register-Mock Get-VstsEndpoint { $vstsEndpoint } -- -Name $serviceConnectionName -Require + +# Setup mock Registry for Service Fabric +$SfRegistry = @{ + "FabricSDKVersion" = "2.8.1.2" +} +Register-Mock Get-ItemProperty { $SfRegistry } -- -Path 'HKLM:\SOFTWARE\Microsoft\Service Fabric SDK\' -ErrorAction SilentlyContinue + +# Setup mock results of cluster connection +Register-Mock Connect-ServiceFabricClusterFromServiceEndpoint { } -- -ClusterConnectionParameters @{} -ConnectedServiceEndpoint $vstsEndpoint + +$deploymentStatus = @{ + "ApplicationName" = $applicationName + "DeploymentName" = $deploymentName + "ComposeDeploymentStatus" = "Ready" + "StatusDetails" = "" +} + +$deploymentUpgraded = @{ + "ApplicationName" = $applicationName + "DeploymentName" = $deploymentName + "UpgradeState" = "RollingForwardCompleted" + "UpgradeStatusDetails" = "" +} +$applicationUpgraded = @{ + "ApplicationName" = $applicationName + "UpgradeState" = "RollingForwardCompleted" +} + +$deploymentUpgrading = @{ + "ApplicationName" = $applicationName + "DeploymentName" = $deploymentName + "UpgradeState" = "RollingForwardInProgress" + "UpgradeStatusDetails" = "" +} +$applicationUpgrading = @{ + "ApplicationName" = $applicationName + "UpgradeState" = "RollingForwardInProgress" +} + +# Need to store the bool in an object so the lambdas will share the reference +$removed = New-Object 'System.Collections.Generic.Dictionary[string, bool]' +$removed.Value = $false +$isUpgrading = New-Object 'System.Collections.Generic.Dictionary[string, bool]' +$isUpgrading.Value = $false + +Register-Mock Get-ServiceFabricComposeDeploymentStatus { + if (($removed.Value -eq $true)) + { + return $null; + } + else + { + return $deploymentStatus + } +} -DeploymentName: $deploymentName + +Register-Mock Remove-ServiceFabricComposeDeployment { + $removed.Value = $true +} -DeploymentName: $deploymentName -Force: $true + +Register-Mock Test-ServiceFabricApplicationPackage { } -- -ComposeFilePath $composeFilePath -ErrorAction Stop + +Register-Mock New-ServiceFabricComposeDeployment { + $removed.Value = $false +} -- -DeploymentName: $deploymentName -Compose: $composeFilePath + +Register-Mock Get-ServiceFabricComposeDeploymentUpgrade { + if ($isUpgrading.Value -eq $true) + { + return $deploymentUpgrading; + } + else + { + return $deploymentUpgraded + } +} -DeploymentName: $deploymentName + +Register-Mock Get-ServiceFabricApplicationUpgrade { + if ($isUpgrading.Value -eq $true) + { + $isUpgrading.Value = $false + return $applicationUpgrading; + } + else + { + return $applicationUpgraded + } +} -ApplicationName: $applicationName + +Register-Mock Start-ServiceFabricComposeDeploymentUpgrade { + $isUpgrading.Value = $true +} -Force: True -ConsiderWarningAsError: True -FailureAction: Rollback -DeploymentName: $deploymentName -Monitored: True -Compose: $composeFilePath + +Register-Mock Start-Sleep { } -ParametersEvaluator { $true } + +# Act +. $PSScriptRoot\..\..\..\Tasks\ServiceFabricComposeDeployV0\ps_modules\ServiceFabricHelpers\Connect-ServiceFabricClusterFromServiceEndpoint.ps1 +@( & $PSScriptRoot/../../../Tasks/ServiceFabricComposeDeployV0/ServiceFabricComposeDeploy.ps1 ) + +# Assert +Assert-WasCalled Get-ServiceFabricComposeDeploymentStatus -Times 3 +Assert-WasCalled Get-ServiceFabricComposeDeploymentUpgrade -Times 0 +Assert-WasCalled Remove-ServiceFabricComposeDeployment -Times 1 +Assert-WasCalled New-ServiceFabricComposeDeployment -Times 1 \ No newline at end of file diff --git a/Tasks/ServiceFabricComposeDeployV0/Tests/Upgrade.2.8.ps1 b/Tasks/ServiceFabricComposeDeployV0/Tests/Upgrade.2.8.ps1 index c8b7b6bd5b33..d3635b6d47df 100644 --- a/Tasks/ServiceFabricComposeDeployV0/Tests/Upgrade.2.8.ps1 +++ b/Tasks/ServiceFabricComposeDeployV0/Tests/Upgrade.2.8.ps1 @@ -5,7 +5,8 @@ param() $serviceConnectionName = "random connection name" $composeFilePath = "docker-compose.yml" -$applicationName = "fabric:/Application1" +$deploymentName = "fabric:/Application1" +$applicationName = "fabric:/fabric:/Application1" $serverCertThumbprint = "random thumbprint" $userName = "random user" $password = "random password" @@ -15,11 +16,12 @@ $connectionEndpoint = ([System.Uri]$connectionEndpointFullUrl).Authority # Setup input arguments Register-Mock Get-VstsInput { $serviceConnectionName } -Name serviceConnectionName -Require Register-Mock Get-VstsInput { $composeFilePath } -Name composeFilePath -Require -Register-Mock Get-VstsInput { $applicationName } -Name applicationName -Require +Register-Mock Get-VstsInput { $deploymentName } -Name applicationName -Require Register-Mock Get-VstsInput { $null } -Name deployTimeoutSec Register-Mock Get-VstsInput { $null } -Name removeTimeoutSec Register-Mock Get-VstsInput { $null } -Name getStatusTimeoutSec Register-Mock Get-VstsInput { "None" } -Name registryCredentials -Require +Register-Mock Get-VstsInput { "true" } -Name upgrade # Setup file resolution Register-Mock Find-VstsFiles { $composeFilePath } -- -LegacyPattern $composeFilePath @@ -50,42 +52,86 @@ Register-Mock Get-ItemProperty { $SfRegistry } -- -Path 'HKLM:\SOFTWARE\Microsof # Setup mock results of cluster connection Register-Mock Connect-ServiceFabricClusterFromServiceEndpoint { } -- -ClusterConnectionParameters @{} -ConnectedServiceEndpoint $vstsEndpoint -$serviceFabricComposeDeploymentStatus = @{ - "DeploymentName" = $applicationName - "ComposeDeploymentStatus" = "Created" +$deploymentStatus = @{ + "ApplicationName" = $applicationName + "DeploymentName" = $deploymentName + "ComposeDeploymentStatus" = "Ready" "StatusDetails" = "" } +$deploymentUpgraded = @{ + "ApplicationName" = $applicationName + "DeploymentName" = $deploymentName + "UpgradeState" = "RollingForwardCompleted" + "UpgradeStatusDetails" = "" +} +$applicationUpgraded = @{ + "ApplicationName" = $applicationName + "UpgradeState" = "RollingForwardCompleted" +} + +$deploymentUpgrading = @{ + "ApplicationName" = $applicationName + "DeploymentName" = $deploymentName + "UpgradeState" = "RollingForwardInProgress" + "UpgradeStatusDetails" = "" +} +$applicationUpgrading = @{ + "ApplicationName" = $applicationName + "UpgradeState" = "RollingForwardInProgress" +} + # Need to store the bool in an object so the lambdas will share the reference -$removed = New-Object 'System.Collections.Generic.Dictionary[string, bool]' -$removed.Value = $false +$isUpgrading = New-Object 'System.Collections.Generic.Dictionary[string, bool]' +$isUpgrading.Value = $false Register-Mock Get-ServiceFabricComposeDeploymentStatus { - if (($removed.Value -eq $true)) + return $deploymentStatus +} -DeploymentName: $deploymentName + +Register-Mock Remove-ServiceFabricComposeDeployment { +} -DeploymentName: $deploymentName -Force: $true + +Register-Mock Test-ServiceFabricApplicationPackage { } -- -ComposeFilePath $composeFilePath -ErrorAction Stop + +Register-Mock New-ServiceFabricComposeDeployment { +} -- -DeploymentName: $deploymentName -Compose: $composeFilePath + +Register-Mock Get-ServiceFabricComposeDeploymentUpgrade { + if ($isUpgrading.Value -eq $true) { - return $null; + return $deploymentUpgrading; } else { - return $serviceFabricComposeDeploymentStatus + return $deploymentUpgraded } -} -DeploymentName: $applicationName +} -DeploymentName: $deploymentName -Register-Mock Remove-ServiceFabricComposeDeployment { - $removed.Value = $true -} -DeploymentName: $applicationName -Force: True +Register-Mock Get-ServiceFabricApplicationUpgrade { + if ($isUpgrading.Value -eq $true) + { + $isUpgrading.Value = $false + return $applicationUpgrading; + } + else + { + return $applicationUpgraded + } +} -ApplicationName: $applicationName -Register-Mock Test-ServiceFabricApplicationPackage { } -- -ComposeFilePath: $composeFilePath -ErrorAction: Stop +Register-Mock Start-ServiceFabricComposeDeploymentUpgrade { + $isUpgrading.Value = $true +} -Force: True -ConsiderWarningAsError: True -FailureAction: Rollback -DeploymentName: $deploymentName -Monitored: True -Compose: $composeFilePath -Register-Mock New-ServiceFabricComposeDeployment { - $removed.Value = $false -} -- -DeploymentName: $applicationName -Compose: $composeFilePath +Register-Mock Start-Sleep { } -ParametersEvaluator { $true } # Act . $PSScriptRoot\..\..\..\Tasks\ServiceFabricComposeDeployV0\ps_modules\ServiceFabricHelpers\Connect-ServiceFabricClusterFromServiceEndpoint.ps1 @( & $PSScriptRoot/../../../Tasks/ServiceFabricComposeDeployV0/ServiceFabricComposeDeploy.ps1 ) # Assert -Assert-WasCalled Get-ServiceFabricComposeDeploymentStatus -Times 3 -Assert-WasCalled Remove-ServiceFabricComposeDeployment -Times 1 -Assert-WasCalled New-ServiceFabricComposeDeployment -Times 1 \ No newline at end of file +Assert-WasCalled Get-ServiceFabricComposeDeploymentStatus -Times 1 +Assert-WasCalled Get-ServiceFabricComposeDeploymentUpgrade -Times 3 +Assert-WasCalled Remove-ServiceFabricComposeDeployment -Times 0 +Assert-WasCalled New-ServiceFabricComposeDeployment -Times 0 \ No newline at end of file diff --git a/Tasks/ServiceFabricComposeDeployV0/Tests/UpgradePreview.ps1 b/Tasks/ServiceFabricComposeDeployV0/Tests/UpgradePreview.ps1 index b96dc91b5fe8..fe134fe814a3 100644 --- a/Tasks/ServiceFabricComposeDeployV0/Tests/UpgradePreview.ps1 +++ b/Tasks/ServiceFabricComposeDeployV0/Tests/UpgradePreview.ps1 @@ -73,7 +73,7 @@ Register-Mock Get-ServiceFabricComposeApplicationStatusPaged { Register-Mock Remove-ServiceFabricComposeApplication { $removed.Value = $true -} -Force: True -ApplicationName: $applicationName +} -Force: $true -ApplicationName: $applicationName Register-Mock Test-ServiceFabricApplicationPackage { } -- -ComposeFilePath: $composeFilePath -ErrorAction: Stop diff --git a/Tasks/ServiceFabricComposeDeployV0/task.json b/Tasks/ServiceFabricComposeDeployV0/task.json index 992d48410820..7e894eaa1203 100644 --- a/Tasks/ServiceFabricComposeDeployV0/task.json +++ b/Tasks/ServiceFabricComposeDeployV0/task.json @@ -16,8 +16,8 @@ "author": "Microsoft Corporation", "version": { "Major": 0, - "Minor": 2, - "Patch": 6 + "Minor": 3, + "Patch": 0 }, "demands": [ "Cmd" @@ -133,6 +133,15 @@ "groupName": "registry", "visibleRule": "registryCredentials = UsernamePassword" }, + { + "name": "upgrade", + "type": "boolean", + "label": "Upgrade", + "defaultValue": false, + "required": false, + "helpMarkDown": "Upgrade an existing deployment rather than removing it.", + "groupName": "advanced" + }, { "name": "deployTimeoutSec", "type": "string", @@ -177,12 +186,16 @@ "ApplicationRemoved": "Application removed.", "EncryptingPassword": "Encrypting the password with the Server Certificate.", "CreatingApplication": "Creating application", + "UpgradingApplication": "Upgrading application", "WaitingForDeploy": "Waiting for deploy...", + "WaitingForUpgrade": "Waiting for upgrade...", "CurrentStatus": "Current Status: {0}", "DeployFailed": "Deploy Failed\nStatus: {0}\nDetails: {1}", + "UpgradeFailed": "Upgrade Failed\nStatus: {0}\nDetails: {1}", "CheckingComposeFile": "Checking compose file", "UnsupportedAPIVersion": "Service Fabric SDK version {0} is not supported.", "UsingAPIVersion": "Using cmdlets for Service Fabric SDK version {0}.", - "InvalidApplicationNameWarning": "Latest Service Fabric has stopped supporting compose application name starting with 'fabric:/' and hence compose deployment might fail with ServiceDnsName error for application name '{0}'. You can provide a different application name and re-run if required." + "InvalidApplicationNameWarning": "Latest Service Fabric has stopped supporting compose application name starting with 'fabric:/' and hence compose deployment might fail with ServiceDnsName error for application name '{0}'. You can provide a different application name and re-run if required.", + "UpgradeInProgress": "An upgrade for the application '{0}' is already in progress." } } \ No newline at end of file diff --git a/Tasks/ServiceFabricComposeDeployV0/task.loc.json b/Tasks/ServiceFabricComposeDeployV0/task.loc.json index 390555692a48..89716eb73f34 100644 --- a/Tasks/ServiceFabricComposeDeployV0/task.loc.json +++ b/Tasks/ServiceFabricComposeDeployV0/task.loc.json @@ -16,8 +16,8 @@ "author": "Microsoft Corporation", "version": { "Major": 0, - "Minor": 2, - "Patch": 6 + "Minor": 3, + "Patch": 0 }, "demands": [ "Cmd" @@ -133,6 +133,15 @@ "groupName": "registry", "visibleRule": "registryCredentials = UsernamePassword" }, + { + "name": "upgrade", + "type": "boolean", + "label": "ms-resource:loc.input.label.upgrade", + "defaultValue": false, + "required": false, + "helpMarkDown": "ms-resource:loc.input.help.upgrade", + "groupName": "advanced" + }, { "name": "deployTimeoutSec", "type": "string", @@ -177,12 +186,16 @@ "ApplicationRemoved": "ms-resource:loc.messages.ApplicationRemoved", "EncryptingPassword": "ms-resource:loc.messages.EncryptingPassword", "CreatingApplication": "ms-resource:loc.messages.CreatingApplication", + "UpgradingApplication": "ms-resource:loc.messages.UpgradingApplication", "WaitingForDeploy": "ms-resource:loc.messages.WaitingForDeploy", + "WaitingForUpgrade": "ms-resource:loc.messages.WaitingForUpgrade", "CurrentStatus": "ms-resource:loc.messages.CurrentStatus", "DeployFailed": "ms-resource:loc.messages.DeployFailed", + "UpgradeFailed": "ms-resource:loc.messages.UpgradeFailed", "CheckingComposeFile": "ms-resource:loc.messages.CheckingComposeFile", "UnsupportedAPIVersion": "ms-resource:loc.messages.UnsupportedAPIVersion", "UsingAPIVersion": "ms-resource:loc.messages.UsingAPIVersion", - "InvalidApplicationNameWarning": "ms-resource:loc.messages.InvalidApplicationNameWarning" + "InvalidApplicationNameWarning": "ms-resource:loc.messages.InvalidApplicationNameWarning", + "UpgradeInProgress": "ms-resource:loc.messages.UpgradeInProgress" } } \ No newline at end of file diff --git a/Tasks/ServiceFabricComposeDeployV0/utilities.ps1 b/Tasks/ServiceFabricComposeDeployV0/utilities.ps1 index b5c05dec8699..18b3a88165bb 100644 --- a/Tasks/ServiceFabricComposeDeployV0/utilities.ps1 +++ b/Tasks/ServiceFabricComposeDeployV0/utilities.ps1 @@ -173,6 +173,75 @@ function New-ServiceFabricComposeApplicationHelper } } +function Start-ServiceFabricComposeDeploymentUpgradeHelper +{ + Param ( + [Parameter(Mandatory = $True)] + [string] + $ApiVersion, + + [Parameter(Mandatory = $True)] + [HashTable] + $UpgradeParameters + ) + + Start-ServiceFabricComposeDeploymentUpgrade @UpgradeParameters +} + +function Get-ServiceFabricComposeDeploymentUpgradeHelper +{ + Param ( + [Parameter(Mandatory = $True)] + [string] + $ApiVersion, + + [Parameter(Mandatory = $True)] + [HashTable] + $GetUpgradeParameters + ) + + $composeDeploymentUpgrade = Get-ServiceFabricComposeDeploymentUpgrade @GetUpgradeParameters + + if ($composeDeploymentUpgrade -eq $null) + { + return $null + } + + # Currently there is a bug in Get-ServiceFabricComposeDeploymentUpgrade so that it returns the wrong upgrade status when rolling back, need to get that information from Get-ServiceFabricApplicationUpgrade instead + $appUpgradeParameters = @{ + "ApplicationName" = $composeDeploymentUpgrade.ApplicationName + } + if ($GetUpgradeParameters['TimeoutSec']) + { + $appUpgradeParameters['TimeoutSec'] = $GetUpgradeParameters['TimeoutSec'] + } + $appUpgrade = Get-ServiceFabricApplicationUpgrade @appUpgradeParameters + + if ($appUpgrade -eq $null) + { + return $composeDeploymentUpgrade + } + + return @{ + "UpgradeState" = $appUpgrade.UpgradeState + "UpgradeStatusDetails" = $composeDeploymentUpgrade.UpgradeStatusDetails + } +} + +function IsUpgradeRunning +{ + Param ( + [Parameter(Mandatory = $True)] + [string] + $UpgradeState + ) + + return ($UpgradeState -ne 'Failed' -and ` + $UpgradeState -ne 'Invalid' -and ` + $UpgradeState -ne 'RollingForwardCompleted' -and ` + $UpgradeState -ne 'RollingBackCompleted') +} + function Test-ApplicationName { Param ( @@ -205,4 +274,4 @@ function Test-ApplicationName return } } -} +} \ No newline at end of file