mirror of
https://github.com/Icinga/icinga-powershell-framework.git
synced 2025-12-21 07:10:15 -05:00
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:
commit
cb613f34c5
13 changed files with 392 additions and 104 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
84
lib/core/dev/Update-IcingaForWindowsManifestArray.psm1
Normal file
84
lib/core/dev/Update-IcingaForWindowsManifestArray.psm1
Normal 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();
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,10 +13,16 @@
|
|||
NestedModules = @(
|
||||
$NESTEDMODULES$
|
||||
)
|
||||
FunctionsToExport = @( '*' )
|
||||
FunctionsToExport = @(
|
||||
$FUNCTIONSTOEXPORT$
|
||||
)
|
||||
CmdletsToExport = @( '*' )
|
||||
VariablesToExport = @( '*' )
|
||||
AliasesToExport = @( '*' )
|
||||
VariablesToExport = @(
|
||||
$VARIABLESTOEXPORT$
|
||||
)
|
||||
AliasesToExport = @(
|
||||
$ALIASESTOEXPORT$
|
||||
)
|
||||
PrivateData = @{
|
||||
PSData = @{
|
||||
Tags = @( $TAGS$ )
|
||||
|
|
|
|||
19
templates/compilation.psm1.template
Normal file
19
templates/compilation.psm1.template
Normal 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);
|
||||
Loading…
Reference in a new issue