diff --git a/doc/31-Changelog.md b/doc/31-Changelog.md index e1aa0d7..503515b 100644 --- a/doc/31-Changelog.md +++ b/doc/31-Changelog.md @@ -16,6 +16,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic * [#136](https://github.com/Icinga/icinga-powershell-framework/pull/136) Adds support to ignore empty check packages and return `Ok` instead of `Unknown` if `-IgnoreEmptyPackage` is set on `New-IcingaCheckPackage` * [#137](https://github.com/Icinga/icinga-powershell-framework/issues/137) Adds Cmdlet to compare a DateTime object with the current DateTime and return the offset as Integer in seconds * [#139](https://github.com/Icinga/icinga-powershell-framework/pull/139) Add Cmdlet `Start-IcingaShellAsUser` to open an Icinga Shell as different user for testing +* [#141](https://github.com/Icinga/icinga-powershell-framework/pull/141) Adds Cmdlet `Convert-IcingaPluginThresholds` as generic approach to convert Icinga Thresholds with units to the lowest unit of this type. ### Bugfixes diff --git a/lib/core/tools/Convert-Bytes.psm1 b/lib/core/tools/Convert-Bytes.psm1 index 870a9b8..757d14a 100644 --- a/lib/core/tools/Convert-Bytes.psm1 +++ b/lib/core/tools/Convert-Bytes.psm1 @@ -5,6 +5,10 @@ function Convert-Bytes() [string]$Unit ); + If (($Value -Match "(^[\d\.]*) ?(B|KB|MB|GB|TB|PT|KiB|MiB|GiB|TiB|PiB)") -eq $FALSE) { + $Value = [string]::Format('{0}B', $Value); + } + If (($Value -Match "(^[\d\.]*) ?(B|KB|MB|GB|TB|PT|KiB|MiB|GiB|TiB|PiB)")) { [single]$CurrentValue = $Matches[1]; [string]$CurrentUnit = $Matches[2]; @@ -37,4 +41,4 @@ function Convert-Bytes() } Exit-IcingaThrowException -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Inputs.ConversionUnitMissing -Force; -} \ No newline at end of file +} diff --git a/lib/core/tools/Convert-IcingaPluginThresholds.psm1 b/lib/core/tools/Convert-IcingaPluginThresholds.psm1 new file mode 100644 index 0000000..54b3481 --- /dev/null +++ b/lib/core/tools/Convert-IcingaPluginThresholds.psm1 @@ -0,0 +1,156 @@ +<# +.SYNOPSIS + Converts any kind of Icinga threshold with provided units + to the lowest base of the unit which makes sense. It does + support the Icinga plugin language, like ~:30, @10:40, 15:30, + ... + + The conversion does currently support the following units: + + Size: B, KB, MB, GB, TB, PT, KiB, MiB, GiB, TiB, PiB + Time: ms, s, m, h, d w, M, y +.DESCRIPTION + Converts any kind of Icinga threshold with provided units + to the lowest base of the unit. It does support the Icinga + plugin language, like ~:30, @10:40, 15:30, ... + + The conversion does currently support the following units: + + Size: B, KB, MB, GB, TB, PT, KiB, MiB, GiB, TiB, PiB + Time: ms, s, m, h, d w, M, y +.FUNCTIONALITY + Converts values with units to the lowest unit of this category. + Accepts Icinga Thresholds. +.EXAMPLE + PS>Convert-IcingaPluginThresholds -Threshold '20d'; + + Name Value + ---- ----- + Value 1728000 + Unit s +.EXAMPLE + PS>Convert-IcingaPluginThresholds -Threshold '5GB'; + + Name Value + ---- ----- + Value 5000000000 + Unit B +.EXAMPLE + PS>Convert-IcingaPluginThresholds -Threshold '10MB:20MB'; + + Name Value + ---- ----- + Value 10000000:20000000 + Unit B +.EXAMPLE + PS>Convert-IcingaPluginThresholds -Threshold '10m:1h'; + + Name Value + ---- ----- + Value 600:3600 + Unit s +.EXAMPLE + PS>Convert-IcingaPluginThresholds -Threshold '@10m:1h'; + + Name Value + ---- ----- + Value @600:3600 + Unit s +.EXAMPLE + Convert-IcingaPluginThresholds -Threshold '~:1M'; + + Name Value + ---- ----- + Value ~:2592000 + Unit s +.INPUTS + System.String +.OUTPUTS + System.Hashtable +.LINK + https://github.com/Icinga/icinga-powershell-framework +#> + +function Convert-IcingaPluginThresholds() +{ + param ( + [string]$Threshold = $null + ); + + [hashtable]$RetValue = @{ + 'Unit' = ''; + 'Value' = $null; + }; + + if ($null -eq $Threshold) { + return $RetValue; + } + + # Always ensure we are using correct digits + $Threshold = $Threshold.Replace(',', '.'); + + [array]$Content = @(); + + if ($Threshold.Contains(':')) { + $Content = $Threshold.Split(':'); + } else { + $Content += $Threshold; + } + + [array]$ConvertedValue = @(); + + foreach ($ThresholdValue in $Content) { + + [bool]$HasTilde = $FALSE; + [bool]$HasAt = $FALSE; + $Value = ''; + $WorkUnit = ''; + + if ($ThresholdValue.Contains('~')) { + $ThresholdValue = $ThresholdValue.Replace('~', ''); + $HasTilde = $TRUE; + } elseif ($ThresholdValue.Contains('@')) { + $HasAt = $TRUE; + $ThresholdValue = $ThresholdValue.Replace('@', ''); + } + + If (($ThresholdValue -Match "(^[\d\.]*) ?(B|KB|MB|GB|TB|PT|KiB|MiB|GiB|TiB|PiB)")) { + $WorkUnit = 'B'; + if ([string]::IsNullOrEmpty($RetValue.Unit) -eq $FALSE -And $RetValue.Unit -ne $WorkUnit) { + Exit-IcingaThrowException -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Inputs.MultipleUnitUsage -Force; + } + $Value = (Convert-Bytes -Value $ThresholdValue -Unit $WorkUnit).Value; + $RetValue.Unit = $WorkUnit; + } elseif (($ThresholdValue -Match "(^[\d\.]*) ?(ms|s|m|h|d|w|M|y)")) { + $WorkUnit = 's'; + if ([string]::IsNullOrEmpty($RetValue.Unit) -eq $FALSE -And $RetValue.Unit -ne $WorkUnit) { + Exit-IcingaThrowException -ExceptionType 'Input' -ExceptionThrown $IcingaExceptions.Inputs.MultipleUnitUsage -Force; + } + $Value = (ConvertTo-Seconds -Value $ThresholdValue); + $RetValue.Unit = $WorkUnit; + } else { + $Value = $ThresholdValue; + } + + if ($HasTilde) { + $ConvertedValue += [string]::Format('~{0}', $Value); + } elseif ($HasAt) { + $ConvertedValue += [string]::Format('@{0}', $Value); + } else { + $ConvertedValue += $Value; + } + } + + [string]$Value = [string]::Join(':', $ConvertedValue); + + if ([string]::IsNullOrEmpty($Value) -eq $FALSE -And $Value.Contains(':') -eq $FALSE) { + if ((Test-Numeric $Value)) { + $RetValue.Value = [convert]::ToDecimal($Value); + return $RetValue; + } + } + + $RetValue.Value = $Value; + + return $RetValue; +} diff --git a/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 b/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 index 7c82ef3..f06665b 100644 --- a/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 +++ b/lib/icinga/exception/Icinga_IcingaExceptionEnums.psm1 @@ -13,12 +13,13 @@ }; [hashtable]$Inputs = @{ - PerformanceCounter = 'A plugin failed to fetch Performance Counter information. Please ensure the counter is written properly and available on your system.'; - EventLogLogName = 'Failed to fetch EventLog information. Please specify a valid LogName.'; - EventLog = 'Failed to fetch EventLog information. Please check your inputs for EntryTypes and other categories and try again.'; - ConversionUnitMissing = 'Unable to parse input value. You have to add an unit to your input value. Example: "10GB". Allowed units are: "B, KB, MB, GB, TB, PB, KiB, MiB, GiB, TiB, PiB".'; - CimClassNameUnknown = 'The provided class name you try to fetch with Get-CimInstance is not known on this system.'; - WmiObjectClassUnknown = 'The provided class name you try to fetch with Get-WmiObject is not known on this system.'; + PerformanceCounter = 'A plugin failed to fetch Performance Counter information. Please ensure the counter is written properly and available on your system.'; + EventLogLogName = 'Failed to fetch EventLog information. Please specify a valid LogName.'; + EventLog = 'Failed to fetch EventLog information. Please check your inputs for EntryTypes and other categories and try again.'; + ConversionUnitMissing = 'Unable to parse input value. You have to add an unit to your input value. Example: "10GB". Allowed units are: "B, KB, MB, GB, TB, PB, KiB, MiB, GiB, TiB, PiB".'; + MultipleUnitUsage = 'Failed to convert your Icinga threshold units as you were trying to convert values with a different type of unit category. This feature only supports the conversion of one unit category. For example you can not convert 20MB:10d in the same call, as size and time units are not compatible.'; + CimClassNameUnknown = 'The provided class name you try to fetch with Get-CimInstance is not known on this system.'; + WmiObjectClassUnknown = 'The provided class name you try to fetch with Get-WmiObject is not known on this system.'; MSSQLCredentialHandling = 'The connection to MSSQL was not possbible because your login credential was not correct.'; MSSQLCommandMissing = 'Failed to build a SQL query' }; @@ -41,7 +42,7 @@ # to make it available within the entire module. # # Example usage: - # $IcingaExceptionEnums.IcingaExecptionHandlers.PerformanceCounter + # $IcingaException.Inputs.PerformanceCounter #> [hashtable]$IcingaExceptions = @{ Permission = $Permission;