lib/core/dev/New-IcingaForWindowsComponent.psm1
<#
.SYNOPSIS Creates an empty new Icinga for Windows module .DESCRIPTION Creates an empty new Icinga for Windows module .PARAMETER Name The name of the Icinga for Windows component and module .PARAMETER Author The author of the module as string .PARAMETER CompanyName The company this module belongs to as string .PARAMETER Copyright The copyright owner of this module as string .PARAMETER ModuleVersion The version of this module as 3 digit version number, eg '1.0.0' .PARAMETER Description The description of what this module does as string .PARAMETER RequiredModules The required modules this module depends on, as an array of hashtables e.g. @( @{ ModuleName = 'icinga-powershell-framework'; ModuleVersion = '1.7.0' } ) .PARAMETER Tags An array of string tags and keywords, for finding this module on the installation list .PARAMETER ProjectUri The url of the project as string .PARAMETER LicenseUri The url to the license as string .PARAMETER ComponentType Defines on how Icinga for Windows will load this module. Valid options are 'plugins', 'apiendpoint', 'daemon', 'library' .PARAMETER OpenInEditor Will open the newly created module within the editor #> function New-IcingaForWindowsComponent() { param ( [string]$Name, [string]$Author = $env:USERNAME, [string]$CompanyName = '', [string]$Copyright = ([string]::Format('(c) {0} {1} | GPL v2.0', [DateTime]::Now.Year, $env:USERNAME)), [Version]$ModuleVersion = '1.0.0', [string]$Description = '', [array]$RequiredModules = @( @{ ModuleName = 'icinga-powershell-framework'; ModuleVersion = '1.7.0' } ), [string[]]$Tags = $Name, [string]$ProjectUri = '', [string]$LicenseUri = '', [ValidateSet('plugins', 'apiendpoint', 'daemon', 'library')] [string]$ComponentType = 'plugins', [switch]$OpenInEditor = $FALSE ); if ([string]::IsNullOrEmpty($Name)) { Write-IcingaConsoleError 'Please specify a name for your new component'; return; } [string]$ModuleName = [string]::Format('icinga-powershell-{0}', $Name.ToLower()); [string]$ModuleRoot = Get-IcingaForWindowsRootPath; [string]$ModuleDir = Join-Path -Path $ModuleRoot -ChildPath $ModuleName; [string]$DaemonFunction = ''; [string]$EndpointName = ''; if (Test-Path $ModuleDir) { Write-IcingaConsoleError 'A component with this name does already exist. Use "Publish-IcingaForWindowsComponent" to apply changes'; return; } $TextInfo = (Get-Culture).TextInfo; New-Item -ItemType Directory -Path $ModuleDir | Out-Null; New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'doc') | Out-Null; New-Item -ItemType File -Path (Join-Path -Path $ModuleDir -ChildPath 'README.md') | Out-Null; New-Item -ItemType File -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('{0}.psm1', $ModuleName))) | Out-Null; switch ($ComponentType) { 'plugins' { New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'plugins') | Out-Null; New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'provider') | Out-Null; New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib') | Out-Null; break; }; 'apiendpoint' { New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'endpoint') | Out-Null; New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib') | Out-Null; [string]$RegisterFunction = ([string]::Format('Register-IcingaRESTAPIEndpoint{0}', $TextInfo.ToTitleCase($Name.ToLower()))); [string]$RegisterFunctionFile = (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('endpoint\{0}.psm1', $RegisterFunction))); [string]$InvokeFunction = ([string]::Format('Invoke-IcingaForWindowsApiRESTCall{0}', $TextInfo.ToTitleCase($Name.ToLower()))); [string]$InvokeFunctionFile = (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('endpoint\{0}.psm1', $InvokeFunction))); Set-Content -Path $RegisterFunctionFile -Value ([string]::Format('function {0}()', $RegisterFunction)); Add-Content -Path $RegisterFunctionFile -Value '{'; Add-Content -Path $RegisterFunctionFile -Value ' # Ensure that we can call our API with a specific endpoint'; Add-Content -Path $RegisterFunctionFile -Value ' return @{'; Add-Content -Path $RegisterFunctionFile -Value ([string]::Format(" 'Alias' = '{0}';", $Name.ToLower())); Add-Content -Path $RegisterFunctionFile -Value ([string]::Format(" 'Command' = '{0}';", $InvokeFunction)); Add-Content -Path $RegisterFunctionFile -Value ' }'; Add-Content -Path $RegisterFunctionFile -Value '}'; Set-Content -Path $InvokeFunctionFile -Value ([string]::Format('function {0}()', $InvokeFunction)); Add-Content -Path $InvokeFunctionFile -Value '{'; Add-Content -Path $InvokeFunctionFile -Value ' # Do not modify the param section'; Add-Content -Path $InvokeFunctionFile -Value ' param ('; Add-Content -Path $InvokeFunctionFile -Value ' [Hashtable]$Request = @{},'; Add-Content -Path $InvokeFunctionFile -Value ' [Hashtable]$Connection = @{},'; Add-Content -Path $InvokeFunctionFile -Value ' $IcingaGlobals,'; Add-Content -Path $InvokeFunctionFile -Value ' [string]$ApiVersion = $null'; Add-Content -Path $InvokeFunctionFile -Value ' );' Add-Content -Path $InvokeFunctionFile -Value ''; Add-Content -Path $InvokeFunctionFile -Value ' $Global:IcingaDaemonData = $IcingaGlobals;'; Add-Content -Path $InvokeFunctionFile -Value ''; Add-Content -Path $InvokeFunctionFile -Value ' # This is the main function for your API endpoint.'; Add-Content -Path $InvokeFunctionFile -Value ' # Also check the developer guide for further details: https://icinga.com/docs/icinga-for-windows/latest/doc/900-Developer-Guide/12-Custom-API-Endpoints/'; Add-Content -Path $InvokeFunctionFile -Value ''; Add-Content -Path $InvokeFunctionFile -Value ' # Send a success message once you connect to the endpoint as example'; Add-Content -Path $InvokeFunctionFile -Value ' Send-IcingaTCPClientMessage -Message ('; Add-Content -Path $InvokeFunctionFile -Value ' New-IcingaTCPClientRESTMessage `'; Add-Content -Path $InvokeFunctionFile -Value ' -HTTPResponse ($IcingaHTTPEnums.HTTPResponseType.Ok) `'; Add-Content -Path $InvokeFunctionFile -Value " -ContentBody 'Api endpoint is installed'"; Add-Content -Path $InvokeFunctionFile -Value ' ) -Stream $Connection.Stream;'; Add-Content -Path $InvokeFunctionFile -Value '}'; $EndpointName = $Name.ToLower(); break; }; 'daemon' { New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'daemon') | Out-Null; New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib') | Out-Null; New-Item ` -ItemType File ` -Path (Join-Path -Path (Join-Path -Path $ModuleDir -ChildPath 'daemon') -ChildPath ([string]::Format('Start-IcingaForWindowsDaemon{0}.psm1', $TextInfo.ToTitleCase($Name.ToLower())))) | Out-Null; $DaemonFunction = ([string]::Format('Start-IcingaForWindowsDaemon{0}', $TextInfo.ToTitleCase($Name.ToLower()))); $DaemonEntry = ([string]::Format('Add-IcingaIcingaForWindowsDaemonEntry{0}', $TextInfo.ToTitleCase($Name.ToLower()))); Set-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ([string]::Format('function {0}()', $DaemonFunction)); Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value '{'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ' # This is the entry point for Icinga for Windows. Use this function for registering your background daemon'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ' # Also check the developer guide for further details: https://icinga.com/docs/icinga-for-windows/latest/doc/900-Developer-Guide/10-Custom-Daemons/'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ''; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ' New-IcingaThreadInstance `'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ( [string]::Format( ' -Name {1}IcingaForWindows_Daemon_{0}{1} `', $TextInfo.ToTitleCase($Name.ToLower()), "'" ) ); Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ' -ThreadPool $IcingaDaemonData.IcingaThreadPool.BackgroundPool `'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ( [string]::Format( ' -Command {0}{1}{0} `', "'", $DaemonEntry ) ); Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ( [string]::Format( ' -CmdParameters @{{ {0}IcingaDaemonData{0} = $global:IcingaDaemonData }} `', "'" ) ); Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value ' -Start;'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonFunction))) -Value '}'; Set-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ([string]::Format('function {0}()', $DaemonEntry)); Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value '{'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' param ('; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' $IcingaDaemonData'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' );'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ''; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' # This is your main daemon function. Add your code inside the WHILE() loop which is executed once the daemon is loaded.'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' # Also check the developer guide for further details: https://icinga.com/docs/icinga-for-windows/latest/doc/900-Developer-Guide/10-Custom-Daemons/'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ''; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' Use-Icinga -LibOnly -Daemon;'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ''; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' while ($TRUE) {'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' # Add your daemon code within this loop'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' Start-Sleep -Seconds 1;'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value ' }'; Add-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('daemon\{0}.psm1', $DaemonEntry))) -Value '}'; break; }; 'library' { New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib') | Out-Null; break; } } Copy-ItemSecure ` -Path (Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'templates\Manifest.psd1.template') ` -Destination (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('{0}.psd1', $ModuleName))) ` -Force | Out-Null; Write-IcingaForWindowsComponentManifest -Name $Name -ModuleConfig @{ '$MODULENAME$' = ([string]::Format('Windows {0}', $Name)); '$GUID$' = (New-Guid); '$ROOTMODULE$' = ([string]::Format('{0}.psm1', $ModuleName)); '$AUTHOR$' = $Author; '$COMPANYNAME$' = $CompanyName; '$COPYRIGHT$' = $Copyright; '$MODULEVERSION$' = $ModuleVersion.ToString(); '$VMODULEVERSION$' = ([string]::Format('v{0}', $ModuleVersion.ToString())); '$DESCRIPTION$' = $Description; '$REQUIREDMODULES$' = $RequiredModules; '$NESTEDMODULES$' = ''; '$TAGS$' = $Tags; '$PROJECTURI$' = $ProjectUri; '$LICENSEURI$' = $LicenseUri; '$COMPONENTTYPE$' = $ComponentType; '$DAEMONFUNCTION$' = $DaemonFunction; '$APIENDPOINT$' = $EndpointName; }; Set-Content ` -Path (Join-Path -Path $ModuleDir -ChildPath 'README.md') ` -Value ([string]::Format('# Icinga for Windows - {0}', $Name)); Add-Content ` -Path (Join-Path -Path $ModuleDir -ChildPath 'README.md') ` -Value ''; Add-Content ` -Path (Join-Path -Path $ModuleDir -ChildPath 'README.md') ` -Value ([string]::Format('This is the auto generated readme for the Icinga for Windows Module `icinga-powershell-{0}`', $Name.ToLower())); Add-Content ` -Path (Join-Path -Path $ModuleDir -ChildPath 'README.md') ` -Value ''; Add-Content ` -Path (Join-Path -Path $ModuleDir -ChildPath 'README.md') ` -Value 'You can start to modify this readme including writing your PowerShell code. Use "Publish-IcingaForWindowsComponent" to generate Icinga 2/Icinga Director configuration files for plugins, auto-generate your configuration and update your module manifest to include all module files you created into the base module.'; Add-Content ` -Path (Join-Path -Path $ModuleDir -ChildPath 'README.md') ` -Value ''; Copy-ItemSecure ` -Path (Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'templates\PSScriptAnalyzerSettings.psd1.template') ` -Destination (Join-Path -Path $ModuleDir -ChildPath 'PSScriptAnalyzerSettings.psd1') ` -Force | Out-Null; Write-IcingaConsoleNotice 'New component "{0}" has been created as module "icinga-powershell-{1}" at location "{2}"' -Objects $Name, $Name.ToLower(), $ModuleDir; Publish-IcingaForWindowsComponent -Name $Name -NoOutput; Import-Module $ModuleDir -Force; Import-Module $ModuleDir -Global -Force; if ($OpenInEditor) { Open-IcingaForWindowsComponentInEditor -Name $Name; } } |