Fixes progress status writer by reworking

This commit is contained in:
Lord Hepipud 2022-01-27 15:11:39 +01:00
parent ce67756910
commit cf52e6372e
8 changed files with 127 additions and 43 deletions

View file

@ -30,6 +30,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
* [#436](https://github.com/Icinga/icinga-powershell-framework/pull/436) Fixes a lookup error for existing plugin documentation files, which caused files not being generated properly in case a similar name was already present on the system
* [#439](https://github.com/Icinga/icinga-powershell-framework/pull/439) Moves PerformanceCounter to private space from previous public, which caused some problems
* [#441](https://github.com/Icinga/icinga-powershell-framework/pull/441) Fixes an exception while loading the Framework, caused by a race condition for missing environment variables which are accessed by some plugins before the Framework is loaded properly
* [#446](https://github.com/Icinga/icinga-powershell-framework/pull/446) Fixes Icinga for Windows progress preference, which sometimes caused UI glitches
### Enhancements

View file

@ -62,6 +62,7 @@ The following entries are set by default within the `Private` space:
| Scheduler | Once plugins are executed, performance data, check results and exit codes are stored in this section, in case the PowerShell instance is set to run as daemon |
| Daemons | This is a place where all daemon data should be added and stored, separated by a namespace for each module as entry. This data is **not** shared between other daemons |
| PerformanceCounter | A space to share all PerformanceCounter information between threads, which counters are already created for internal usage |
| ProgressStatus | A list of all created progress status bars from Icinga for Windows |
#### Example Data

View file

@ -21,6 +21,7 @@ function New-IcingaEnvironmentVariable()
$Global:Icinga.Private.Add('Daemons', @{ });
$Global:Icinga.Private.Add('Timers', @{ });
$Global:Icinga.Private.Add('ProgressStatus', @{ });
$Global:Icinga.Private.Add(
'Scheduler',

View file

@ -27,8 +27,10 @@ function Get-IcingaJEAConfiguration()
# Lookup all PowerShell modules installed for Icinga for Windows inside the same folder as the Framework
# and fetch each single module file to list the used Cmdlets and Functions
# Add each file content to a big string file for better parsing
New-IcingaProgressStatus -Name 'Icinga for Windows Components' -Message 'Fetching Icinga for Windows Components' -MaxValue $PowerShellModules.Count -Details;
foreach ($module in $PowerShellModules) {
$Progress = Write-IcingaProgressStatus -Message 'Fetching Icinga for Windows Components' -CurrentValue $Progress -MaxValue $PowerShellModules.Count -Details;
Write-IcingaProgressStatus -Name 'Icinga for Windows Components';
if ($module.Name.ToLower() -eq 'icinga-powershell-framework') {
continue;
}
@ -78,12 +80,16 @@ function Get-IcingaJEAConfiguration()
$ModuleContent += $ModuleFileContent;
}
Complete-IcingaProgressStatus -Name 'Icinga for Windows Components';
if ($DependencyCache -eq $FALSE) {
# Now lets lookup every single Framework file and get all used Cmdlets and Functions so we know our dependencies
$FrameworkFiles = Get-ChildItem -Path (Get-IcingaFrameworkRootPath) -Recurse -Filter '*.psm1';
New-IcingaProgressStatus -Name 'Icinga for Windows Files' -Message 'Compiling Icinga PowerShell Framework Dependency List' -MaxValue $FrameworkFiles.Count -Details;
foreach ($ModuleFile in $FrameworkFiles) {
$Progress = Write-IcingaProgressStatus -Message 'Compiling Icinga PowerShell Framework Dependency List' -CurrentValue $Progress -MaxValue $FrameworkFiles.Count -Details;
Write-IcingaProgressStatus -Name 'Icinga for Windows Files';
# Just ignore our cache file
if ($ModuleFile.FullName -eq (Get-IcingaFrameworkCodeCacheFile)) {
@ -99,6 +105,8 @@ function Get-IcingaJEAConfiguration()
}
}
Complete-IcingaProgressStatus -Name 'Icinga for Windows Files';
Write-IcingaFileSecure -File (Join-Path -Path (Get-IcingaCacheDir) -ChildPath 'framework_dependencies.json') -Value $DependencyList;
}
@ -107,8 +115,10 @@ function Get-IcingaJEAConfiguration()
# Check all our configured background daemons and ensure we get all Cmdlets and Functions including the dependency list
$BackgroundDaemons = (Get-IcingaBackgroundDaemons).Keys;
New-IcingaProgressStatus -Name 'Compiling Icinga for Windows Daemons' -Message 'Compiling Background Daemon Dependency List' -MaxValue $BackgroundDaemons.Count -Details;
foreach ($daemon in $BackgroundDaemons) {
$Progress = Write-IcingaProgressStatus -Message 'Compiling Background Daemon Dependency List' -CurrentValue $Progress -MaxValue $BackgroundDaemons.Count -Details;
Write-IcingaProgressStatus -Name 'Compiling Icinga for Windows Daemons';
$DaemonCmd = (Get-Command $daemon);
@ -127,6 +137,8 @@ function Get-IcingaJEAConfiguration()
-CmdType $CommandType;
}
Complete-IcingaProgressStatus -Name 'Compiling Icinga for Windows Daemons';
# We need to add this function which is not used anywhere else and should still add the entire dependency tree
$UsedCmdlets = Get-IcingaCommandDependency `
-DependencyList $DependencyList `
@ -146,8 +158,10 @@ function Get-IcingaJEAConfiguration()
$DeserializedFile = Read-IcingaPowerShellModuleFile -FileContent $ModuleContent;
[array]$JeaCmds = $DeserializedFile.CommandList + $DeserializedFile.FunctionList;
New-IcingaProgressStatus -Name 'Compiling JEA' -Message 'Compiling JEA Profile Catalog' -MaxValue $JeaCmds.Count -Details;
foreach ($cmd in $JeaCmds) {
$Progress = Write-IcingaProgressStatus -Message 'Compiling JEA Profile Catalog' -CurrentValue $Progress -MaxValue $JeaCmds.Count -Details;
Write-IcingaProgressStatus -Name 'Compiling JEA';
$CmdData = Get-Command $cmd -ErrorAction SilentlyContinue;
if ($null -eq $CmdData) {
@ -163,6 +177,8 @@ function Get-IcingaJEAConfiguration()
-CmdType $CommandType;
}
Complete-IcingaProgressStatus -Name 'Compiling JEA';
Disable-IcingaProgressPreference;
return $UsedCmdlets;

View file

@ -0,0 +1,28 @@
function Complete-IcingaProgressStatus()
{
param (
[string]$Name = ''
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError -Message 'Failed to complete progress status. You have to specify a name.';
return;
}
if ($Global:Icinga.Private.ProgressStatus.ContainsKey($Name) -eq $FALSE) {
return;
}
if ($Global:Icinga.Private.ProgressStatus[$Name].Details) {
$Message = [string]::Format('{0}: {1}/{2}', $Global:Icinga.Private.ProgressStatus[$Name].Message, $Global:Icinga.Private.ProgressStatus[$Name].MaxValue, $Global:Icinga.Private.ProgressStatus[$Name].MaxValue);
} else {
$Message = $Global:Icinga.Private.ProgressStatus[$Name].Message;
}
$ProgressPreference = 'Continue';
Write-Progress -Activity $Message -Status ([string]::Format($Global:Icinga.Private.ProgressStatus[$Name].Status, 100)) -PercentComplete 100 -Completed;
$Global:Icinga.Private.ProgressStatus.Remove($Name);
$ProgressPreference = 'SilentlyContinue';
}

View file

@ -0,0 +1,39 @@
function New-IcingaProgressStatus()
{
param (
[string]$Name = '',
[int]$CurrentValue = 0,
[int]$MaxValue = 1,
[string]$Message = 'Processing Icinga for Windows',
[string]$Status = '{0}% Complete',
[switch]$Details = $FALSE
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError -Message 'Failed to create new progress status. You have to specify a name.';
return;
}
if ($MaxValue -le 0) {
Write-IcingaConsoleError -Message 'Failed to create new progress status. The maximum value has to be larger than 0.';
return;
}
if ($Global:Icinga.Private.ProgressStatus.ContainsKey($Name)) {
Write-IcingaConsoleError -Message 'Failed to create new progress status. A progress status with this name is already active. Use "Complete-IcingaProgressStatus" to remove it.';
return;
}
$Global:Icinga.Private.ProgressStatus.Add(
$Name,
@{
'CurrentValue' = $CurrentValue;
'MaxValue' = $MaxValue;
'Message' = $Message;
'Status' = $Status;
'Details' = ([bool]$Details);
}
);
$ProgressPreference = 'Continue';
}

View file

@ -0,0 +1,37 @@
function Write-IcingaProgressStatus()
{
param (
[string]$Name = '',
[int]$AddValue = 1,
[switch]$PrintErrors = $FALSE
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError -Message 'Failed to write progress status. You have to specify a name.' -DropMessage:$(-Not $PrintErrors);
return;
}
if ($Global:Icinga.Private.ProgressStatus.ContainsKey($Name) -eq $FALSE) {
Write-IcingaConsoleError -Message 'Failed to write progress status. A progress status with the name "{0}" does not exist. You have to create it first with "New-IcingaProgressStatus".' -Objects $Name -DropMessage:$(-Not $PrintErrors);
return;
}
$Global:Icinga.Private.ProgressStatus[$Name].CurrentValue += $AddValue;
$ProgressValue = [math]::Round($Global:Icinga.Private.ProgressStatus[$Name].CurrentValue / $Global:Icinga.Private.ProgressStatus[$Name].MaxValue * 100, 0);
if ($Global:Icinga.Private.ProgressStatus[$Name].Details) {
$Message = [string]::Format('{0}: {1}/{2}', $Global:Icinga.Private.ProgressStatus[$Name].Message, $Global:Icinga.Private.ProgressStatus[$Name].CurrentValue, $Global:Icinga.Private.ProgressStatus[$Name].MaxValue);
} else {
$Message = $Global:Icinga.Private.ProgressStatus[$Name].Message;
}
if ($ProgressValue -ge 100) {
Complete-IcingaProgressStatus -Name $Name;
return;
}
$ProgressPreference = 'Continue';
Write-Progress -Activity $Message -Status ([string]::Format($Global:Icinga.Private.ProgressStatus[$Name].Status, $ProgressValue)) -PercentComplete $ProgressValue;
}

View file

@ -1,39 +0,0 @@
function Write-IcingaProgressStatus()
{
param (
[int]$CurrentValue = 0,
[int]$MaxValue = 1,
[string]$Message = 'Processing Icinga for Windows',
[string]$Status = "{0}% Complete",
[switch]$Details = $FALSE
);
if ($CurrentValue -le -99) {
$CurrentValue = 0;
return;
}
if ($MaxValue -le 0) {
$MaxValue = 1;
}
$ProgressValue = [math]::Round($CurrentValue / $MaxValue * 100, 0);
if ($Details) {
$Message = [string]::Format('{0}: {1}/{2}', $Message, $CurrentValue, $MaxValue);
}
$ProgressPreference = 'Continue';
if ($ProgressValue -ge 100) {
$ProgressValue = 100;
Write-Progress -Activity $Message -Status ([string]::Format($Status, $ProgressValue)) -PercentComplete $ProgressValue -Completed;
$CurrentValue = -99;
return $CurrentValue;
}
Write-Progress -Activity $Message -Status ([string]::Format($Status, $ProgressValue)) -PercentComplete $ProgressValue;
return ($CurrentValue += 1);
}