icinga-powershell-framework/icinga-powershell-framework.psm1

316 lines
10 KiB
PowerShell
Raw Normal View History

2018-11-06 11:14:49 -05:00
<#
.Synopsis
Icinga PowerShell Module - Powerfull PowerShell Framework for monitoring Windows Systems
.DESCRIPTION
2019-10-31 12:24:30 -04:00
More Information on https://github.com/Icinga/icinga-powershell-framework
2018-11-06 11:14:49 -05:00
.EXAMPLE
Install-Icinga
2018-11-06 11:14:49 -05:00
.NOTES
#>
function Use-Icinga()
{
2019-10-05 15:54:24 -04:00
param(
[switch]$LibOnly = $FALSE,
[switch]$Daemon = $FALSE,
[switch]$DebugMode = $FALSE
2019-10-05 15:54:24 -04:00
);
# Ensure we autoload the Icinga Plugin collection, provided by the external
# module 'icinga-powershell-plugins'
if (Get-Command 'Use-IcingaPlugins' -ErrorAction SilentlyContinue) {
Use-IcingaPlugins;
}
# This function will allow us to load this entire module including possible
# actions, making it available within our shell environment
# First load our custom modules
Import-IcingaLib '\' -Init -Custom;
Import-IcingaLib '\' -Init;
2019-10-05 15:54:24 -04:00
if ($LibOnly -eq $FALSE) {
Register-IcingaEventLog;
2019-10-05 15:54:24 -04:00
$global:IcingaThreads = [hashtable]::Synchronized(@{});
$global:IcingaThreadContent = [hashtable]::Synchronized(@{});
$global:IcingaThreadPool = [hashtable]::Synchronized(@{});
$global:IcingaTimers = [hashtable]::Synchronized(@{});
2019-10-05 15:54:24 -04:00
$global:IcingaDaemonData = [hashtable]::Synchronized(
@{
'IcingaThreads' = $global:IcingaThreads;
'IcingaThreadContent' = $global:IcingaThreadContent;
'IcingaThreadPool' = $global:IcingaThreadPool;
'IcingaTimers' = $global:IcingaTimers;
2019-10-05 15:54:24 -04:00
'FrameworkRunningAsDaemon' = $Daemon;
'DebugMode' = $DebugMode;
2019-10-05 15:54:24 -04:00
}
);
} else {
# This will fix the debug mode in case we are only using Libs
# without any other variable content and daemon handling
if ($null -eq $global:IcingaDaemonData) {
$global:IcingaDaemonData = [hashtable]::Synchronized(@{});
}
if ($global:IcingaDaemonData.ContainsKey('DebugMode') -eq $FALSE) {
$global:IcingaDaemonData.DebugMode = $DebugMode;
}
if ($global:IcingaDaemonData.ContainsKey('FrameworkRunningAsDaemon') -eq $FALSE) {
$global:IcingaDaemonData.FrameworkRunningAsDaemon = $Daemon;
}
2019-10-05 15:54:24 -04:00
}
# Enable DebugMode in case it is enabled in our config
if (Get-IcingaFrameworkDebugMode) {
Enable-IcingaFrameworkDebugMode;
$DebugMode = $TRUE;
}
$EventLogMessages = Invoke-IcingaNamespaceCmdlets -Command 'Register-IcingaEventLogMessages*';
foreach ($entry in $EventLogMessages.Values) {
foreach ($event in $entry.Keys) {
Add-IcingaHashtableItem -Hashtable $global:IcingaEventLogEnums `
-Key $event `
-Value $entry[$event] | Out-Null;
}
}
}
2019-07-18 11:52:21 -04:00
function Import-IcingaLib()
{
param(
[Parameter(
Position=0,
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)
]
[String]$Lib,
# The Force Reload will remove the module in case it's loaded and reload it to track
# possible development changes without having to create new PowerShell environments
[Switch]$ForceReload,
[switch]$Init,
2019-10-31 12:24:30 -04:00
[switch]$Custom,
[switch]$WriteManifests
2019-07-18 11:52:21 -04:00
);
# This is just to only allow a global loading of the module. Import-IcingaLib is ignored on every other
# location. It is just there to give a basic idea within commands, of which functions are used
if ($Init -eq $FALSE) {
return;
}
if ($Custom) {
[string]$directory = Join-Path -Path $PSScriptRoot -ChildPath 'custom\';
} else {
[string]$directory = Join-Path -Path $PSScriptRoot -ChildPath 'lib\';
}
2019-07-18 11:52:21 -04:00
[string]$module = Join-Path -Path $directory -ChildPath $Lib;
[string]$moduleName = '';
2019-07-18 11:52:21 -04:00
$ListOfLoadedModules = Get-Module | Select-Object Name;
2019-07-18 11:52:21 -04:00
# Load modules from directory
if ((Test-Path $module -PathType Container)) {
Get-ChildItem -Path $module -Recurse -Filter *.psm1 |
ForEach-Object {
[string]$modulePath = $_.FullName;
$moduleName = $_.Name.Replace('.psm1', '');
2019-07-18 11:52:21 -04:00
2019-07-23 03:17:11 -04:00
if ($ListOfLoadedModules -like "*$moduleName*") {
if ($ForceReload) {
Remove-Module -Name $moduleName
2019-07-23 03:17:11 -04:00
Import-Module ([string]::Format('{0}', $modulePath)) -Global;
}
2019-07-23 03:17:11 -04:00
} else {
Import-Module ([string]::Format('{0}', $modulePath)) -Global;
2019-10-31 12:24:30 -04:00
if ($WriteManifests) {
Publish-IcingaModuleManifests -Module $moduleName;
}
}
}
} else {
$module = $module.Replace('.psm1', ''); # Cut possible .psm1 ending
$moduleName = $module.Split('\')[-1]; # Get the last element
2019-07-18 11:52:21 -04:00
if ($ForceReload) {
if ($ListOfLoadedModules -Like "*$moduleName*") {
Remove-Module -Name $moduleName;
2019-07-18 11:52:21 -04:00
}
}
Import-Module ([string]::Format('{0}.psm1', $module)) -Global;
2019-10-31 12:24:30 -04:00
if ($WriteManifests) {
Publish-IcingaModuleManifests -Module $moduleName;
}
2019-07-18 11:52:21 -04:00
}
}
2019-10-28 12:03:19 -04:00
function Publish-IcingaModuleManifests()
2018-11-06 11:14:49 -05:00
{
param(
2019-10-28 12:03:19 -04:00
[string]$Module
2018-11-06 11:14:49 -05:00
);
2019-10-28 12:03:19 -04:00
[string]$ManifestDir = Join-Path -Path $PSScriptRoot -ChildPath 'manifests';
[string]$ModuleFile = [string]::Format('{0}.psd1', $Module);
[string]$PSDFile = Join-Path -Path $ManifestDir -ChildPath $ModuleFile;
2018-11-06 11:14:49 -05:00
2019-10-28 12:03:19 -04:00
if (Test-Path $PSDFile) {
2018-11-06 11:14:49 -05:00
return;
}
2019-10-28 12:03:19 -04:00
New-ModuleManifest -path $PSDFile -ModuleVersion 1.0 -Author $env:USERNAME -CompanyName 'Icinga GmbH' -Copyright '(c) 2019 Icinga GmbH. All rights reserved.' -PowerShellVersion 4.0;
$Content = Get-Content $PSDFile;
$NewContent = @();
2018-11-06 11:14:49 -05:00
2019-10-28 12:03:19 -04:00
foreach ($line in $Content) {
if ([string]::IsNullOrEmpty($line)) {
continue;
}
2018-11-06 11:14:49 -05:00
2019-10-28 12:03:19 -04:00
if ($line[0] -eq '#') {
continue;
}
2018-11-06 11:14:49 -05:00
2019-10-28 12:03:19 -04:00
if ($line.Contains('#')) {
$line = $line.Substring(0, $line.IndexOf('#'));
}
2018-11-06 11:14:49 -05:00
2019-10-28 12:03:19 -04:00
$tmpLine = $line;
while ($tmpLine.Contains(' ')) {
$tmpLine = $tmpLine.Replace(' ', '');
}
if ([string]::IsNullOrEmpty($tmpLine)) {
continue;
}
2018-11-06 11:14:49 -05:00
2019-10-28 12:03:19 -04:00
$NewContent += $line;
2018-11-06 11:14:49 -05:00
}
2019-10-28 12:03:19 -04:00
Set-Content -Path $PSDFile -Value $NewContent;
2018-11-06 11:14:49 -05:00
}
function Publish-IcingaEventlogDocumentation()
{
param(
[string]$Namespace,
[string]$OutFile
);
[string]$DocContent = [string]::Format(
'# {0} Eventlog Documentation',
$Namespace
);
$DocContent += New-IcingaNewLine;
$DocContent += New-IcingaNewLine;
$DocContent += "Below you will find a list of EventId's which are exported by this module. The short and detailed message are both written directly into the eventlog. This documentation shall simply provide a summary of available EventId's";
$SortedArray = $IcingaEventLogEnums[$Namespace].Keys.GetEnumerator() | Sort-Object;
foreach ($entry in $SortedArray) {
$entry = $IcingaEventLogEnums[$Namespace][$entry];
$DocContent = [string]::Format(
'{0}{2}{2}## Event Id {1}{2}{2}| Category | Short Message | Detailed Message |{2}| --- | --- | --- |{2}| {3} | {4} | {5} |',
$DocContent,
$entry.EventId,
(New-IcingaNewLine),
$entry.EntryType,
$entry.Message,
$entry.Details
);
}
if ([string]::IsNullOrEmpty($OutFile)) {
Write-Host $DocContent;
} else {
Set-Content -Path $OutFile -Value $DocContent;
}
}
2019-10-28 12:03:19 -04:00
function Get-IcingaPluginDir()
2018-11-06 11:14:49 -05:00
{
2019-10-28 12:03:19 -04:00
return (Join-Path -Path $PSScriptRoot -ChildPath 'lib\plugins\');
2018-11-06 11:14:49 -05:00
}
2019-10-28 12:03:19 -04:00
function Get-IcingaCustomPluginDir()
2018-11-06 11:14:49 -05:00
{
2019-10-28 12:03:19 -04:00
return (Join-Path -Path $PSScriptRoot -ChildPath 'custom\plugins\');
2018-11-06 11:14:49 -05:00
}
2019-10-28 12:03:19 -04:00
function Get-IcingaCacheDir()
2018-11-06 11:14:49 -05:00
{
2019-10-28 12:03:19 -04:00
return (Join-Path -Path $PSScriptRoot -ChildPath 'cache');
2018-11-06 11:14:49 -05:00
}
2019-10-28 12:03:19 -04:00
function Get-IcingaPowerShellConfigDir()
2018-11-06 11:14:49 -05:00
{
2019-10-28 12:03:19 -04:00
return (Join-Path -Path $PSScriptRoot -ChildPath 'config');
2018-11-06 11:14:49 -05:00
}
2019-11-02 07:12:26 -04:00
function Get-IcingaFrameworkRootPath()
{
[string]$Path = $PSScriptRoot;
[int]$Index = $Path.LastIndexOf('\') + 1;
$Path = $Path.Substring(0, $Index);
return $Path;
}
function Get-IcingaPowerShellModuleFile()
{
2019-10-31 12:24:30 -04:00
return (Join-Path -Path $PSScriptRoot -ChildPath 'icinga-powershell-framework.psm1');
}
function Invoke-IcingaCommand()
{
[CmdletBinding()]
param (
$ScriptBlock,
[switch]$SkipHeader = $FALSE
);
Import-LocalizedData `
-BaseDirectory $PSScriptRoot `
-FileName 'icinga-powershell-framework.psd1' `
-BindingVariable IcingaFrameworkData;
# Print a header informing our user that loaded the Icinga Framework with a specific
# version. We can also skip the header by using $SKipHeader
if ([string]::IsNullOrEmpty($ScriptBlock) -And $SkipHeader -eq $FALSE) {
Write-Host '******************************************************';
Write-Host ([string]::Format('** Icinga PowerShell Framework {0}', $IcingaFrameworkData.PrivateData.Version));
Write-Host ([string]::Format('** Copyright {0}', $IcingaFrameworkData.Copyright));
Write-Host '******************************************************';
}
powershell.exe -NoExit -Command {
$Script = $args[0];
$RootPath = $args[1];
# Load our Icinga Framework
Use-Icinga;
# Set the location to the Icinga Framework module folder
Set-Location $RootPath;
# If we added a block to execute, do it right here and exit the shell
# with the last exit code of the command
if ([string]::IsNullOrEmpty($Script) -eq $FALSE) {
Invoke-Command -ScriptBlock ([Scriptblock]::Create($Script));
exit $LASTEXITCODE;
}
# Set our "path" to something different so we know that we loaded the Framework
function prompt {
Write-Host -Object "icinga" -NoNewline;
return "> "
}
} -Args $ScriptBlock, $PSScriptRoot;
}
Set-Alias icinga Invoke-IcingaCommand -Description "Execute Icinga Framework commands in a new PowerShell instance for testing or quick access to data";
Export-ModuleMember -Alias * -Function *;