331 lines
15 KiB
PowerShell
331 lines
15 KiB
PowerShell
function Install-Provider {
|
|
<#
|
|
.SYNOPSIS
|
|
This function is used in conjunction with Alkami.Installer.Provider to install legacy providers to the appropriate locations.
|
|
|
|
.DESCRIPTION
|
|
This function is used in conjunction with Alkami.Installer.Provider to install legacy providers to the appropriate locations.
|
|
It will stop the following services and restart them if they were running at the time of install:
|
|
* BankService - WCF Service
|
|
* SchedulerService - WCF Service
|
|
* CoreService - WCF Service
|
|
* SecurityManagementService - WCF Service
|
|
* NagConfigurationService - WCF Service
|
|
* Nag - Windows Service
|
|
* Radium - Windows Service
|
|
|
|
.PARAMETER ProviderAssemblyInfo
|
|
The provider's configured assembly info.
|
|
|
|
.PARAMETER SourcePath
|
|
This is the path to the source containing folder. Typically this is a chocolatey folder.
|
|
|
|
.PARAMETER ProviderName
|
|
The provider's configured name. This is not required, it will be used for display purposes only as of Alkami.PowerShell.IIS v3.1.1
|
|
|
|
.PARAMETER ProviderTargets
|
|
Names of services that the Provider will be installed to
|
|
|
|
.PARAMETER NoSymlink
|
|
Force installation using File Copy operations, omitting a call to Test-InstallerUseSymlinkStrategy, even on hosts with the ENVIRONMENT VARIABLE 'Alkami.Installer.UseSymlink' set
|
|
|
|
.LINK
|
|
Test-InstallerUseSymlinkStrategy
|
|
|
|
.OUTPUTS
|
|
This function will only Write-Information, but also show the files that will be tentatively copied over
|
|
|
|
.EXAMPLE
|
|
Install-Provider -ProviderAssemblyInfo Alkami.App.Providers.Core.Dynamic -SourcePath C:\ProgramData\chocolatey\lib\Alkami.App.Providers.Core.Dynamic
|
|
|
|
Install-Provider output may be verbose from the underlying calls being made.
|
|
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[AllowNull()]
|
|
[string]$ProviderAssemblyInfo,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateScript( { Test-Path (Resolve-Path $_) })]
|
|
[string]$SourcePath,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[AllowNull()]
|
|
[string]$ProviderName = $null,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[AllowNull()]
|
|
[string[]]$ProviderTargets = @('BankService', 'CoreService', 'NotificationService', 'SecurityManagementService', 'Radium', 'Nag', 'NagConfigurationService', 'SchedulerService'),
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[switch]$NoSymlink
|
|
)
|
|
process {
|
|
$loglead = Get-LogLeadName
|
|
|
|
Write-Host "$loglead : $ProviderName being installed by $($env:USERNAME) on $($env:COMPUTERNAME) at $(Get-Date)"
|
|
|
|
## If it's a developer machine we can install anything
|
|
## Don't install on MIC or WEB servers, only APP servers.
|
|
if ( -not (Test-IsDeveloperMachine) -and -not (Test-IsAppServer)) {
|
|
Write-Warning "$loglead : Can ONLY install providers on APP machines or DEVELOPER machines"
|
|
return
|
|
}
|
|
if ( -not (Test-IsAdmin)) {
|
|
throw "You are not running as administrator. Can not continue."
|
|
}
|
|
|
|
# See if there is an override
|
|
if ($NoSymlink) {
|
|
Write-Host "$loglead : Override provided! Using Legacy non-Symlink Installer Strategy"
|
|
$usingSymlinkStrategy = $false
|
|
} else {
|
|
$usingSymlinkStrategy = Test-InstallerUseSymlinkStrategy
|
|
|
|
if ($usingSymlinkStrategy) {
|
|
Write-Host "$loglead : Using Symlink Installer Strategy."
|
|
} else {
|
|
Write-Host "$loglead : Using Legacy non-Symlink Installer Strategy"
|
|
}
|
|
}
|
|
|
|
$copyScriptBlock = {
|
|
param($sbSourcePath, $sbTargetPath, $sbUseSymlinkStrategy, $sbLoglead)
|
|
|
|
$sbloglead = "$sbLoglead (copyScriptBlock)"
|
|
$sbTargetFilename = Split-Path -Path $sbSourcePath -Leaf
|
|
$sbTargetDestination = Join-Path -Path $sbTargetPath -ChildPath $sbTargetFilename
|
|
#If sbTargetPath exists, delete it
|
|
#NOTE - the Symlink codepath SPECIFICALLY DOES NOT DELETE
|
|
if (Test-Path -Path $sbTargetDestination) {
|
|
Write-Host "$sbloglead : Removing non-symlinked file at destination $sbTargetDestination"
|
|
# This is to remove legacy files when upgrading to new Symlink Strategy.
|
|
Remove-FileSystemItem -Path $sbTargetDestination -Force -SkipSymlinks
|
|
}
|
|
|
|
if ($sbUseSymlinkStrategy) {
|
|
Write-Host "$sbloglead : Symlinking file $sbSourcePath into Destination $sbTargetPath"
|
|
New-Symlink -Path $sbSourcePath -Destination $sbTargetDestination
|
|
} else {
|
|
Write-Host "$sbloglead : Copying file $sbSourcePath into Destination $sbTargetPath"
|
|
Copy-Item -Path $sbSourcePath -Destination $sbTargetPath -Force | Out-Null
|
|
}
|
|
}
|
|
|
|
if ( -not (Test-Path -Path $SourcePath)) {
|
|
throw "Could not find the source path specified at $SourcePath"
|
|
}
|
|
|
|
$libSourcePath = Join-Path -Path $SourcePath -ChildPath "lib"
|
|
|
|
## We aren't in a valid Alkami choco package if this is the case.
|
|
if ( -not (Test-Path -Path $libSourcePath)) {
|
|
throw "Could not find the lib folder path specified at $libSourcePath"
|
|
}
|
|
|
|
$libSourceFSOFolder = (Get-ChildItem $libSourcePath -Directory) | Sort-Object -Descending | Select-Object -First 1
|
|
# SRE-16977 - following line should be this
|
|
# $libSourceFolderPath = $libSourceFSOFolder.FullName
|
|
# However, developers implemented packages that UNINTENTIONALLY took advantage of this bug
|
|
# We must reintroduce this bug in order to not break the deployment of malformed packages
|
|
# This allows for the preceding Get-ChildItem to return $null and the following line to return
|
|
# the path it was trying to Get-ChildItem from without problem, instead of $null
|
|
$libSourceFolderPath = Join-Path -Path $libSourcePath -ChildPath $libSourceFSOFolder.Name
|
|
|
|
#TODO: Get these only once for the $childFiles array below
|
|
if ((Get-ChildItem -Path $libSourceFolderPath -Filter "*.dll").Count -eq 0 -and (Get-ChildItem -Path $libSourceFolderPath -Filter "*.exe").Count -eq 0) {
|
|
throw "Could not find any dll or exe files under $libSourceFolderPath"
|
|
}
|
|
|
|
if ( -not (Get-ChildItem $libSourceFolderPath -Filter "$ProviderAssemblyInfo.dll")) {
|
|
$message = "The folder $libSourceFolderPath does not have a $ProviderAssemblyInfo dll file. This is in violation of package structuring. The Dev team must fix this so the $ProviderAssemblyInfo package id matches the principal dll of the package."
|
|
Write-Error $message
|
|
throw $message
|
|
}
|
|
|
|
$folderTargets = @()
|
|
$orbPath = Get-OrbPath
|
|
|
|
## If the following services are in any status other than Stopped, we want to stop, then restart them when on a NON-PROD machine.
|
|
## Production servers are always deployed to when out-of-pool, so the services are already, in theory, stopped.
|
|
$isRadiumRunning = $false
|
|
$radiumServiceName = @(Get-ServiceNamesByFragment -Name "Radium")[0]
|
|
if ($ProviderTargets -contains "Radium") {
|
|
if ($radiumServiceName -ne "Not installed") {
|
|
$isRadiumRunning = (Get-Service -Name $radiumServiceName).Status -ne "Stopped"
|
|
if (Test-Path -Path (Join-Path -Path (Get-OrbPath) -ChildPath 'Radium')) {
|
|
$folderTargets += Join-Path -Path $orbPath -ChildPath "Radium"
|
|
}
|
|
}
|
|
}
|
|
|
|
$isNagRunning = $false
|
|
$nagServiceName = @(Get-ServiceNamesByFragment -Name "Alkami Nag")[0]
|
|
if ($ProviderTargets -contains "Nag") {
|
|
if ($nagServiceName -ne "Not installed") {
|
|
$isNagRunning = (Get-Service -Name $nagServiceName).Status -ne "Stopped"
|
|
if (Test-Path -Path (Join-Path -Path (Get-OrbPath) -ChildPath 'Nag')) {
|
|
$folderTargets += Join-Path -Path $orbPath -ChildPath "Nag"
|
|
}
|
|
}
|
|
}
|
|
|
|
$isBankRunning = $false
|
|
if ($ProviderTargets -contains "BankService") {
|
|
$isBankRunning = Test-IISAppPoolByName -Name "BankService"
|
|
$bankServicePath = Join-Path -Path $orbPath -ChildPath "BankService"
|
|
$bankServiceBinPath = Join-Path -Path $bankServicePath -ChildPath "bin"
|
|
if (Test-Path -Path $bankServiceBinPath) {
|
|
$folderTargets += $bankServiceBinPath
|
|
}
|
|
}
|
|
|
|
$isSchedulerRunning = $false
|
|
if ($ProviderTargets -contains "SchedulerService") {
|
|
$isSchedulerRunning = Test-IISAppPoolByName -Name "SchedulerService"
|
|
$SchedulerServicePath = Join-Path -Path $orbPath -ChildPath "SchedulerService"
|
|
$SchedulerServiceBinPath = Join-Path -Path $SchedulerServicePath -ChildPath "bin"
|
|
if (Test-Path -Path $SchedulerServiceBinPath) {
|
|
$folderTargets += $SchedulerServiceBinPath
|
|
}
|
|
}
|
|
|
|
$isCoreRunning = $false
|
|
if ($ProviderTargets -contains 'CoreService') {
|
|
$isCoreRunning = Test-IISAppPoolByName -Name "CoreService"
|
|
## CoreService is included because occasionally it may use other providers.
|
|
$coreServicePath = Join-Path -Path $orbPath -ChildPath "CoreService"
|
|
$coreServiceBinPath = Join-Path -Path $coreServicePath -ChildPath "bin"
|
|
if (Test-Path -Path $coreServiceBinPath) {
|
|
$folderTargets += $coreServiceBinPath
|
|
}
|
|
}
|
|
|
|
$isNagConfigRunning = $false
|
|
if ($ProviderTargets -contains 'NagConfigurationService') {
|
|
$isNagConfigRunning = Test-IISAppPoolByName -Name "NagConfigurationService"
|
|
$nagConfigurationServicePath = Join-Path -Path $orbPath -ChildPath "NagConfigurationService"
|
|
$nagConfigurationServiceBinPath = Join-Path -Path $nagConfigurationServicePath -ChildPath "bin"
|
|
if (Test-Path -Path $nagConfigurationServiceBinPath) {
|
|
$folderTargets += $nagConfigurationServiceBinPath
|
|
}
|
|
}
|
|
|
|
$isNotifyRunning = $false
|
|
if ($ProviderTargets -contains 'NotificationService') {
|
|
$isNotifyRunning = Test-IISAppPoolByName -Name "NotificationService"
|
|
$notificationServicePath = Join-Path -Path $orbPath -ChildPath "NotificationService"
|
|
$notificationServiceBinPath = Join-Path -Path $notificationServicePath -ChildPath "bin"
|
|
if (Test-Path -Path $notificationServiceBinPath) {
|
|
$folderTargets += $notificationServiceBinPath
|
|
}
|
|
}
|
|
|
|
$isSecMgmtRunning = $false
|
|
if ($ProviderTargets -contains 'SecurityManagementService') {
|
|
$isSecMgmtRunning = Test-IISAppPoolByName -Name "SecurityManagementService"
|
|
$securityManagementServicePath = Join-Path -Path $orbPath -ChildPath "SecurityManagementService"
|
|
$securityManagementServiceBinPath = Join-Path -Path $securityManagementServicePath -ChildPath "bin"
|
|
if (Test-Path -Path $securityManagementServiceBinPath) {
|
|
$folderTargets += $securityManagementServiceBinPath
|
|
}
|
|
}
|
|
|
|
if ($isRadiumRunning) {
|
|
Stop-AlkamiService -ServiceName $radiumServiceName
|
|
}
|
|
|
|
if ($isNagRunning) {
|
|
Stop-AlkamiService -ServiceName $nagServiceName
|
|
}
|
|
|
|
if ($isBankRunning) {
|
|
Stop-IISAppPoolByName -Name "BankService"
|
|
Remove-DotNetTemporaryFiles -Name "Bank"
|
|
}
|
|
|
|
if ($isSchedulerRunning) {
|
|
Stop-IISAppPoolByName -Name "SchedulerService"
|
|
Remove-DotNetTemporaryFiles -Name "SchedulerService"
|
|
}
|
|
|
|
if ($isCoreRunning) {
|
|
Stop-IISAppPoolByName -Name "CoreService"
|
|
Remove-DotNetTemporaryFiles -Name "CoreService"
|
|
}
|
|
|
|
if ($isNagConfigRunning) {
|
|
Stop-IISAppPoolByName -Name "NagConfigurationService"
|
|
Remove-DotNetTemporaryFiles -Name "NagConfigurationService"
|
|
}
|
|
|
|
if ($isNotifyRunning) {
|
|
Stop-IISAppPoolByName -Name "NotificationService"
|
|
Remove-DotNetTemporaryFiles -Name "NotificationService"
|
|
}
|
|
|
|
if ($isSecMgmtRunning) {
|
|
Stop-IISAppPoolByName -Name "SecurityManagementService"
|
|
Remove-DotNetTemporaryFiles -Name "securityManagement"
|
|
}
|
|
|
|
if ($isBankRunning -or $isCoreRunning -or $isNagConfigRunning -or $isNotifyRunning -or $isSecMgmtRunning -or $isRadiumRunning -or $isNagRunning -or $isSchedulerRunning) {
|
|
Start-Sleep -Seconds 30
|
|
}
|
|
|
|
$childFiles = @()
|
|
$childFiles += @(Get-ChildItem -Path $libSourceFolderPath -Filter "*.dll")
|
|
$childFiles += @(Get-ChildItem -Path $libSourceFolderPath -Filter "*.exe")
|
|
foreach ($childFile in $childFiles) {
|
|
$pdbPath = $file.FullName -replace $file.Extension, ".pdb"
|
|
if (Test-Path -Path $pdbPath) {
|
|
$childFiles += $pdbPath
|
|
}
|
|
}
|
|
|
|
Write-Host "$loglead : Files to copy or link: "
|
|
Write-Host ("$loglead : `n`t{0}" -f ($childFiles.FullName -join "`n`t"))
|
|
|
|
## THIS COMMENT APPLIES TO THE SCRIPTBLOCK BEING CALLED BY Invoke-CommandWithRetry
|
|
## As we've already checked the files against the shared folder in ORB, let's now check each individual service
|
|
## bin folder for the pared-down list of files from the package.
|
|
## If the file in the bin folder already exists and matches/wins, we don't need to do anything.
|
|
## The anticipation is that the list of files to be checked here is approximately 5-8, or less.
|
|
## That's 40 potential file comparisons across five services, so it should be relatively fast.
|
|
foreach($targetFolder in $folderTargets) {
|
|
foreach($filePath in $childFiles.FullName) {
|
|
Write-Host "$loglead : Copying file $filePath into Destination $targetFolder with -Force"
|
|
Write-Information '.'
|
|
|
|
Invoke-CommandWithRetry -MaxRetries 3 -SecondsDelay 1 -Arguments @($filePath, $targetFolder, $usingSymlinkStrategy, $loglead) -ScriptBlock $copyScriptBlock
|
|
}
|
|
}
|
|
|
|
if ($isBankRunning) {
|
|
Start-IISAppPoolByName -Name "BankService"
|
|
}
|
|
if ($isSchedulerRunning) {
|
|
Start-IISAppPoolByName -Name "SchedulerService"
|
|
}
|
|
if ($isCoreRunning) {
|
|
Start-IISAppPoolByName -Name "CoreService"
|
|
}
|
|
if ($isNagConfigRunning) {
|
|
Start-IISAppPoolByName -Name "NagConfigurationService"
|
|
}
|
|
if ($isNotifyRunning) {
|
|
Start-IISAppPoolByName -Name "NotificationService"
|
|
}
|
|
if ($isSecMgmtRunning) {
|
|
Start-IISAppPoolByName -Name "SecurityManagementService"
|
|
}
|
|
if ($isRadiumRunning) {
|
|
Start-Service -Name $radiumServiceName
|
|
}
|
|
if ($isNagRunning) {
|
|
Start-Service -Name $nagServiceName
|
|
}
|
|
}
|
|
} |