168 lines
9.4 KiB
PowerShell
168 lines
9.4 KiB
PowerShell
|
function Install-AlkamiServiceFabricPackages {
|
|||
|
<#
|
|||
|
.SYNOPSIS
|
|||
|
Deploys Microservice Packages to the Service Fabric cluster.
|
|||
|
.PARAMETER packages
|
|||
|
Package objects for the packages to be deployed to the cluster.
|
|||
|
.PARAMETER hostname
|
|||
|
The host name of any server in the Service Fabric cluster.
|
|||
|
.PARAMETER defaultLogConfigFolder
|
|||
|
SOURCE folder for default log4net configs
|
|||
|
.PARAMETER nugetCredential
|
|||
|
Credential used to authenticate with Proget server
|
|||
|
.PARAMETER HealthCheckStableDurationSec
|
|||
|
Amount of time after 1st successful HC to require continuing successful HCs
|
|||
|
See: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-application-upgrade-parameters
|
|||
|
.PARAMETER HealthCheckRetryTimeoutSec
|
|||
|
Max time to keep waiting for successful HC before failing Upgrade
|
|||
|
See: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-application-upgrade-parameters
|
|||
|
#>
|
|||
|
[CmdletBinding()]
|
|||
|
Param(
|
|||
|
[Parameter(Mandatory = $true)]
|
|||
|
[Alias("PackagesToPublish")]
|
|||
|
[AllowNull()]
|
|||
|
[object[]]$packages,
|
|||
|
|
|||
|
[Parameter(Mandatory = $true)]
|
|||
|
[Alias("s")]
|
|||
|
[string]$hostname,
|
|||
|
|
|||
|
[Parameter(Mandatory = $false)]
|
|||
|
[string]$defaultLogConfigFolder = $null,
|
|||
|
[Parameter(Mandatory = $false)]
|
|||
|
[pscredential]$nugetCredential = $null,
|
|||
|
|
|||
|
[Parameter(Mandatory = $false)]
|
|||
|
[Int32]$HealthCheckStableDurationSec = 120,
|
|||
|
|
|||
|
[Parameter(Mandatory = $false)]
|
|||
|
[Int32]$HealthCheckRetryTimeoutSec = 600
|
|||
|
)
|
|||
|
|
|||
|
$loglead = Get-LogLeadName;
|
|||
|
|
|||
|
# Arrange the subscription service and broker to the front of the packages list if they exist.
|
|||
|
$packages = ($packages | Sort-Object -Property @{Expression={ $Global:InfrastructureMicroServices -contains $_.Name }} -Descending);
|
|||
|
|
|||
|
# Remove microservice installers from the list.
|
|||
|
$packages = $packages | Where-Object { !(Test-IsPackageInstaller -packageName $_.Name) };
|
|||
|
|
|||
|
# Write out the packages being installed.
|
|||
|
Write-Verbose "$loglead Now installing:";
|
|||
|
foreach($package in $packages) {
|
|||
|
Write-Verbose "$($package.Name) - $($package.Version)";
|
|||
|
}
|
|||
|
|
|||
|
# Set feeds to packages if they are not already there.
|
|||
|
Set-ChocoPackageSourceFeeds -packages $packages -hostname $hostname -Verbose;
|
|||
|
|
|||
|
# Connect to SF cluster.
|
|||
|
Connect-AlkamiServiceFabricCluster -hostname $hostname | Out-Null;
|
|||
|
|
|||
|
# Get the environment name, and clean it up.
|
|||
|
$environmentName = Get-AppSetting -appSettingKey "Environment.Name" -ComputerName $hostname;
|
|||
|
|
|||
|
# Stage all packages, which it only does fully if they aren't already staged.
|
|||
|
Write-Host "$loglead : Staging $($packages.Count) packages.";
|
|||
|
if ([String]::IsNullOrEmpty($defaultLogConfigFolder)) {
|
|||
|
|
|||
|
Publish-AlkamiServiceFabricPackages -packages $packages -hostname $hostname -nugetCredential $NugetCredential
|
|||
|
} else {
|
|||
|
|
|||
|
Write-Host "defaultLogConfigFolder: <$defaultLogConfigFolder>"
|
|||
|
Publish-AlkamiServiceFabricPackages -packages $packages -hostname $hostname -defaultLogConfigFolder $defaultLogConfigFolder -nugetCredential $NugetCredential
|
|||
|
}
|
|||
|
|
|||
|
# Deploy all the packages.
|
|||
|
Write-Host "$loglead : Deploying $($packages.Count) packages.";
|
|||
|
foreach($package in $packages) {
|
|||
|
$packageString = "$($package.Name).$($package.Version)";
|
|||
|
$packageSource = $package.Feed.Source;
|
|||
|
$isReliableService = Test-IsPackageReliableService -feedSource $packageSource -name $package.Name -version $package.Version -Credential $NugetCredential -Verbose
|
|||
|
|
|||
|
# Determine application name and application type name.
|
|||
|
$applicationName = $null;
|
|||
|
$applicationTypeName = $null;
|
|||
|
if($isReliableService) {
|
|||
|
# The application type name -must- be the name of the class that implements the reliable service contract.
|
|||
|
# Pull this name from the manifest located inside the package.
|
|||
|
$applicationTypeName = Get-AlkamiServiceFabricPackageServiceTypeName -source $packageSource -name $package.Name -version $package.Version -nugetCredential $NugetCredential;
|
|||
|
|
|||
|
# Reliable services are not tied to specific environments.
|
|||
|
$applicationName = Format-AlkamiServiceFabricApplicationName -name $applicationTypeName -version $package.Version;
|
|||
|
} else {
|
|||
|
# For normal microservices the application type name is environment tied, and the application name matches the service name.
|
|||
|
$applicationName = Format-AlkamiServiceFabricApplicationName -name $package.Name -version $package.Version -environmentName $environmentName;
|
|||
|
$applicationTypeName = Format-AlkamiServiceFabricApplicationName -name $package.Name -environmentName $environmentName; # No version
|
|||
|
}
|
|||
|
$applicationPath = "fabric:/$applicationName";
|
|||
|
|
|||
|
# Figure out if we need to create a new application, or an upgrade.
|
|||
|
$application = (Get-ServiceFabricApplication -ApplicationName $applicationPath);
|
|||
|
|
|||
|
$updateAffinity = $true;
|
|||
|
$isNewApplication = $false;
|
|||
|
if(!($application)) {
|
|||
|
Write-Host "$loglead : Application $($package.Name) has never been deployed! Deploying.";
|
|||
|
$isNewApplication = $true;
|
|||
|
New-ServiceFabricApplication -ApplicationName $applicationPath -ApplicationTypeName $applicationTypeName -ApplicationTypeVersion $package.Version
|
|||
|
} elseif($application.ApplicationTypeVersion -ne $package.Version) {
|
|||
|
Start-ServiceFabricApplicationUpgrade -ApplicationName $applicationPath -ApplicationTypeVersion $package.Version -Monitored -FailureAction Rollback -Force -UpgradeReplicaSetCheckTimeoutSec 15 -HealthCheckStableDurationSec $HealthCheckStableDurationSec -HealthCheckRetryTimeoutSec $HealthCheckRetryTimeoutSec
|
|||
|
Write-Host "$loglead : Application $($package.Name) is running in the cluster on version $($application.ApplicationTypeVersion). Rolling out version $($package.Version).";
|
|||
|
} else {
|
|||
|
$updateAffinity = $false;
|
|||
|
Write-Host "$loglead : Application $packageString is already deployed on the cluster. Skipping.";
|
|||
|
}
|
|||
|
|
|||
|
# Set affinity to the subscription service.
|
|||
|
# Only set affinity on the non-infra services. Affinity can't be set on services that run everywhere without errors.
|
|||
|
if($updateAffinity -and ($null -eq ($Global:InfrastructureMicroServices | Where-Object { $_ -eq $package.name; }))) {
|
|||
|
Write-Verbose "$loglead : Setting Affinity to the Subscription Service";
|
|||
|
|
|||
|
# Only query for the subscription service once. This only matters if the subscription service is not yet deployed.
|
|||
|
if($null -eq $subscriptionService) {
|
|||
|
# Query for the subscription service app in SF.
|
|||
|
# Grab all apps and wildcard search because we don't know what major version might be running, and SF doesn't do partial searches.
|
|||
|
Write-Verbose "$loglead : Searching for subscription service application name in the cluster.";
|
|||
|
$subscriptionAppName = (Format-AlkamiServiceFabricApplicationName -name $Global:SubscriptionServiceFabricName -environmentName $environmentName);
|
|||
|
$subscriptionAppNameUri = "fabric:/$($subscriptionAppName)*";
|
|||
|
$subscriptionApplication = (Get-ServiceFabricApplication | Where-Object { $_.ApplicationName -like $subscriptionAppNameUri} | Select-Object -First 1);
|
|||
|
if($null -ne $subscriptionApplication) {
|
|||
|
$subscriptionService = Get-ServiceFabricService -ApplicationName $subscriptionApplication.ApplicationName;
|
|||
|
}
|
|||
|
if($null -eq $subscriptionService) {
|
|||
|
Write-Verbose "$loglead : Could not find subscription service to set affinity to.";
|
|||
|
} else {
|
|||
|
Write-Verbose "$loglead : Found $($subscriptionService.ServiceName)";
|
|||
|
}
|
|||
|
}
|
|||
|
if($null -ne $subscriptionService) {
|
|||
|
$affinity = "NonAlignedAffinity";
|
|||
|
$affinityRules = @("$($subscriptionService.ServiceName),$affinity");
|
|||
|
|
|||
|
# Set affinity for every service in the application that was just deployed.
|
|||
|
$services = Get-ServiceFabricService -ApplicationName $applicationPath;
|
|||
|
foreach($service in $services) {
|
|||
|
Update-ServiceFabricService -Stateless -ServiceName $service.ServiceName -Correlation $affinityRules -Force;
|
|||
|
}
|
|||
|
Write-Verbose "$loglead : Affinity update complete.";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
# If we deployed a new major version, instead of an upgrade of an existing major version, there will be multiple applications running.
|
|||
|
# Remove every major version of the application that is not the version we just deployed.
|
|||
|
if($isNewApplication) {
|
|||
|
$runningApplications = Get-AlkamiServiceFabricApplications -ComputerName $hostname -Name $package.Name;
|
|||
|
$oldApplications = $runningApplications | Where-Object { $_.Version -ne $package.Version };
|
|||
|
if(!(Test-IsCollectionNullOrEmpty $oldApplications)) {
|
|||
|
Write-Host "$loglead : New major version is deployed. Removing other major versions.";
|
|||
|
foreach($application in $oldApplications) {
|
|||
|
Write-Host "$loglead : Removing $($application.Name) $($application.Version) from cluster.";
|
|||
|
Remove-ServiceFabricApplication -ApplicationName $($application.ServiceFabricApplicationName) -Force;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|