ps/Modules/Alkami.DevOps.Installation/Public/Get-ServerPackageInformation.ps1

314 lines
17 KiB
PowerShell
Raw Permalink Normal View History

2023-05-30 22:51:22 -07:00
function Get-ServerPackageInformation {
<#
.SYNOPSIS
The bulk of the Classify logic. Determines what versions of which packages get installed. Utilized by Classify-Packages.
.PARAMETER PackageMetadata
Packages object to populate.
.PARAMETER DebugMetadata
Meta object used to determine what goes where.
.PARAMETER BuildCheckoutDirectory
Directory where the code is checked out by TC. Passed through.
.PARAMETER AwsProfileName
Profile name to get information from AWS.
.PARAMETER UseV2PackageMetadata
Whether or not to use the new version of the PackageMetadata functions. Passed through.
.PARAMETER DependencyReleaseValue
The value of the orb release being classified. Passed through.
#>
[CmdletBinding()]
param(
[Parameter (Mandatory = $true)]
[PSObject]$PackageMetadata,
[Parameter (Mandatory = $true)]
[PSObject]$DebugMetadata,
[Parameter (Mandatory = $true)]
[string]$BuildCheckoutDirectory,
[Parameter (Mandatory = $true)]
[string]$AwsProfileName,
[Parameter (Mandatory = $true)]
[System.Management.Automation.PSCredential]$NugetCredential,
[switch]$UseV2PackageMetadata,
[Parameter (Mandatory = $true)]
[string]$DependencyReleaseValue
)
# These were set outside of the region this function came from, but are used only in this function. Nothing happens to the
# underlying data between when they were set and when this function was called, so declare them here instead.
# TODO: Consider moving these values to DebugMetadata
$webInstallNames = $PackageMetadata.WebPackagesToInstall.Name
$webUninstallNames = $PackageMetadata.WebPackagesToUninstall.Name
$appInstallNames = $PackageMetadata.AppPackagesToInstall.Name
$appUninstallNames = $PackageMetadata.AppPackagesToUninstall.Name
Write-Host "##teamcity[blockOpened name='Gather Information']"
$PackageMetadata = Get-EnvironmentData -packageMetadata $PackageMetadata
# Construct a map of server -> packages installed on that server.
$serverToPackages = @{}
foreach ($server in $PackageMetadata.ServersToQuery) {
# TODO ~ Fix this to not need the !StartsWith part
# ~ Relies on the package classification being right. We can just remove all SREModule types.
$serverToPackages[$server] = (Get-InstalledPackages -ComputerName $server).Where({ !$_.Name.StartsWith("Alkami.Installer") })
}
#region Filter existing packages by servertype
# Get the packages from each type of server.
if ($PackageMetadata.HasWebServers) {
$packages = @()
foreach ($server in $PackageMetadata.WebServers) {
$packages += @($serverToPackages[$server])
}
$DebugMetadata.WebServerPackages = @(Select-UniqueServerPackages $packages)
}
if ($PackageMetadata.HasAppServers) {
$packages = @()
foreach ($server in $PackageMetadata.AppServers) {
$packages += @($serverToPackages[$server])
}
$DebugMetadata.AppServerPackages = @(Select-UniqueServerPackages $packages)
}
if ($PackageMetadata.HasMicServers) {
$packages = @()
foreach ($server in $PackageMetadata.MicServers) {
$packages += @($serverToPackages[$server])
}
$DebugMetadata.MicServerPackages = @(Select-UniqueServerPackages $packages)
}
if ($PackageMetadata.HasFabServers) {
$packages = @()
foreach ($server in $PackageMetadata.FabServers) {
$packages += @($serverToPackages[$server])
}
$DebugMetadata.FabServerPackages = @(Select-UniqueServerPackages $packages)
}
#endregion Filter existing packages by servertype
#region Find all packages with multi-server-existing-version-mismatch for true-up
# Create a list of package name -> versions installed on each server.
# This gives a view of all of the versions of a particular package installed.
foreach ($serverPackages in $serverToPackages.Values) {
foreach ($package in $serverPackages) {
$packageNameLower = $package.Name.ToLower()
if (!$PackageMetadata.PackageToVersions.ContainsKey($packageNameLower)) {
$PackageMetadata.PackageToVersions[$packageNameLower] = @($package.Version)
} else {
$PackageMetadata.PackageToVersions[$packageNameLower] = $PackageMetadata.PackageToVersions[$packageNameLower] + $package.Version
}
}
}
# Limit the versions down to unique versions installed.
$packageToVersionsKeys = @() + $PackageMetadata.PackageToVersions.Keys; # So we aren't "changing" the keys of the map and breaking enumeration.
foreach ($key in $packageToVersionsKeys) {
$PackageMetadata.PackageToVersions[$key] = ($PackageMetadata.PackageToVersions[$key] | Select-Object -Unique)
}
#endregion Find all packages with multi-server-existing-version-mismatch for true-up
# Create a list of package names to servers the package is installed on.
# Also, when a FAB name is encountered, add the entire list of FAB servers.
foreach ($server in $serverToPackages.Keys) {
$serversToAdd = @($server)
if ($server -like "fab*") {
$serversToAdd = @($PackageMetadata.FabServers)
}
$serverPackages = $serverToPackages[$server]
foreach ($package in $serverPackages) {
$lowerName = $package.Name.ToLower()
if (!$PackageMetadata.PackageToServers.ContainsKey($lowerName)) {
$PackageMetadata.PackageToServers[$lowerName] = $serversToAdd
} else {
$PackageMetadata.PackageToServers[$lowerName] += $serversToAdd
}
}
}
#region Filter packages down to unique packages across the entire environment
$allWebTierPackages = (Select-UniqueServerPackages $DebugMetadata.WebServerPackages)
$allAppTierPackages = (Select-UniqueServerPackages (
@($DebugMetadata.AppServerPackages) +
@($DebugMetadata.MicServerPackages) +
@($DebugMetadata.FabServerPackages)
))
# Create a map of the packages getting installed from the job parameters. We need to know which packages came from the deploy params, and which from the servers.
if (!(Test-IsCollectionNullOrEmpty $PackageMetadata.WebPackagesToInstall)) {
foreach ($package in $PackageMetadata.WebPackagesToInstall) {
$DebugMetadata.WebPackagesToInstallMap[$package.Name.ToLower()] = $package
}
}
if (!(Test-IsCollectionNullOrEmpty $PackageMetadata.AppPackagesToInstall)) {
foreach ($package in $PackageMetadata.AppPackagesToInstall) {
$DebugMetadata.AppPackagesToInstallMap[$package.Name.ToLower()] = $package
}
}
#endregion Filter packages down to unique packages across the entire environment
#region Determine $all___TierPackageInstalls
if ($PackageMetadata.ForceReinstallPackages) {
# It's a full deploy. (This is an implicit reproduction of the .IsOrbDeploy flag. The two should probably be consolidated at some point.)
# Overwrite the packages from the environment with packages intended to be installed.
# This will leave us with a list of things we want installed, plus the things we might force-reinstall.
$allWebTierPackages = (Select-InstallPackages $allWebTierPackages $PackageMetadata.WebPackagesToInstall)
$allAppTierPackages = (Select-InstallPackages $allAppTierPackages $PackageMetadata.AppPackagesToInstall)
} else {
# Otherwise it's an element deploy.
# Filter down the list of packages to the ones that are being deployed.
$allWebTierPackages = $PackageMetadata.WebPackagesToInstall
$allAppTierPackages = $PackageMetadata.AppPackagesToInstall
}
#endregion Determine $all___TierPackageInstalls
#region Exclude chocolatey if present
if ($null -ne ($allWebTierPackages | Where-Object { $_.Name -eq "chocolatey" })) {
Write-Warning "The Chocolatey Package Manager Program package (chocolatey) was passed in to be installed on the Web Tier. At this time we explicitly dissallow that. It has been skipped."
}
if ($null -ne ($allAppTierPackages | Where-Object { $_.Name -eq "chocolatey" })) {
Write-Warning "The Chocolatey Package Manager Program package (chocolatey) was passed in to be installed on the App Tier. At this time we explicitly dissallow that. It has been skipped."
}
# Remove chocolatey from the install lists.
$allWebTierPackages = $allWebTierPackages | Where-Object { $_.Name -ne "chocolatey" }
$allAppTierPackages = $allAppTierPackages | Where-Object { $_.Name -ne "chocolatey" }
#endregion Exclude chocolatey if present
#region Remove PackagesToUninstall from all***TierPackages
#TODO: Independent filter here or add to Select-InstallPackages called from Line 636-637 ?
#TODO: OR Add to Get-PackageInstallationData in Alkami.Powershell.Choco called from 675-677 ?
#endregion Remove PackagesToUninstall from all***TierPackages
$buildMappingArgs = @{
AllAppTierPackages = $allAppTierPackages
AllWebTierPackages = $allWebTierPackages
BuildCheckoutDirectory = $BuildCheckoutDirectory
DebugMetadata = $DebugMetadata
NugetCredential = $NugetCredential
PackageMetadata = $PackageMetadata
UseV2PackageMetadata = $UseV2PackageMetadata
DependencyReleaseValue = $DependencyReleaseValue
}
$PackageMetadata,$DebugMetadata = Get-PackageServerMapping @buildMappingArgs
$PackageMetadata = Get-BadPackages -DebugMetadata $DebugMetadata -PackageMetadata $PackageMetadata
# Strip out empty/null entries. Follow up/remove with SRE-17113. Suggestion for debugging; move this block around and see where it fails
[array]$PackageMetadata.WebPackagesToInstall = $PackageMetadata.WebPackagesToInstall.Where({$null -ne $_})
[array]$PackageMetadata.AppPackagesToInstall = $PackageMetadata.AppPackagesToInstall.Where({$null -ne $_})
[array]$PackageMetadata.MicPackagesToInstall = $PackageMetadata.MicPackagesToInstall.Where({$null -ne $_})
#region Doublecheck force-reinstall
# Keep only the packages that need to be force reinstalled, or that came from the install parameters.
if ($PackageMetadata.ForceReinstallPackages) {
$PackageMetadata.WebPackagesToInstall = $PackageMetadata.WebPackagesToInstall | Where-Object {
# Where package exists on a server, and will be deleted (ie: widget), but isn't in either of our lists.
(($_.ForceSameVersion -and ($webUninstallNames -inotcontains $_.Name -and $webInstallNames -inotcontains $_.Name))) -or
# Packages we're installing for some reason decided upon above.
($DebugMetadata.WebPackagesToInstallMap.ContainsKey($_.Name.ToLower())) }
$PackageMetadata.AppPackagesToInstall = $PackageMetadata.AppPackagesToInstall | Where-Object {
(($_.ForceSameVersion -and ($appUninstallNames -inotcontains $_.Name -and $appInstallNames -inotcontains $_.Name))) -or
# Packages we're installing for some reason decided upon above.
($DebugMetadata.AppPackagesToInstallMap.ContainsKey($_.Name.ToLower())) }
}
#endregion Doublecheck force-reinstall
#region Remove packages from the install lists that do not need to be needlessly re-installed.
Write-Host ("##teamcity[blockOpened name='Removing Already-Installed Packages']")
# Web/App package arrays here are getting null entries from *mumble mumble* somewhere...
# cut out the nulls before passing it along.
if (!(Test-IsCollectionNullOrEmpty $PackageMetadata.WebPackagesToInstall)) {
$packagesToInstall = @()
foreach($package in $PackageMetadata.WebPackagesToInstall){
if($null -ne $package){
$packagesToInstall += $package
}
}
$PackageMetadata.WebPackagesToInstall = (Remove-PackagesThatAreAlreadyInstalled -packagesToInstall $packagesToInstall -packageMetadata $PackageMetadata -debugMetadata $DebugMetadata)
}
if (!(Test-IsCollectionNullOrEmpty $PackageMetadata.AppPackagesToInstall)) {
$packagesToInstall = @()
foreach($package in $PackageMetadata.AppPackagesToInstall){
if($null -ne $package){
$packagesToInstall += $package
}
}
$PackageMetadata.AppPackagesToInstall = (Remove-PackagesThatAreAlreadyInstalled -packagesToInstall $packagesToInstall -packageMetadata $PackageMetadata -debugMetadata $DebugMetadata)
}
# $PackageMetadata.WebPackagesToInstall = (Remove-PackagesThatAreAlreadyInstalled -packagesToInstall $PackageMetadata.WebPackagesToInstall -packageMetadata $PackageMetadata -debugMetadata $DebugMetadata)
# $PackageMetadata.AppPackagesToInstall = (Remove-PackagesThatAreAlreadyInstalled -packagesToInstall $PackageMetadata.AppPackagesToInstall -packageMetadata $PackageMetadata -debugMetadata $DebugMetadata)
Write-Host ("##teamcity[blockClosed name='Removing Already-Installed Packages']")
#endregion Remove packages from the install lists that do not need to be needlessly re-installed.
#region Gather AWS settings from a sample server
# Had to re-obtain this value here when functionalizing classify.
$serverToQuery = $packageMetadata.ServersToQuery | Select-Object -First 1
# Grab data from first server available
$awsSettings = Get-AwsSettings -serverToTest $serverToQuery -profileName $AwsProfileName
$PackageMetadata.AwsSettings = $awsSettings
#endregion Gather AWS settings from a sample server
#region Separate App-Mic/Fab installs and uninstalls.
# Separate out the mic/fab installs from the app installs.
[array]$PackageMetadata.MicPackagesToInstall = $PackageMetadata.AppPackagesToInstall | Where-Object { $_.InstallToMic -or $_.InstallToFab }
[array]$PackageMetadata.AppPackagesToInstall = $PackageMetadata.AppPackagesToInstall | Where-Object { $_.InstallToApp }
$newAppUninstalls = @()
$newMicUninstalls = @()
foreach($package in $PackageMetadata.AppPackagesToUninstall) {
$packageInstalledOnServers = $PackageMetadata.PackageToServers[$package.Name]
$installedOnAppServers = $null -ne (Select-AlkamiAppServers -servers $packageInstalledOnServers)
$installedOnMicServers = ($null -ne (Select-AlkamiMicServers -servers $packageInstalledOnServers)) -or
($null -ne (Select-AlkamiFabServers -servers $packageInstalledOnServers))
if($installedOnAppServers) {
$newAppUninstalls += $package
}
if($installedOnMicServers) {
$newMicUninstalls += $package
}
}
$PackageMetadata.AppPackagesToUninstall = $newAppUninstalls
$PackageMetadata.MicPackagesToUninstall = $newMicUninstalls
# Add the bad packages to uninstall to the uninstall lists.
# This must happen underneath the app/mic uninstall separation, so we don't remove a valid package from a mic/app server.
# This preserves explicit package uninstalls, but allows for specific removal of bad packages.
if (!(Test-IsCollectionNullOrEmpty $PackageMetadata.BadWebPackagesToUninstall)) { $PackageMetadata.WebPackagesToUninstall += $PackageMetadata.BadWebPackagesToUninstall; }
if (!(Test-IsCollectionNullOrEmpty $PackageMetadata.BadAppPackagesToUninstall)) { $PackageMetadata.AppPackagesToUninstall += $PackageMetadata.BadAppPackagesToUninstall; }
if (!(Test-IsCollectionNullOrEmpty $PackageMetadata.BadMicPackagesToUninstall)) { $PackageMetadata.MicPackagesToUninstall += $PackageMetadata.BadMicPackagesToUninstall; }
#endregion Separate Mic/Fab installs/uninstalls.
$packageMetadata, $debugMetadata = Add-OldHotfixPackagesToUninstallList -DependencyReleaseValue $DependencyReleaseValue -PackageMetadata $packageMetadata -DebugMetadata $debugMetadata
#region Final determination of what types of installs we are doing
$PackageMetadata.HasWebInstalls = !(Test-IsCollectionNullOrEmpty $PackageMetadata.WebPackagesToInstall)
$PackageMetadata.HasWebUninstalls = !(Test-IsCollectionNullOrEmpty $PackageMetadata.WebPackagesToUninstall)
$PackageMetadata.HasAppInstalls = !(Test-IsCollectionNullOrEmpty $PackageMetadata.AppPackagesToInstall)
$PackageMetadata.HasAppUninstalls = !(Test-IsCollectionNullOrEmpty $PackageMetadata.AppPackagesToUninstall)
$PackageMetadata.HasMicInstalls = !(Test-IsCollectionNullOrEmpty $PackageMetadata.MicPackagesToInstall)
$PackageMetadata.HasMicUninstalls = !(Test-IsCollectionNullOrEmpty $PackageMetadata.MicPackagesToUninstall)
#endregion Final determination of what types of installs we are doing
return $PackageMetadata, $DebugMetadata
Write-Host ("##teamcity[blockClosed name='Gather Information']")
}