ps/Modules/Alkami.PowerShell.Common/Public/Get-NewRelicApmUpgradeData.ps1

280 lines
12 KiB
PowerShell
Raw Permalink Normal View History

2023-05-30 22:51:22 -07:00
function Get-NewRelicApmUpgradeData {
<#
.SYNOPSIS
Compares the current version of NewRelic APM to the expected version, and returns an object describing if an upgrade or downgrade is required.
.DESCRIPTION
Compares the current version of NewRelic APM to the expected version, and returns an object describing if an upgrade or downgrade is required. Uses either
the supplied desired version value OR the calculated value based on the deployed ORB version, if applicable.
.PARAMETER DesiredAPMVersion
Optional parameter indicating the desired APM version. When not supplied, will calculate the desired version based on deployed ORB version
.PARAMETER SourceFeed
Optional parameter. If supplied, should be the full soruce URL for the desired Chocolatey feed to pull the newrelic-dotnet package froms
.PARAMETER NewRelicPackageName
Optional parameter, defaults to "newrelic-dotnet". Should be set to the NewRelic APM MSI-based chocolatey package you want to install
.OUTPUTS
An object which contains the below properties
- ActionRequired [Boolean] : Indicates if an upgrade or downgrade is required
- ActionType [String] : Value should be one of Upgrade or Downgrade
- TargetVersion [System.Version] : The dervied version for install
- SourceFeed [String] : The feed URL which should be used for install
.Example
e
#>
[CmdletBinding()]
[OutputType([System.Object])]
param(
[Parameter(Mandatory = $false)]
[System.Version]$DesiredAPMVersion = $null,
[Parameter(Mandatory = $false)]
[string]$SourceFeed = $null,
[Parameter(Mandatory = $false)]
[string]$NewRelicPackageName = "newrelic-dotnet"
)
#TODO: Add -ComputerName to allow remote-running this?
$alkamiFeedMatch = "http?://packagerepo.orb.alkamitech.com/nuget/choco.*"
$alkamiFeedBlockExpression = "choco.sre|choco.internal"
$logLead = Get-LogLeadName
$hostname = Get-FullyQualifiedServerName
$newrelicApmUpgradelData = @{
ComputerName = $hostname
ActionRequired = $false
ActionType = $null
TargetVersion = $null
FeedUrl = $null
FoundPackage = $null
}
$takeAction = $null
if (Test-StringIsNullOrEmpty -Value $DesiredAPMVersion) {
# No target version was supplied, lets see if we can figure it out from what's deployed
Write-Verbose "$logLEad : No DesiredAPMVersion supplied. Will attempt to determine target version based on deployed platform version"
$deployedPlatformVersion = Get-OrbVersion
if (-NOT (Test-StringIsNullOrEmpty -Value $deployedPlatformVersion)) {
$targetAPMVersion = Get-SupportedPlatformAPMVersion -PlatformVersion $deployedPlatformVersion
}
} else {
# Lets assume the person calling the function knows what they want
$targetAPMVersion = $DesiredAPMVersion
}
if ($null -eq $targetAPMVersion) {
# Since no version was supplied, we will use the latest on the feed. This may be the case for non-ORB servers where they just want whatever
# is appropriate, and not a specific version
Write-Host "$logLead : Could not determine the appropriate target APM version. The latest version in the configured feeds will be used"
}
# Print what we're going to compare against
$targetVersionString = Test-IsNull $targetAPMVersion "LATEST AVAILABLE" -Strict
Write-Host "$logLead : Evaluating current state vs. desired APM version [$targetVersionString]"
# Get the local NewRelic APM version
$localChoco = Get-ChocoState -LocalOnly -Exact -PackageName $NewRelicPackageName
if ($null -eq $localChoco) {
Write-Host "$logLead : No local NewRelic APM choco package detected."
} else {
$localChocoVersion = $localChoco.Version
Write-Host "$logLead : Detected local NewRelic APM choco package version: [$localChocoVersion]"
}
# Figure out where we're installing NewRelic APM from, if not supplied by the caller
#region FindPackage
[hashtable]$foundPackage = @{
PackageId = $null
PackageVersion = $null
Source = $null
FeedUrl = $null
}
if (Test-StringIsNullOrEmpty -Value $SourceFeed) {
# Pull the local feeds matching $alkamiFeedMatch
#[array]$sources = Get-ChocolateySources | Where-Object {
# $_.Source -like $alkamiFeedMatch -and
# [bool]$_.IsSDK -eq $false -and
# [bool]$_.Disabled -eq $false
#}
[array]$sources = (Get-ChocolateySources).Where({
$_.Source -like $alkamiFeedMatch -and
[bool]$_.IsSDK -eq $false -and
[bool]$_.Disabled -eq $false -and
$_.Source -notmatch $alkamiFeedBlockExpression
})
if (Test-IsCollectionNullOrEmpty -Collection $sources) {
# (/) TESTCASE - Get-ChocolateySources - return hashtable with 1 item that has a .Source member
# https://packagerepo.orb.alkamitech.com/nuget/choco.sre
# should write this warning and eventually return a ActionRequired=$false object
# No matching choco sources found. We have to exit early
Write-Warning "$logLead : Could not find a configured feed which matches the requirements for NewRelic APM. Evaluation cannot continue"
$takeAction = $false
} else {
#TESTCASE - Get-ChocolateySources - return hashtable with 1 item that has a .Source member
# https://packagerepo.orb.alkamitech.com/nuget/choco.good
# should write this verbose and call Get-ChocoState and more
# Find the feed with NewRelic APM
foreach ($feedSource in $sources) {
Write-Verbose "$logLead : Checking source with name [$($feedSource.Name)] and Feed URL [$($feedSource.Source)]"
# In order to not overwrite this value, we CONTINUE once found
# Get-ChocoState returns an array, even though we often only get 1 result
# sometimes powershell unboxes for us, sometimes it doesn't
# Take no changes, force the Select-Object -First 1 anyway
$availableChocoPackageList = Get-ChocoState -Exact -PackageName $NewRelicPackageName -PackageVersion $targetAPMVersion -Source $feedSource.Source -ErrorAction Continue
$availableChocoPackage = Select-Object -InputObject $availableChocoPackageList -First 1
if ($null -eq $availableChocoPackage -or (Test-IsCollectionNullOrEmpty -Collection $availableChocoPackage)) {
Write-Host "$logLead : Package $NewRelicPackageName not found at feed [$($feedSource.Source)]."
} else {
Write-Host "$logLead : Package $NewRelicPackageName found at $($feedSource.Source). Adding this package with this source to the list"
# The first found package is enough, even if there are other versions on other feeds
# I know Source and FeedUrl are redundant. It is convenient.
$packageSource = $feedSource.Source
$foundPackage.PackageId = $availableChocoPackage.Name
$foundPackage.PackageVersion = [Version]($availableChocoPackage.Version)
$foundPackage.Source = $feedSource
$foundPackage.FeedUrl = $feedSource.Source
continue
}
}
if ($null -eq $packageSource) {
Write-Host "$logLead : No configured feed has package $NewRelicPackageName available. Evaluation cannot continue."
$takeAction = $false
}
}
}
#endregion FindPackage
# Now the Version Comparison
#region CompareVersions
# Compare-Semver shorthand
# -1 -> first value TRAILS/IS LESS THAN second value
# 0 -> values are equal
# +1 -> first value LEADS/IS MORE THAN second value
# SO
# -1 = should upgrade
# 0 = do nothing
# 1 = should downgrade
$actions = @{
-1 = "Upgrade"
0 = "Nothing"
1 = "Downgrade"
}
if ($takeAction -eq $false) {
Write-Warning "$loglead : Skipping version comparison due to previous condition preventing action"
$actionValue = 0
} else {
Write-Host "$loglead : Comparing versions to determine what action to take"
# OK so we have a local NewRelic version already.
if ($null -ne $localChocoVersion) {
#region Have Local Installation
# we don't really *need* this if-else....
# both of them use the $foundPackage anyway because we added -Version
# to Get-ChocoState and we need whatever we found to be installed....
# so figure out how to not have this `if ($null -eq $targetAPMVersion)` - go off of $foundPackage
# instead
# The insides are basically teh same anyway, right?
# The Write-Hosts are subtly different, but... uh... do we really need them?
if ($null -eq $targetAPMVersion) {
# But we don't have a specific target version. So we need to upgrade/downgrade to the latest, if it's different
$actionValue = Compare-SemVer -Version1 $localChocoVersion -Version2 $foundPackage.PackageVersion
if ($actionValue -ne 0) {
Write-Host "$logLead : A(n) $($actions[$actionValue]) is required because local choco version [$localChocoVersion] is not equivalent to the highest available version on the feeds [$($foundPackage.PackageVersion)]."
$takeAction = $true
$targetAPMVersion = $foundPackage.PackageVersion
} else {
Write-Host "$logLead : A(n) $($actions[$actionValue]) is not required because local choco version [$localChocoVersion] is equivalent to the highest available version on the feeds [$($foundPackage.PackageVersion)]."
$takeAction = $false
}
} else {
# We DO have a target
$actionValue = Compare-SemVer -Version1 $localChocoVersion -Version2 $targetAPMVersion
# We do have a specific target version. So let's compare against that
if ($actionValue -ne 0) {
Write-Host "$logLead : A(n) $($actions[$actionValue]) is required because local choco version [$localChocoVersion] is not equivalent to the target APM version [$targetAPMVersion]."
$takeAction = $true
} else {
Write-Host "$logLead : A(n) $($actions[$actionValue]) is not required because local choco version [$localChocoVersion] is equivalent to the target APM version [$targetAPMVersion]."
$takeAction = $false
}
}
#endregion Have Local Installation
} else {
#region No Local Installation
# There is no local choco version.
# The only reason we would return false here is if the calculated target version is not on the feed
if ($null -eq $targetAPMVersion -and $null -eq $foundPackage.PackageVersion) {
# No version specified, but it wouldn't matter either way.
Write-Host "$logLead : No local NewRelic APM choco package is installed, and no configured feeds host any version of the package [$NewRelicPackageName]. Upgrade/downgrade cannot be performed"
$takeAction = $false
}
#if ($null -ne $targetAPMVersion) {
# We have a specific target version. Lets check to see if there
# $foundPackage below handles this.
#}
if ($null -ne $foundPackage.PackageVersion) {
$actionValue = -1
Write-Host "$loglead : A(n) $($actions[$actionValue]) is required because no local NewRelic APM choco package is installed and version [$($foundPackage.PackageVersion)] was found on the feed named [$($foundPackage.Source.Name)]"
$takeAction = $true
}
#endregion No Local Installation
}
#endregion CompareVersions
}
$newrelicApmUpgradelData.ActionRequired = $takeAction
$newrelicApmUpgradelData.ActionType = $actions[$actionValue]
$newrelicApmUpgradelData.TargetVersion = $foundPackage.PackageVersion
$newrelicApmUpgradelData.FeedUrl = $foundPackage.FeedUrl
$newrelicApmUpgradelData.FoundPackage = $foundPackage
# And the result!
return $newrelicApmUpgradelData
}