118 lines
5.7 KiB
PowerShell
118 lines
5.7 KiB
PowerShell
function Remove-PackagesThatAreAlreadyInstalled {
|
|
<#
|
|
.SYNOPSIS
|
|
Given a list of packages, and a hashtable of packagename->unique-versions-of-package, return a list of packages
|
|
that actually need to be installed.
|
|
.PARAMETER PackagesToInstall
|
|
An array of packages to be installed
|
|
.PARAMETER PackageMetadata
|
|
The giant list of all the things from Classify Packages.
|
|
.PARAMETER DebugMetadata
|
|
Not used, but supplied from Classify Packages. Intentionally left here with the expectation of adding additional properties to it which might be passed through.
|
|
#>
|
|
[CmdletBinding()]
|
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("DebugMetadata", '', Justification="Intentionally left here with the expectation of adding additional properties to it which might be passed through.", Scope = "Function")]
|
|
param (
|
|
[array]$PackagesToInstall,
|
|
$PackageMetadata,
|
|
$DebugMetadata
|
|
)
|
|
|
|
if (Test-IsCollectionNullOrEmpty $PackagesToInstall) {
|
|
return @()
|
|
}
|
|
|
|
# Declare a hashtable to track which packages we are going to preserve from the install list.
|
|
$packagesToKeep = @{ }
|
|
|
|
# Cache the combinations of serversToInstall so we don't recreate them / resize arrays thousands of times.
|
|
$serversToInstallCache = @{}
|
|
|
|
# Filter packages to be installed by what is installed in the environment.
|
|
foreach ($package in $PackagesToInstall) {
|
|
$lowerName = $package.Name.ToLower()
|
|
$packageIsInstalled = $PackageMetadata.PackageToVersions.ContainsKey($lowerName)
|
|
|
|
$packageIsInUninstallList = ($PackageMetadata.WebPackagesToUninstall.Name -contains $package.Name) -or ($PackageMetadata.AppPackagesToUninstall.Name -contains $package.Name)
|
|
|
|
# Install the package if it's not installed at all.
|
|
if (!$packageIsInstalled) {
|
|
$packagesToKeep[$lowerName] = $true
|
|
continue
|
|
}
|
|
|
|
# Install the package if it is in either uninstall list
|
|
# Case 1 - Uninstalling from App to Install on Web in the case of a misplaced widget
|
|
# Case 2 - Forcing an uninstall/reinstall - maybe the wrong version got installed or partly installed
|
|
if ($packageIsInUninstallList) {
|
|
$packagesToKeep[$lowerName] = $true
|
|
continue
|
|
}
|
|
|
|
# Otherwise figure out if we need to install/force-reinstall the package.
|
|
# Get the different versions of the package on-hand.
|
|
[array]$versionsOfPackage = $PackageMetadata.PackageToVersions[$lowerName]
|
|
|
|
# We are reinstalling ORB
|
|
if ($PackageMetadata.ForceReinstallPackages) {
|
|
# If it's a package type that is reinstalled with ORB, or must reinstall for the same version of the package, keep the package.
|
|
if ($package.ReinstallWithORB -or $package.ForceSameVersion) {
|
|
$packagesToKeep[$lowerName] = $true
|
|
continue
|
|
}
|
|
}
|
|
|
|
# If there are multiple versions of the package installed, keep the package.
|
|
# Hopefully this will standardize that same version everywhere.
|
|
if ($versionsOfPackage.Count -gt 1) {
|
|
$packagesToKeep[$lowerName] = $true
|
|
continue
|
|
}
|
|
|
|
# Otherwise if there is one version of the package, keep it only if it is NOT the version we are trying to install.
|
|
if ($packageIsInstalled -and ($versionsOfPackage.Count -eq 1) -and ($versionsOfPackage[0] -ne $package.Version)) {
|
|
$packagesToKeep[$lowerName] = $true
|
|
continue
|
|
}
|
|
|
|
# Make sure that this package is on all of the servers its supposed to be installed on.
|
|
# Produce the combination of servers that the package needs to be installed to.
|
|
# Cache the combinations of serversToInstall so that we don't recreate them thousands of times.
|
|
$serversToInstallKey = 1 * [int]($package.InstallToWeb) +
|
|
2 * [int]($package.InstallToFab) +
|
|
4 * [int]($package.InstallToMic) +
|
|
8 * [int]($package.InstallToApp)
|
|
if($serversToInstallCache.ContainsKey($serversToInstallKey)) {
|
|
$serversToInstall = $serversToInstallCache[$serversToInstallKey]
|
|
} else {
|
|
$serversToInstall = @()
|
|
if($package.InstallToWeb) { $serversToInstall += $PackageMetadata.WebServers; }
|
|
if($package.InstallToFab) { $serversToInstall += $PackageMetadata.FabServers; }
|
|
if($package.InstallToMic) { $serversToInstall += $PackageMetadata.MicServers; }
|
|
if($package.InstallToApp) { $serversToInstall += $PackageMetadata.AppServers; }
|
|
$serversToInstall = $serversToInstall | Where-Object { $null -ne $_ }
|
|
$serversToInstallCache[$serversToInstallKey] = $serversToInstall
|
|
}
|
|
|
|
# If the package is not installed on all of the servers it should be installed on, then keep the package.
|
|
$installedServers = $PackageMetadata.PackageToServers[$lowerName]
|
|
$installedToAllServers = $true
|
|
foreach($server in $serversToInstall) {
|
|
if($installedServers -notcontains $server) {
|
|
$installedToAllServers = $false
|
|
break
|
|
}
|
|
}
|
|
if(!$installedToAllServers -or $packageIsInUninstallList) {
|
|
$packagesToKeep[$lowerName] = $true
|
|
continue
|
|
}
|
|
|
|
Write-Host "Package $($package.Name) is already installed on all servers. Removing from list of packages to deploy"
|
|
# Now only packages we care to install/reinstall are in $packagesToKeep!
|
|
}
|
|
|
|
# Filter the install packages down to the packages we intend on keeping.
|
|
[array]$PackagesToInstall = $PackagesToInstall | Where-Object { $packagesToKeep.ContainsKey($_.Name.ToLower()) }
|
|
return $PackagesToInstall
|
|
} |