Set-StrictMode -Off $defaultErrorActionPreference = "Stop"; $ErrorActionPreference = $defaultErrorActionPreference; $isChocolateyInstalled = (Test-Path ENV:\ChocolateyInstall) $chocoUpgradePreByDefaultTag = "chocoUpgradePreByDefault"; $chocoUpgradePreByDefaultStore = "User"; $noFilterValue = ""; $moduleUpdateEnvironmentVariableLocation = "Machine"; ## The level we store the environmental variable at $moduleUpdateTimeVariableName = "ModuleUpdateDate" ## The name of the machine-level environmental variable which stores the last update start time $moduleUpdateWindowInMinutes = "3" ## How long since the last update start time before we assume the update failed $requiredSREFeeds = @("SRETools", "nuget.internal") if ($host.Version.Major -eq 5 -and $host.Version.Minor -eq 0) { Write-Warning "This machine is not running WMF 5.1. It's probable that the profile or features will not work as expected. Download the latest WMF 5.1 patch from https://www.microsoft.com/en-us/download/details.aspx?id=54616" } ## The array of modules to install ## The order of this is fairly important. We should keep these in load order. $loadModulesAtStartup = @( @{ Name = 'Alkami.PowerShell.Common'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.Ops.Common'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } # Needs Deprecation @{ Name = 'Alkami.Ops.Certificates'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.Ops.SecretServer'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } # Needs Deprecation @{ Name = 'Alkami.PowerShell.AD'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.PowerShell.Configuration'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.PowerShell.Services'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.PowerShell.Database'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.PowerShell.ServerManagement'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.PowerShell.Choco'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.PowerShell.ServiceFabric'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.PowerShell.IIS'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.DevOps.Common'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.DevOps.Certificates'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.DevOps.Installation'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.DevOps.Operations'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.DevOps.SqlReports'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.DevOps.Inventory'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.DevOps.Validations'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'AWSPowerShell'; IsChocoInstalled = $false; AutoLoad = $true; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } # Needs Internal Hosting @{ Name = 'PSReadLine'; IsChocoInstalled = $false; AutoLoad = $true; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } # Needs Internal Hosting @{ Name = 'Alkami.Installer.ApiComponent'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $false; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.Installer.Widget'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $false; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.Installer.Provider'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $false; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.Installer.WebExtension'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $false; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.Installer.WebApplication'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $false; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.Installer.Services'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $false; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.Installer.Hotfix'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $false; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.Installer.Migration'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $false; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.Installer.LegacyUtility'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $false; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'Alkami.SRE.MigrationUtility'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $false; Filter = $noFilterValue; IsDeprecated = $false; } @{ Name = 'powershell-yaml'; IsChocoInstalled = $true; AutoLoad = $true; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } # Needs Internal Hosting @{ Name = 'PsRedis'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } # Deprecated @{ Name = 'Alkami.PowerShell.Migrations'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $true; } # No Nuspec @{ Name = 'Alkami.Ops.SmokeTest'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $true; } # Should not exist, might. @{ Name = 'Carbon'; IsChocoInstalled = $true; AutoLoad = $false; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $true; } # loseit ); <# .SYNOPSIS Updates the Alkami Modules .DESCRIPTION Updates the Alkami Modules. In order to reduce the liklihood of chocolatey causing problems, it sets a machine-level environment variable named ModuleUpdateDate with the date/time of execution, and clears it upon completion Will also attempt to avoid execution at the same time as other choco commands are running Both safety measures may be overridden .PARAMETER usePre Will use pre versions of any published modules, available on the configured feeds .PARAMETER forceUpdate Deprecated and does nothing. Retained temporarily to maintain signature compatability .PARAMETER ignoreTimeSpan Will bypass the 3 minute environmental variable marker used to prevent accidental paralell execution .PARAMETER ignoreChocoProcesses Will bypass the checks for running choco.exe processes before beginning upgrades .EXAMPLE Update-AlkamiModules -Verbose VERBOSE: Setting Environment Variable ModuleUpdateDate with value 10/02/2019 19:36:59 VERBOSE: Local Module Alkami.PowerShell.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.Certificates is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.SecretServer is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.AD is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Configuration is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Services is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Database is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.ServerManagement is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Choco is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.ServiceFabric is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.IIS is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Certificates is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Installation is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Operations is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.SqlReports is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Inventory is the Latest Version Based on Available Sources VERBOSE: Module AWSPowerShell Not Installed Via Chocolatey -- It Will Not Be Updated VERBOSE: Module PSReadLine Not Installed Via Chocolatey -- It Will Not Be Updated VERBOSE: Clearing Environment Variable ModuleUpdateDate Update Complete. 0 Module(s) Upgraded. .EXAMPLE Update-AlkamiModules -usePre -Verbose VERBOSE: Dependent Modules Will Be Ignored During Update VERBOSE: Local Module Alkami.PowerShell.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.Certificates is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.SecretServer is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.AD is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Configuration is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Services is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Database is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.ServerManagement is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Choco is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.ServiceFabric is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.IIS is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Certificates is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Installation is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Operations is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.SqlReports is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Inventory is the Latest Version Based on Available Sources VERBOSE: Module AWSPowerShell Not Installed Via Chocolatey -- It Will Not Be Updated VERBOSE: Module PSReadLine Not Installed Via Chocolatey -- It Will Not Be Updated Update Complete. 0 Module(s) Upgraded. .EXAMPLE Update-AlkamiModules -ignoreTimeSpan -Verbose WARNING: The last update appears to still be in progress, but you have selected to ignore this safety check. The potential for imposter modules is increased due to your decision. VERBOSE: Setting Environment Variable ModuleUpdateDate with value 10/02/2019 19:34:41 VERBOSE: Local Module Alkami.PowerShell.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.Certificates is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.SecretServer is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.AD is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Configuration is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Services is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Database is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.ServerManagement is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Choco is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.ServiceFabric is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.IIS is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Certificates is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Installation is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Operations is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.SqlReports is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Inventory is the Latest Version Based on Available Sources VERBOSE: Module AWSPowerShell Not Installed Via Chocolatey -- It Will Not Be Updated VERBOSE: Module PSReadLine Not Installed Via Chocolatey -- It Will Not Be Updated VERBOSE: Clearing Environment Variable ModuleUpdateDate Update Complete. 0 Module(s) Upgraded. .EXAMPLE Update-AlkamiModules -ignoreChocoProcesses -Verbose WARNING: Chocolatey processes are currently running but you have selected to ignore this safety check. The potential for imposter modules is increased due to your decision. VERBOSE: Setting Environment Variable ModuleUpdateDate with value 10/02/2019 19:39:34 VERBOSE: Local Module Alkami.PowerShell.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.Certificates is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.Ops.SecretServer is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.AD is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Configuration is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Services is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Database is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.ServerManagement is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.Choco is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.ServiceFabric is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.PowerShell.IIS is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Common is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Certificates is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Installation is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Operations is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.SqlReports is the Latest Version Based on Available Sources VERBOSE: Local Module Alkami.DevOps.Inventory is the Latest Version Based on Available Sources VERBOSE: Module AWSPowerShell Not Installed Via Chocolatey -- It Will Not Be Updated VERBOSE: Module PSReadLine Not Installed Via Chocolatey -- It Will Not Be Updated VERBOSE: Clearing Environment Variable ModuleUpdateDate Update Complete. 0 Module(s) Upgraded. #> function Update-AlkamiModules { [CmdletBinding()] Param( [Parameter(Mandatory = $false)][Alias("Pre")][switch]$usePre, [Parameter(Mandatory = $false)][Alias("Force")][switch]$forceUpdate, [Parameter(Mandatory = $false)][Alias("IgnoreTimeSafety")][switch]$ignoreTimeSpan, [Parameter(Mandatory = $false)][Alias("IgnoreChocoSafety")][switch]$ignoreChocoProcesses ) begin { if ($forceUpdate.IsPresent) { Write-Warning "Force Update is a Deprecated Parameter Which May Be Removed in the Future." } $lastUpdateTime = [Environment]::GetEnvironmentVariable($moduleUpdateTimeVariableName, [EnvironmentVariableTarget]::Machine); $preFlagTag = @("", "--pre")[($usePre -or (Test-ChocoUpgradePreByDefault))] $ignoreDepsFlag = @("", "--ignore-dependencies")[$usePre -or (Test-ChocoUpgradePreByDefault)] $now = Get-Date } process { $doViaParallel = $false if (Test-IsEclairInstalled) { Write-Host "Matched on Eclair, so we run in parallel" $doViaParallel = $true if ([Environment]::GetEnvironmentVariable('EclairParallel') -eq "false") { Write-Host "Found Eclair parallel override value, not running parallel" $doViaParallel = $false } } if ($ignoreDepsFlag -or $doViaParallel) { Write-Host "Dependent Modules Will Be Ignored During Update" } if ($null -ne $lastUpdateTime) { try { $lastUpdateTimeSpanDiff = (New-TimeSpan -Start $lastUpdateTime -End $now) } catch { Write-Warning "An error occurred trying to calculate the timespan since the last update." Write-Warning "Exception: $($_.Exception.Message)" Write-Host "Last Update Time: $lastUpdateTime" } } if ($null -ne $lastUpdateTime -and $null -ne $lastUpdateTimeSpanDiff -and $lastUpdateTimeSpanDiff.TotalMinutes -lt $moduleUpdateWindowInMinutes) { if ($ignoreTimeSpan.IsPresent) { Write-Warning "The last update appears to still be in progress, but you have selected to ignore this safety check. The potential for imposter modules is increased due to your decision." } else { Write-Warning "The last update appears to still be in progress and started at $lastUpdateTime. To override this safety check, rerun with the -ignoreTimeSpan parameter. No update will be performed" return } } [array]$chocoProcesses = (Get-CimInstance Win32_Process -Filter "name = 'choco.exe'" -Verbose:$false | Select-Object Name, CommandLine) if ($null -ne $chocoProcesses -and $chocoProcesses.Count -gt 0) { if ($ignoreChocoProcesses.IsPresent) { Write-Warning "Chocolatey processes are currently running but you have selected to ignore this safety check. The potential for imposter modules is increased due to your decision." } else { Write-Warning "$($chocoProcesses.Count) Chocolatey process(es) are currently executing. Attempting to wait them out for up to 1 minute." $maxWait = 30 $currentWait = 0 do { Write-Host "[$currentWait / $maxWait] : Waiting on Choco Processes to Exit" Start-Sleep -Seconds 2 $currentWait++ [array]$chocoProcesses = (Get-CimInstance Win32_Process -Filter "name = 'choco.exe'" -Verbose:$false | Select-Object Name, CommandLine, ProcessId) if ($null -ne $chocoProcesses -and $chocoProcesses.Count -gt 0) { Write-Verbose "Current Choco Processes Executing:" $chocoProcesses | ForEach-Object { if ($null -ne $_.CommandLine) { Write-Verbose "[$($_.ProcessId)] : $($_.CommandLine)" } } } } while ($null -ne $chocoProcesses -and $chocoProcesses.Count -gt 0 -and $maxWait -ge $currentWait) if ($maxWait -le $currentWait) { Write-Warning "Timed out waiting for choco processes to stop. Update will not be performed" return } else { Write-Host "Choco processes exited. Continuing." } } } Write-Host "Gathering local and remote package lists for comparison" # TODO: Limit this to just the package names we care about to speed up the process $chocoList = choco list -r $preFlagTag $localChocoList = choco list $loadModulesAtStartup.Name -lr $preFlagTag # Grab local/remote choco state to determine if packages need to be updated. try { $chocoUpgradesCompleted = 0 $chocoRemovesCompleted = 0 Write-Verbose "Setting Environment Variable $moduleUpdateTimeVariableName with value $now" [Environment]::SetEnvironmentVariable($moduleUpdateTimeVariableName, $now.ToString(), $moduleUpdateEnvironmentVariableLocation) Write-Host "Running Installs in parallel : $doViaParallel" $jobs = @() foreach ($module in $loadModulesAtStartup) { $installViaChoco = $module.IsChocoInstalled $moduleName = $module.Name $isDeprecated = $module.IsDeprecated if (!$installViaChoco) { Write-Host "Module $moduleName Not Installed Via Chocolatey -- It Will Not Be Updated" continue } if ($isDeprecated) { # If it is installed, remove it, otherwise, do nothing but don't try to install if (Test-IsChocoPackageInstalled -PackageName $moduleName) { if ($doViaParallel) { $jobs += Start-Job -ArgumentList ($moduleName) -ScriptBlock { param ( $sb_moduleName ) if ($sb_moduleName -eq "Carbon") { $noUninstallScriptFlag = "-n" } else { $noUninstallScriptFlag = "" } (choco uninstall $sb_moduleName -fy --ignore-dependencies --no-progress $noUninstallScriptFlag) | Out-String return @{ RemovesCompleted = 1 UpgradesCompleted = 0 } } } else { if ($moduleName -eq "Carbon") { $noUninstallScriptFlag = "-n" } else { $noUninstallScriptFlag = "" } choco uninstall $moduleName -fy $ignoreDepsFlag --no-progress $noUninstallScriptFlag $chocoRemovesCompleted++ } if ($moduleName -eq "Carbon") { try { Remove-Item -Path "C:\Program Files\WindowsPowerShell\Modules\Carbon" -Force -Recurse } catch { Write-Warning "Unable to remove Carbon module from C:\Program Files\WindowsPowerShell\Modules\Carbon" Write-Warning $_ } } } # We were deprecated, don't try to then install continue } # Compare local to remote chocolatey. If the versions are different we need to update. $localPackage = $localChocoList | Where-Object { $_ -match "$moduleName" } $remotePackage = $chocoList | Where-Object { $_ -match "$moduleName" } if ($localPackage -ne $remotePackage) { if ($doViaParallel) { $jobs += Start-Job -ArgumentList @($moduleName, $preFlagTag) -ScriptBlock { param ( $sb_moduleName, $sp_preFlagTag ) Write-Host "Updating Module Package: $sb_moduleName" $results = (choco upgrade $sb_moduleName -y $sp_preFlagTag --ignore-dependencies --no-progress) | Out-String Write-Host $results return @{ RemovesCompleted = 0 UpgradesCompleted = 1 } } } else { Write-Host "Updating Module Package: $moduleName" choco upgrade $moduleName -y $preFlagTag $ignoreDepsFlag --no-progress; $chocoUpgradesCompleted++ } if ($module.IsModule -and ($null -ne (Get-Module $moduleName))) { Remove-Module $moduleName -Force } } else { Write-Host "Local Module $moduleName is the Latest Version Based on Available Sources" } } if ($doViaParallel) { if ($jobs.Count -gt 0) { Write-Host "Waiting on the parallel installs to finish" $jobs | Wait-Job | Out-Null $results = $jobs | Receive-Job foreach ($result in $results) { $chocoUpgradesCompleted += $result.UpgradesCompleted $chocoRemovesCompleted += $result.RemovesCompleted } $jobs | Remove-Job Write-Host "Parallel installs finished" } else { # nothing to do here, no real reason to log anything, we just didn't have anything to upgrade, which is literally going to be printed below in the finally } } } finally { Write-Verbose "Clearing Environment Variable $moduleUpdateTimeVariableName" [Environment]::SetEnvironmentVariable($moduleUpdateTimeVariableName, "", $moduleUpdateEnvironmentVariableLocation) Write-Host "Update Complete. $chocoUpgradesCompleted Module(s) Upgraded." if ($chocoRemovesCompleted -gt 0) { Write-Host "Additionally: $chocoRemovesCompleted Module(s) Removed." } } } } function Test-IsEclairInstalled { <# .SYNOPSIS Returns true if the Alkami Eclair package manager is installed and running correctly. .DESCRIPTION Eclair has the key "ALKAMI_ECLAIR" in the Description of the assembly. This can be found by inspecting the VersionInfo object and getting the "Comments" field. #> [CmdletBinding()] [OutputType([System.Boolean])] Param() $isEclairInstalled = $false try { $chocoPath = (Get-Item (Join-Path (Get-ChocolateyInstallPath) 'choco.exe')) $versionInfo = (Get-Item $chocoPath).VersionInfo $versionInfoJson = $versionInfo | ConvertTo-Json -Depth 6 if($versionInfo.Comments -like "ALKAMI_ECLAIR*") { Write-Host "Found Eclair." $isEclairInstalled = $true } else { Write-Host "Eclair not found." } } catch { Write-Host "Problem checking Eclair." Write-Host $_ } return $isEclairInstalled } <# .SYNOPSIS This function checks to see if a chocolatey package with a given id has been installed. #> Function Test-IsChocoPackageInstalled { [CmdletBinding()] Param([Parameter(Mandatory = $true)][string]$packageName) process { return (Test-Path (Join-Path (Join-Path $ENV:ChocolateyInstall "lib\") $packageName)); } } <# .SYNOPSIS Configure a chocolatey source #> Function Add-ChocolateySource { [CmdletBinding()] Param($name, $url) process { (choco source add -n $name -s $url); } } <# .SYNOPSIS Check to see if this user is running the flag to always upgrade chocolatey at pre by default #> Function Test-ChocoUpgradePreByDefault() { [CmdletBinding()] Param() process { return [Environment]::GetEnvironmentVariable($chocoUpgradePreByDefaultTag, $chocoUpgradePreByDefaultStore) -eq $true; } } <# .SYNOPSIS Set this user's flag to always upgrade chocolatey at pre by default #> Function Set-ChocoUpgradePreByDefault() { [CmdletBinding()] Param() process { [Environment]::SetEnvironmentVariable($chocoUpgradePreByDefaultTag, $true, $chocoUpgradePreByDefaultStore); } } <# .SYNOPSIS Clear this user's flag to always upgrade chocolatey at pre by default #> Function Clear-ChocoUpgradePreByDefault() { [CmdletBinding()] Param() process { [Environment]::SetEnvironmentVariable($chocoUpgradePreByDefaultTag, $null, $chocoUpgradePreByDefaultStore); } } if ($isChocolateyInstalled) { # Add required chocolatey feeds if they do not exist. $moduleBaseRepositoryUrl = "https://packagerepo.orb.alkamitech.com/nuget/" try { $configuredFeeds = ([xml](Get-Content (Join-Path $ENV:ChocolateyInstall "config\chocolatey.config"))).chocolatey.Sources.source $feedsFromXml = $true } catch { Write-Warning "Unable to read configured feeds from choco config file. Falling back on choco sources command" Write-Host "Exception: $($_.Exception.Message)" $configuredFeeds = (choco sources list) $feedsFromXml = $false } foreach ($feed in $requiredSREFeeds) { $feedUrl = ("{0}{1}" -f $moduleBaseRepositoryUrl, $feed); $isFeedConfigured = switch ($feedsFromXml) { $false { ($null -ne ($configuredFeeds | Where-Object { $_ -like "*$feedUrl*" })); } default { ($null -ne ($configuredFeeds | Where-Object { $_.Value -like "*$feedUrl*" })); } } if (!$isFeedConfigured) { Write-Host "$feed chocolatey source not found -- adding" Add-ChocolateySource $feed $feedUrl } } } else { Write-Warning "Could not find chocolatey installed. Did not do anything chocolatey oriented. Install chocolatey, then restart this PowerShell window"; } # We will only load the SysEng module if it has been previously installed $systemEngineeringModule = "Alkami.DevOps.SystemEngineering" if ((Test-IsChocoPackageInstalled $systemEngineeringModule) -or ($null -ne (Get-Module -ListAvailable $systemEngineeringModule))) { $loadModulesAtStartup += @{ Name = $systemEngineeringModule; IsChocoInstalled = $true; AutoLoad = $true; IsModule = $true; Filter = $noFilterValue; IsDeprecated = $false; } } # SRE-17009 - For AWS Systems Manager Inventory Association to succeed (no Write-Host) $cleanUsername = $env:username -replace '[$]', '' if ( $cleanUsername -ne $env:computername ) { Write-Verbose "`nLoaded modules to host:" Get-Module | ForEach-Object { Write-Verbose "$($_.Name.PadRight(40)) $($_.Version.ToString())" } if (Test-ChocoUpgradePreByDefault) { Write-Warning ""; Write-Warning ""; Write-Warning " YOU ARE IN CHOCO-INSTALL-PACKAGES-VIA-PRE MODE. YOU HAVE BEEN WARNED."; Write-Warning " To turn this mode off, call this command: Clear-ChocoUpgradePreByDefault "; Write-Warning ""; Write-Warning ""; } } else { Write-Verbose "Running as system. Don't output module info" } function Remove-AllAlkamiModules { <# .SYNOPSIS Use the -Force flag to remove all the Alkami PS modules from choco/eclair folders and PS module folder Mostly only useful when testing or wanting to reset to a known state. .PARAMETER Force Used to indicate you actually want to delete them #> param ( [switch]$Force ) if ($Force) { Write-Host "SystemProfile - Destroying all Alkami Modules" Get-Module Alkami* | Remove-Module -Force Get-ChildItem -Path "C:\Program Files\WindowsPowerShell\Modules\Alkami.*" | Remove-Item -Force -Recurse Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\Alkami.DevOps.*" | Remove-Item -Force -Recurse Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\Alkami.Ops.*" | Remove-Item -Force -Recurse Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\Alkami.PowerShell.*" | Remove-Item -Force -Recurse Get-ChildItem -Path "C:\ProgramData\eclair\lib\Alkami.DevOps.*" | Remove-Item -Force -Recurse Get-ChildItem -Path "C:\ProgramData\eclair\lib\Alkami.Ops.*" | Remove-Item -Force -Recurse Get-ChildItem -Path "C:\ProgramData\eclair\lib\Alkami.PowerShell.*" | Remove-Item -Force -Recurse } else { Write-Host "SystemProfile - If you want to remove all the Alkami Modules, you have to use the -Force flag on this function call." Write-Host "SystemProfile - Be careful on calling Remove-AllAlkamiModules -Force because it does not prompt you to confirm deleting them." } }