icinga-powershell-framework icon indicating copy to clipboard operation
icinga-powershell-framework copied to clipboard

Creating own module with 'New-IcingaForWindowsComponent' - module don't load correctly

Open stevie-sy opened this issue 2 years ago • 7 comments

After upgrading and testing 1.10. I have to do some adjustment to ower own module to be also more compatible to (our own) icinga repo. So I tried the (new) command New-IcingaForWindowsComponent to create a new module skeleton.

After editing the skelleton, the the module loads only 'Import-IcingaPowerShellComponent___' no own functions.

So I compared the docs, the plugin-module and the own module and I found following diffrences:

  • In the docs (https://icinga.com/docs/icinga-for-windows/latest/doc/900-Developer-Guide/00-General/) is written, that we have to write our psm1 files for the functions into the Array "NestedModules" in the file icinga-powershell-__.psd1 (like before CodeCaching).
  • But the cmdlet New-IcingaForWindowsComponent is linking the file '.\compiled\icinga-powershell-___.ifw_compilation.psm1' as NestedModule.
  • Comparing the the content of the caching file from the new skelleton and the plugins-module we can find also some diffrences: the code cache file from the own module has an empty function. The code cache file from the plugins module has some code to rewrite the code cache file. If use this code in our own module, the functions of the own module gets loaded

This means there is a discrepancy between the documentation, the result of function New-IcingaForWindowsComponent and the plugin module.

stevie-sy avatar Sep 07 '22 09:09 stevie-sy

Hello,

Thank you for the issue and the details. I will have a closer look on the description and the details. In general, all you need to do is the following:

Create a new component:

 New-IcingaForWindowsComponent -Name 'custom_plugin'

This will create the project as intended. Once done, you can start adding your own providers and plugins code for example and publish the module afterwards:

Publish-IcingaForWindowsComponent -Name 'custom_plugin'

This will update the .psd1 file with all functions which should be available in the public space and reset the plugin cache file to the default state. Functions either placed inside a public or the plugin folder as well as functions with the Global: flag are exported to a new PowerShell instance and should be callable.

LordHepipud avatar Sep 09 '22 10:09 LordHepipud

After some digging through the docs I know where the confusing part starts. The NestedModules variable does not need to be changed anymore, as it will hard-link the cache file which contains all later code. I will review and update the entire docs to explain this properly and enforce the dev tools more for easier usability.

LordHepipud avatar Sep 09 '22 10:09 LordHepipud

sounds goods. But pls control also the cache file. After running the new-IcingaForWindowsComponent-cmdlet, into the cache file is written an empty function (in the docs I didn't found anything what to do with it). So nothing is loaded after importing the module. If I copy the code of the cache file from plugin-module everything is fine.

But what I see yesterday and today the Publish-IcingaForWindowsComponent-cmdlet overwrite this cache file again with the content of an empty function. If I correct it again and run the import-module-cmdlet, the cache file has the same content like after creating the module skellton - an empty function. For me this is something weird.

stevie-sy avatar Sep 09 '22 11:09 stevie-sy

You don't need to copy anything manually. The module handler will create an empty function Import-IcingaPowerShellComponent<modulename>

This function is just present to ensure that once Icinga for Windows loads, all modules and dependencies are present. There is no need to add code into this function or do something with this. It is just for internal handling.

Once a plugin function is added to the plugins function or a provider, you require to publish the module with Publish-IcingaForWindowsComponent -Name '<component name>'to update the .psd1 and reset the cache file.

Once you start a new PowerShell and execute a module function, the cache is created and the function is executed, as long as the function is exported publicly.

You can also use

icinga {
# Your code to test
} -DeveloperMode:

to always reset the cache and rebuild it, to instantly apply changes.

LordHepipud avatar Sep 09 '22 13:09 LordHepipud

I debugged Publish-IcingaForWindowsComponent a little bit and noticed a very strange behavior. But I found the issue. I will described it and helps you.

First of all I defined the required modules like this:

RequiredModules   = @(
        @{ ModuleName = 'icinga-powershell-framework'; ModuleVersion = '1.10.0'; }
    )

Publish-IcingaForWindowsComponent is doing this:

RequiredModules   = @(
        @{ ModuleName = 'icinga-powershell-framework'; ModuleVersion = '1.7.0'; }
    )

same with the the FunctionToExport-Array. From this

FunctionsToExport     = @(
        'Import-IcingaPowerShellComponent__',
        'Invoke-IcingaCheck__',
        'Invoke-IcingaCheck__',
        'Invoke-IcingaCheck__',
    )

Publish-IcingaForWindowsComponent is doing this:

FunctionsToExport     = @(
        'Import-IcingaPowerShellComponent__'
    )

So I ran every code line manually. The funny thing $ManifestContent = Get-Content -Path $ModuleManifest; had the correct file content. But during foreach loop happens something weird, that the content has changed like written above. Why? It's incomprehensible.

It looks like PowerShell had some old information (like the empty module skeleton) in the memory. So the cmdlet generates a wrong manifest and some files were missing in the ZIP. Somehow the problem solved itself. After running the code multiple times, the content of $ManifestScript was correct. So also the Manfifest- and CodeCache files.

So maybe at the beginning of the function should be something like Import-Module $ModuleName -force to be save?

stevie-sy avatar Sep 13 '22 12:09 stevie-sy

ref/NC/762829

danopt avatar Sep 15 '22 12:09 danopt

Have you placed the .psm1 files for the plugins inside the plugins folder or used Global:Invoke-IcingaCheck to make them available for the public?

I tried to duplicate your results without any luck. The publish function, manifest writer and dependencies work as expected in my environments.

LordHepipud avatar Sep 21 '22 09:09 LordHepipud