Merge pull request #514 from Icinga:feature/improve_module_isolation

Features: Adds module isolation support

Improves writing and publishing of modules, by ensuring that only certain functions are exported and modules have an own compilation file for loading.

This reduces load times, execution time and in addition allows modules to be isolated from each other, making it impossible to hijack certain code for not exported functions.
This commit is contained in:
Lord Hepipud 2022-04-27 11:21:06 +02:00 committed by GitHub
commit cb613f34c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 392 additions and 104 deletions

View file

@ -28,6 +28,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
* [#495](https://github.com/Icinga/icinga-powershell-framework/pull/495) Adds feature to check the sign status for the local Icinga Agent certificate and notifying the user, in case the certificate is not yet signed by the Icinga CA
* [#496](https://github.com/Icinga/icinga-powershell-framework/pull/496) Improves REST-Api default timeout for internal plugin execution calls from 30s to 120s
* [#498](https://github.com/Icinga/icinga-powershell-framework/pull/498) Adds feature for thread queuing optimisation and frozen thread detection for REST calls
* [#514](https://github.com/Icinga/icinga-powershell-framework/pull/514) Adds support for Icinga for Windows module isolation
## 1.8.0 (2022-02-08)

View file

@ -121,6 +121,18 @@ The following entries are set by default within the `Protected` space:
| DebugMode | Enables the debug mode of Icinga for Windows, printing additional details during operations or tasks |
| Minimal | Changes certain behavior regarding check execution and internal error handling |
## Private and Public Functions
Icinga for Windows will by default only export `Functions` and `Cmdlets`, in case they are either located within the `root .psm1` file, inside a folder called `public` or in case `Global:` is added before the function:
```powershell
function Global:Invoke-MyCommand()
```
In addition, all commands with the alias `Invoke-IcingaCheck` are automatically exported for plugins. This ensures that each module is isolated from each other and functions with the same name can be used within different modules, without overwriting existing ones. This ensures a better integrity of the module itself.
Last but not least, each module is created with a compilation file which is created during the first run of the module and used later on. This ensures en even faster response and reduced load on the system.
## Using Icinga for Windows Dev Tools
Maintaining the entire structure above seems to be complicated at the beginning, especially when considering to update the `NestedModules` section whenever you make changes. To mitigate this, Icinga for Windows provides a bunch of Cmdlets to help with the process
@ -139,7 +151,7 @@ The command ships with a bunch of configurations to modify the created `.psd1` i
### Publish/Update Components
Once you have started to write your own code, you can use the Cmdlet `Publish-IcingaForWindowsComponent` to update the `NestedModules` attribute inside the `.psd1` file automatically, including the documentation in case the module is of type plugin.
Once you have started to write your own code, you can use the Cmdlet `Publish-IcingaForWindowsComponent` to compile and add requires functions for the calls, including the documentation in case the module is of type plugin.
In addition, you ca create a `.zip` file for this module which can be integrated directly into the [Repository Manager](../120-Repository-Manager/01-Add-Repositories.md). By default, created `.zip` files will be created in your home folder, the path can how ever be changed while executing the command.
@ -149,6 +161,8 @@ In addition, you ca create a `.zip` file for this module which can be integrated
| ReleasePackagePath | String | The path on where the `.zip` file will be created in. Defaults to the current users home folder |
| CreateReleasePackage | Switch | This will toggle the `.zip` file creation of the specified package |
Please note that using `Publish-IcingaForWindowsComponent` is mandatory, before you can use the module on target systems. Each Icinga for Windows module is isolated from the general environment and allows to overwrite certain functions locally, inside the module instead of having to worry about them being overwritten on other, critical areas.
### Testing Your Component
In order to validate if your module can be loaded and is working properly, you can use the command `Test-IcingaForWindowsComponent`. In addition to an import check, it will also validate the code styling and give you an overview if and how many issues there are with your code.

View file

@ -0,0 +1,31 @@
function Get-IcingaForWindowsComponentPublicFunctions()
{
param (
$FileObject = $null,
[string]$ModuleName = ''
);
[array]$ExportFunctions = @();
# First first if we are inside a public space
if ((Test-IcingaForWindowsComponentPublicFunctions -FileObject $FileObject -ModuleName $ModuleName) -eq $FALSE) {
$FileData = (Read-IcingaPowerShellModuleFile -File $FileObject.FullName);
foreach ($entry in $FileData.FunctionList) {
if ($entry.Contains('Global:')) {
$ExportFunctions += $entry.Replace('Global:', '');
}
}
$ExportFunctions += $FileData.ExportFunction;
return $ExportFunctions;
}
$FileData = (Read-IcingaPowerShellModuleFile -File $FileObject.FullName);
$ExportFunctions += $FileData.FunctionList;
$ExportFunctions += $FileData.ExportFunction;
# If we are, add all functions we found
return $ExportFunctions;
}

View file

@ -75,13 +75,19 @@ function New-IcingaForWindowsComponent()
'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 'provider\public') | Out-Null;
New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'provider\private') | Out-Null;
New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib') | Out-Null;
New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib\public') | Out-Null;
New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib\private') | 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;
New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib\public') | Out-Null;
New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib\private') | 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)));
@ -124,6 +130,8 @@ function New-IcingaForWindowsComponent()
'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 Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib\public') | Out-Null;
New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib\private') | 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;
@ -182,6 +190,8 @@ function New-IcingaForWindowsComponent()
};
'library' {
New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib') | Out-Null;
New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib\public') | Out-Null;
New-Item -ItemType Directory -Path (Join-Path -Path $ModuleDir -ChildPath 'lib\private') | Out-Null;
break;
}
@ -204,6 +214,9 @@ function New-IcingaForWindowsComponent()
'$DESCRIPTION$' = $Description;
'$REQUIREDMODULES$' = $RequiredModules;
'$NESTEDMODULES$' = '';
'$FUNCTIONSTOEXPORT$' = '';
'$VARIABLESTOEXPORT$' = '';
'$ALIASESTOEXPORT$' = '';
'$TAGS$' = $Tags;
'$PROJECTURI$' = $ProjectUri;
'$LICENSEURI$' = $LicenseUri;

View file

@ -66,28 +66,48 @@ function Publish-IcingaForWindowsComponent()
[ScriptBlock]$ManifestScriptBlock = [ScriptBlock]::Create('return ' + $ManifestScript);
$ModuleManifestData = (& $ManifestScriptBlock);
$ModuleList = @();
$ModuleFiles = Get-ChildItem -Path $ModuleDir -Recurse -Filter '*.psm1';
[array]$FunctionList = @();
[array]$CmdletList = @();
[array]$VariableList = @();
[array]$AliasList = @();
[string]$CompiledFolder = (Join-Path -Path $ModuleDir -ChildPath 'compiled');
[string]$CompiledFile = [string]::Format('{0}.ifw_compilation.psm1', $ModuleName.ToLower());
[string]$CompiledFileInclude = [string]::Format('.\compiled\{0}', $CompiledFile);
[string]$CompiledFilePath = (Join-Path -Path $CompiledFolder -ChildPath $CompiledFile);
foreach ($entry in $ModuleFiles) {
if ($entry.Name -eq ([string]::Format('{0}.psm1', $ModuleName))) {
# Ensure the compilation file never includes itself
if ($entry.FullName -eq $CompiledFilePath) {
continue;
}
$ModuleList += $entry.FullName.Replace($ModuleDir, '.');
$FunctionList += Get-IcingaForWindowsComponentPublicFunctions -FileObject $entry -ModuleName $ModuleName;
$FileConfig = (Read-IcingaPowerShellModuleFile -File $entry.FullName);
$VariableList += $FileConfig.VariableList;
$AliasList += $FileConfig.AliasList;
$CmdletList += $FileConfig.ExportCmdlet;
}
if ((Test-Path -Path $CompiledFolder) -eq $FALSE) {
New-Item -Path $CompiledFolder -ItemType Directory -Force | Out-Null;
}
Copy-ItemSecure -Path (Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'templates\compilation.psm1.template') -Destination $CompiledFilePath -Force | Out-Null;
if ($NoOutput) {
Disable-IcingaFrameworkConsoleOutput;
}
Write-IcingaForWindowsComponentManifest -Name $Name -ModuleList $ModuleList;
Write-IcingaForWindowsComponentManifest -Name $Name -ModuleList @( $CompiledFileInclude ) -FunctionList $FunctionList -VariableList $VariableList -AliasList $AliasList -CmdletList $CmdletList;
if ($ModuleManifestData.PrivateData.Type -eq 'plugins') {
Publish-IcingaPluginConfiguration -ComponentName $Name;
Publish-IcingaPluginDocumentation -ModulePath $ModuleDir;
}
Copy-ItemSecure -Path (Join-Path -Path (Get-IcingaFrameworkRootPath) -ChildPath 'templates\compilation.psm1.template') -Destination $CompiledFilePath -Force | Out-Null;
if ($CreateReleasePackage) {
if ([string]::IsNullOrEmpty($ReleasePackagePath)) {
$ReleasePackagePath = Join-Path -Path $ENV:HOMEDRIVE -ChildPath $ENV:HOMEPATH;

View file

@ -0,0 +1,25 @@
function Test-IcingaForWindowsComponentPublicFunctions()
{
param (
$FileObject = $null,
[string]$ModuleName = ''
);
if ($null -eq $FileObject -Or [string]::IsNullOrEmpty($ModuleName)) {
return $FALSE;
}
# If we load the main .psm1 file of this module, add all functions inside to the public space
if ($FileObject.Name -eq ([string]::Format('{0}.psm1', $ModuleName))) {
return $TRUE;
}
[int]$RelativPathStartIndex = $FileObject.FullName.IndexOf($ModuleName) + $ModuleName.Length;
$ModuleFileRelativePath = $FileObject.FullName.SubString($RelativPathStartIndex, $FileObject.FullName.Length - $RelativPathStartIndex);
if ($ModuleFileRelativePath.Contains('\public\') -Or $ModuleFileRelativePath.Contains('\plugins\') -Or $ModuleFileRelativePath.Contains('\endpoint\') -Or $ModuleFileRelativePath.Contains('\daemon\')) {
return $TRUE;
}
return $FALSE;
}

View file

@ -0,0 +1,84 @@
function Update-IcingaForWindowsManifestArray()
{
param (
[string]$ManifestFile = '',
[array]$ArrayVariableValues = @(),
[string]$ArrayVariableName = ''
);
if ([string]::IsNullOrEmpty($ArrayVariableName)) {
return;
}
# Remove duplicate entries
$ArrayVariableValues = $ArrayVariableValues | Select-Object -Unique;
[array]$ManifestContent = Get-Content -Path $ManifestFile -ErrorAction SilentlyContinue;
if ($null -eq $ManifestContent -Or $ManifestContent.Count -eq 0) {
Write-IcingaConsoleWarning 'The manifest file "{0}" could not be loaded for updating array element "{1}2' -Objects $ManifestFile, $ArrayVariableName;
return;
}
$ContentString = New-Object -TypeName 'System.Text.StringBuilder';
[bool]$UpdatedArrayContent = $FALSE;
foreach ($entry in $ManifestContent) {
[string]$ManifestLine = $entry;
if ($UpdatedArrayContent -And $entry -Like '*)*') {
$UpdatedArrayContent = $FALSE;
continue;
}
if ($UpdatedArrayContent) {
continue;
}
if ($entry -Like ([string]::Format('*{0}*', $ArrayVariableName.ToLower()))) {
if ($entry -NotLike '*)*') {
$UpdatedArrayContent = $TRUE;
}
$ContentString.AppendLine(([string]::Format(' {0} = @(', $ArrayVariableName))) | Out-Null;
if ($ArrayVariableValues.Count -ne 0) {
[array]$NestedModules = (ConvertFrom-IcingaArrayToString -Array $ArrayVariableValues -AddQuotes -UseSingleQuotes).Split(',');
[int]$ModuleIndex = 0;
foreach ($module in $NestedModules) {
if ([string]::IsNullOrEmpty($module)) {
continue;
}
$ModuleIndex += 1;
if ($ModuleIndex -ne $NestedModules.Count) {
if ($ModuleIndex -eq 1) {
$ManifestLine = [string]::Format(' {0},', $module);
} else {
$ManifestLine = [string]::Format(' {0},', $module);
}
} else {
if ($ModuleIndex -eq 1) {
$ManifestLine = [string]::Format(' {0}', $module);
} else {
$ManifestLine = [string]::Format(' {0}', $module);
}
}
$ContentString.AppendLine($ManifestLine) | Out-Null;
}
}
$ContentString.AppendLine(' )') | Out-Null;
continue;
}
if ([string]::IsNullOrEmpty($ManifestLine.Replace(' ', '')) -Or $ManifestLine -eq "`r`n" -Or $ManifestLine -eq "`n") {
continue;
}
$ContentString.AppendLine($ManifestLine) | Out-Null;
}
Write-IcingaFileSecure -File $ManifestFile -Value $ContentString.ToString();
}

View file

@ -0,0 +1,60 @@
function Write-IcingaForWindowsComponentCompilationFile()
{
param (
[string]$ScriptRootPath = '',
[string]$CompiledFilePath = ''
);
# Get the current location and leave this folder
Set-Location -Path $ScriptRootPath;
Set-Location -Path '..';
# Store the location of the current file
# Now as we are inside the module root, get the name of the module and the path
[string]$ModulePath = Get-Location;
[string]$ModuleName = $ModulePath.Split('\')[-1];
# Fetch all '.psm1' files from this module content
[array]$ModuleFiles = Get-ChildItem -Path $ModulePath -Recurse -Filter '*.psm1';
# Get all public functions
[array]$FunctionList = @();
[array]$VariableList = @();
[array]$AliasList = @();
[array]$CmdletList = @();
# Variable to store all of our module files
[string]$CompiledModule = '';
foreach ($entry in $ModuleFiles) {
# Ensure the compilation file never includes itself
if ($entry.FullName -eq $CompiledFilePath) {
continue;
}
$FunctionList += Get-IcingaForWindowsComponentPublicFunctions -FileObject $entry -ModuleName $ModuleName;
$FileConfig = (Read-IcingaPowerShellModuleFile -File $entry.FullName);
$VariableList += $FileConfig.VariableList;
$AliasList += $FileConfig.AliasList;
$CmdletList += $FileConfig.ExportCmdlet;
$CompiledModule += (Get-Content -Path $entry.FullName -Raw -Encoding 'UTF8');
$CompiledModule += "`r`n";
}
if ((Test-Path -Path $CompiledFilePath) -eq $FALSE) {
New-Item -Path $CompiledFilePath -ItemType File -Force | Out-Null;
}
$CompiledModule += "`r`n";
$CompiledModule += [string]::Format(
"Export-ModuleMember -Cmdlet @( {0} ) -Function @( {1} ) -Variable @( {2} ) -Alias @( {3} );",
((ConvertFrom-IcingaArrayToString -Array ($CmdletList | Select-Object -Unique) -AddQuotes -UseSingleQuotes)),
((ConvertFrom-IcingaArrayToString -Array ($FunctionList | Select-Object -Unique) -AddQuotes -UseSingleQuotes)),
((ConvertFrom-IcingaArrayToString -Array ($VariableList | Select-Object -Unique) -AddQuotes -UseSingleQuotes)),
((ConvertFrom-IcingaArrayToString -Array ($AliasList | Select-Object -Unique) -AddQuotes -UseSingleQuotes))
);
Set-Content -Path $CompiledFilePath -Value $CompiledModule -Encoding 'UTF8';
Import-Module -Name $ModulePath -Force;
Import-Module -Name $ModulePath -Force -Global;
}

View file

@ -17,7 +17,11 @@ function Write-IcingaForWindowsComponentManifest()
param (
[string]$Name,
[hashtable]$ModuleConfig = @{ },
[array]$ModuleList = @()
[array]$ModuleList = @(),
[array]$FunctionList = @(),
[array]$CmdletList = @(),
[array]$VariableList = @(),
[array]$AliasList = @()
);
if ([string]::IsNullOrEmpty($Name)) {
@ -75,71 +79,14 @@ function Write-IcingaForWindowsComponentManifest()
$ContentString.Clear() | Out-Null;
[array]$ManifestContent = Get-Content -Path (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('{0}.psd1', $ModuleName)));
[string]$ManifestFile = (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('{0}.psd1', $ModuleName)));
if ($null -eq $ManifestContent -Or $ManifestContent.Count -eq 0) {
Write-IcingaConsoleWarning 'The manifest file of module "{0}" could not be loaded for updating NestedModules' -Objects $ModuleName;
return;
}
Update-IcingaForWindowsManifestArray -ArrayVariableName 'NestedModules' -ArrayVariableValues $ModuleList -ManifestFile $ManifestFile;
Update-IcingaForWindowsManifestArray -ArrayVariableName 'FunctionsToExport' -ArrayVariableValues $FunctionList -ManifestFile $ManifestFile;
Update-IcingaForWindowsManifestArray -ArrayVariableName 'CmdletsToExport' -ArrayVariableValues $CmdletList -ManifestFile $ManifestFile;
Update-IcingaForWindowsManifestArray -ArrayVariableName 'VariablesToExport' -ArrayVariableValues $VariableList -ManifestFile $ManifestFile;
Update-IcingaForWindowsManifestArray -ArrayVariableName 'AliasesToExport' -ArrayVariableValues $AliasList -ManifestFile $ManifestFile;
[bool]$UpdateNestedModules = $FALSE;
foreach ($entry in $ManifestContent) {
[string]$ManifestLine = $entry;
if ($UpdateNestedModules -And $entry -Like '*)*') {
$UpdateNestedModules = $FALSE;
continue;
}
if ($UpdateNestedModules) {
continue;
}
if ($entry -Like '*nestedmodules*') {
if ($entry -NotLike '*)*') {
$UpdateNestedModules = $TRUE;
}
$ContentString.AppendLine(' NestedModules = @(') | Out-Null;
if ($ModuleList.Count -ne 0) {
[array]$NestedModules = (ConvertFrom-IcingaArrayToString -Array $ModuleList -AddQuotes -UseSingleQuotes).Split(',');
[int]$ModuleIndex = 0;
foreach ($module in $NestedModules) {
if ([string]::IsNullOrEmpty($module)) {
continue;
}
$ModuleIndex += 1;
if ($ModuleIndex -ne $NestedModules.Count) {
if ($ModuleIndex -eq 1) {
$ManifestLine = [string]::Format(' {0},', $module);
} else {
$ManifestLine = [string]::Format(' {0},', $module);
}
} else {
if ($ModuleIndex -eq 1) {
$ManifestLine = [string]::Format(' {0}', $module);
} else {
$ManifestLine = [string]::Format(' {0}', $module);
}
}
$ContentString.AppendLine($ManifestLine) | Out-Null;
}
}
$ContentString.AppendLine(' )') | Out-Null;
continue;
}
if ([string]::IsNullOrEmpty($ManifestLine.Replace(' ', '')) -Or $ManifestLine -eq "`r`n" -Or $ManifestLine -eq "`n") {
continue;
}
$ContentString.AppendLine($ManifestLine) | Out-Null;
}
Write-IcingaFileSecure -File (Join-Path -Path $ModuleDir -ChildPath ([string]::Format('{0}.psd1', $ModuleName))) -Value $ContentString.ToString();
Import-Module -Name $ManifestFile -Force;
Import-Module -Name $ManifestFile -Force -Global;
}

View file

@ -43,6 +43,10 @@ function Get-IcingaJEAConfiguration()
$ModuleFileContent = '';
foreach ($PSFile in $ModuleFiles) {
if ($PSFile.Name.ToLower() -eq ([string]::Format('{0}.ifw_compilation.psm1', $module.Name))) {
continue;
}
$DeserializedFile = Read-IcingaPowerShellModuleFile -File $PSFile.FullName;
$RawModuleContent = $DeserializedFile.NormalisedContent;

View file

@ -19,6 +19,10 @@ function Read-IcingaPowerShellModuleFile()
[string]$RegexPattern = '';
[array]$CommandList = @();
[array]$FunctionList = @();
[array]$VariableList = @();
[array]$AliasList = @();
[array]$ExportFunctionList = @();
[array]$ExportCmdletList = @();
[hashtable]$CmdCache = @{ };
[hashtable]$FncCache = @{ };
[int]$Index = 0;
@ -26,6 +30,12 @@ function Read-IcingaPowerShellModuleFile()
[bool]$ThreadFetchNext = $FALSE;
[bool]$ShellCommand = $FALSE;
[bool]$ShellGroupStart = $FALSE;
[bool]$BeginExportMember = $FALSE;
[bool]$BeginExportFunc = $FALSE;
[bool]$BeginExportCmdlet = $FALSE;
[bool]$BeginExportVar = $FALSE;
[bool]$BeginExportAlias = $FALSE;
[bool]$BeginReadExport = $FALSE;
foreach ($entry in $PSParser) {
if ($entry.Type -eq 'Comment') {
@ -36,6 +46,10 @@ function Read-IcingaPowerShellModuleFile()
$CmdCache.Add($entry.Content, 0);
}
if ($entry.Content.ToLower() -eq 'export-modulemember') {
$BeginExportMember = $TRUE;
}
# We need to include commands we call with New-IcingaThreadInstance e.g.
# => New-IcingaThreadInstance -Name "Main" -ThreadPool (Get-IcingaThreadPool -Name 'MainPool') -Command 'Add-IcingaForWindowsDaemon' -Start;
if ($entry.Content.ToLower() -eq 'new-icingathreadinstance') {
@ -54,6 +68,52 @@ function Read-IcingaPowerShellModuleFile()
$ShellCommand = $TRUE;
}
if ($BeginExportMember) {
if ($entry.Type -eq 'NewLine' -Or ($entry.Type -eq 'StatementSeparator' -And $entry.Content -eq ';')) {
$BeginExportMember = $FALSE;
}
if ($BeginExportVar -Or $BeginExportAlias -Or $BeginExportFunc -Or $BeginExportCmdlet) {
if ($BeginReadExport) {
if ($entry.Type -ne 'String' -And ($entry.Type -ne 'Operator' -And $entry.Content -ne ',')) {
$BeginReadExport = $FALSE;
$BeginExportVar = $FALSE;
$BeginExportAlias = $FALSE;
$BeginExportFunc = $FALSE;
$BeginExportCmdlet = $FALSE;
}
}
if ($entry.Type -eq 'String') {
$BeginReadExport = $TRUE;
if ($BeginExportVar) {
$VariableList += $entry.Content;
}
if ($BeginExportAlias) {
$AliasList += $entry.Content;
}
if ($BeginExportFunc) {
$ExportFunctionList += $entry.Content;
}
if ($BeginExportCmdlet) {
$ExportCmdletList += $entry.Content;
}
}
}
# Read -Variable argument
if ($entry.Type -eq 'CommandParameter' -And $entry.Content.ToLower() -eq '-variable') {
$BeginExportVar = $TRUE;
}
if ($entry.Type -eq 'CommandParameter' -And $entry.Content.ToLower() -eq '-alias') {
$BeginExportAlias = $TRUE;
}
if ($entry.Type -eq 'CommandParameter' -And $entry.Content.ToLower() -eq '-function') {
$BeginExportFunc = $TRUE;
}
if ($entry.Type -eq 'CommandParameter' -And $entry.Content.ToLower() -eq '-cmdlet') {
$BeginExportCmdlet = $TRUE;
}
}
# If we reached -Command for New-IcingaThreadInstance, check for the String element and add its value to our function list e.g.
# => Add-IcingaForWindowsDaemon
if ($ThreadFetchNext) {
@ -113,5 +173,9 @@ function Read-IcingaPowerShellModuleFile()
'RawContent' = $FileContent;
'CommandList' = $CommandList;
'FunctionList' = $FunctionList;
'VariableList' = $VariableList;
'AliasList' = $AliasList;
'ExportFunction' = $ExportFunctionList;
'ExportCmdlet' = $ExportCmdletList;
};
}

View file

@ -13,10 +13,16 @@
NestedModules = @(
$NESTEDMODULES$
)
FunctionsToExport = @( '*' )
FunctionsToExport = @(
$FUNCTIONSTOEXPORT$
)
CmdletsToExport = @( '*' )
VariablesToExport = @( '*' )
AliasesToExport = @( '*' )
VariablesToExport = @(
$VARIABLESTOEXPORT$
)
AliasesToExport = @(
$ALIASESTOEXPORT$
)
PrivateData = @{
PSData = @{
Tags = @( $TAGS$ )

View file

@ -0,0 +1,19 @@
<#
Icinga for Windows Component compilation file.
Will be overwritten to defaults with every update and contains
all code pre-compiled for faster execution and for providing
private/public commands.
Fetches the current module and file location, reads all .psm1 files and compiles them into one large environment
#>
if ($null -eq (Get-Command -Name 'Write-IcingaForWindowsComponentCompilationFile' -ErrorAction SilentlyContinue)) {
Write-Host '[' -NoNewline;
Write-Host 'Error' -ForegroundColor Red -NoNewline;
Write-Host ([string]::Format(']: Failed to compile Icinga for Windows component at location "{0}", because the required function "Write-IcingaForWindowsComponentCompilationFile" is not installed. Please ensure Icinga PowerShell Framework v1.9.0 or later is installed and try again.', $MyInvocation.MyCommand.Path));
return;
}
Write-IcingaForWindowsComponentCompilationFile `
-ScriptRootPath $PSScriptRoot `
-CompiledFilePath ($MyInvocation.MyCommand.Path);