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
2018-12-06 12:21:55 -05:00
Install-Icinga
2018-11-06 11:14:49 -05:00
. NOTES
#>
2019-07-22 06:41:07 -04:00
function Use-Icinga ( )
{
2019-10-05 15:54:24 -04:00
param (
2020-03-24 09:04:41 -04:00
[ switch ] $LibOnly = $FALSE ,
[ switch ] $Daemon = $FALSE ,
[ switch ] $DebugMode = $FALSE
2019-10-05 15:54:24 -04:00
) ;
2019-11-03 05:59:08 -05: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 ;
}
2019-07-22 06:41:07 -04:00
# This function will allow us to load this entire module including possible
# actions, making it available within our shell environment
2019-10-06 18:04:30 -04:00
# First load our custom modules
Import-IcingaLib '\' -Init -Custom ;
2019-09-25 14:22:44 -04:00
Import-IcingaLib '\' -Init ;
2019-10-05 15:54:24 -04:00
if ( $LibOnly -eq $FALSE ) {
2020-03-24 09:04:41 -04:00
Register-IcingaEventLog ;
2019-10-05 15:54:24 -04:00
$global:IcingaThreads = [ hashtable ] :: Synchronized ( @ { } ) ;
$global:IcingaThreadContent = [ hashtable ] :: Synchronized ( @ { } ) ;
$global:IcingaThreadPool = [ hashtable ] :: Synchronized ( @ { } ) ;
$global:IcingaDaemonData = [ hashtable ] :: Synchronized (
@ {
'IcingaThreads' = $global:IcingaThreads ;
'IcingaThreadContent' = $global:IcingaThreadContent ;
'IcingaThreadPool' = $global:IcingaThreadPool ;
'FrameworkRunningAsDaemon' = $Daemon ;
2020-03-24 09:04:41 -04:00
'DebugMode' = $DebugMode ;
2019-10-05 15:54:24 -04:00
}
) ;
2020-03-25 17:28:54 -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
}
2020-03-27 11:39:47 -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-22 06:41:07 -04:00
}
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
2019-09-25 14:22:44 -04:00
[ Switch ] $ForceReload ,
2019-10-06 18:04:30 -04:00
[ switch ] $Init ,
2019-10-31 12:24:30 -04:00
[ switch ] $Custom ,
[ switch ] $WriteManifests
2019-07-18 11:52:21 -04:00
) ;
2019-09-25 14:22:44 -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 ;
}
2019-10-06 18:04:30 -04:00
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 ;
2019-07-22 06:41:07 -04:00
[ string ] $moduleName = '' ;
2019-07-18 11:52:21 -04:00
2019-07-22 06:41:07 -04:00
$ListOfLoadedModules = Get-Module | Select-Object Name ;
2019-07-18 11:52:21 -04:00
2019-07-22 06:41:07 -04:00
# Load modules from directory
if ( ( Test-Path $module -PathType Container ) ) {
2019-09-25 14:22:44 -04:00
2019-07-22 06:41:07 -04:00
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 ) {
2019-07-22 06:41:07 -04:00
Remove-Module -Name $moduleName
2019-07-23 03:17:11 -04:00
Import-Module ( [ string ] :: Format ( '{0}' , $modulePath ) ) -Global ;
2019-07-22 06:41:07 -04:00
}
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 ;
}
2019-07-22 06:41:07 -04:00
}
}
} 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 ) {
2019-07-22 06:41:07 -04:00
if ( $ListOfLoadedModules -Like " * $moduleName * " ) {
Remove-Module -Name $moduleName ;
2019-07-18 11:52:21 -04:00
}
}
2019-07-22 06:41:07 -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
}
2020-03-28 13:58:14 -04: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-10-31 08:43:20 -04: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 ;
}
2019-10-31 08:43:20 -04:00
function Get-IcingaPowerShellModuleFile ( )
{
2019-10-31 12:24:30 -04:00
return ( Join-Path -Path $PSScriptRoot -ChildPath 'icinga-powershell-framework.psm1' ) ;
2019-10-31 08:43:20 -04:00
}
2020-08-03 05:15:15 -04:00
function Invoke-IcingaCommand ( )
{
[ CmdletBinding ( ) ]
param (
2020-08-03 05:46:56 -04:00
$ScriptBlock ,
[ switch ] $SkipHeader = $FALSE
2020-08-03 05:15:15 -04:00
) ;
2020-08-03 06:29:28 -04:00
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
2020-08-03 08:58:50 -04:00
if ( [ string ] :: IsNullOrEmpty ( $ScriptBlock ) -And $SkipHeader -eq $FALSE ) {
2020-08-03 06:29:28 -04:00
Write-Host '******************************************************' ;
Write-Host ( [ string ] :: Format ( '** Icinga PowerShell Framework {0}' , $IcingaFrameworkData . PrivateData . Version ) ) ;
Write-Host ( [ string ] :: Format ( '** Copyright {0}' , $IcingaFrameworkData . Copyright ) ) ;
Write-Host '******************************************************' ;
}
2020-08-03 05:15:15 -04:00
powershell . exe -NoExit -Command {
2020-08-03 06:29:28 -04:00
$Script = $args [ 0 ] ;
$RootPath = $args [ 1 ] ;
2020-08-03 05:46:56 -04:00
# Load our Icinga Framework
2020-08-03 05:15:15 -04:00
Use-Icinga ;
2020-08-03 05:46:56 -04:00
# 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
2020-08-03 05:15:15 -04:00
if ( [ string ] :: IsNullOrEmpty ( $Script ) -eq $FALSE ) {
Invoke-Command -ScriptBlock ( [ Scriptblock ] :: Create ( $Script ) ) ;
exit $LASTEXITCODE ;
}
2020-08-03 05:46:56 -04:00
2020-08-03 05:15:15 -04:00
# Set our "path" to something different so we know that we loaded the Framework
function prompt {
Write-Host -Object " icinga " -NoNewline ;
return " > "
}
2020-08-03 06:29:28 -04:00
} -Args $ScriptBlock , $PSScriptRoot ;
2020-08-03 05:15:15 -04:00
}
Set-Alias icinga Invoke-IcingaCommand -Description " Execute Icinga Framework commands in a new PowerShell instance for testing or quick access to data " ;
2020-08-03 11:06:06 -04:00
Export-ModuleMember -Alias * -Function * ;