Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pode imports modules fail if modules use RequiredModules dependency (Pode.Web) #1046

Closed
ili101 opened this issue Dec 14, 2022 · 4 comments · Fixed by #1074
Closed

Pode imports modules fail if modules use RequiredModules dependency (Pode.Web) #1046

ili101 opened this issue Dec 14, 2022 · 4 comments · Fixed by #1074
Assignees
Labels
Milestone

Comments

@ili101
Copy link
Contributor

ili101 commented Dec 14, 2022

Pode by default loads all modules automatically. If modules psd1 files are using RequiredModules, and the modules loaded in the session are not in the PSModulePath, depending on the "random" load order they may fail with error:

Import-Module: C:\Users\illym\Documents\PowerShell\ModulesManual\Pode\2.7.2\Private\Helpers.ps1:912:17
Line |
 912 |  …     $null = Import-Module $path -DisableNameChecking -Scope Global -E …
     |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The required module 'Pode' is not loaded. Load the module or remove the module from 'RequiredModules' in the file
     | 'C:\Users\illym\Documents\PowerShell\ModulesManual\Pode.Web\0.8.2\Pode.Web.psd1'.

Unlike 2 external modules that will error depending on the import order, in particular Pode.Web\0.8.2 errors consistently in this situation (as Pode itself is excluded from the auto import or imported last?).

Steps To Reproduce

$Path = Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'PowerShell\ModulesManual'
Save-Module -Name 'Pode' -Path $Path
Save-Module -Name 'Pode.Web' -Path $Path
Save-Module -Name 'Pode.Kestrel' -Path $Path

Import-Module -Name (Join-Path $Path 'Pode')
Import-Module -Name (Join-Path $Path 'Pode.Web')
Import-Module -Name (Join-Path $Path 'Pode.Kestrel')

# Workaround:
# $env:PSModulePath = $env:PSModulePath + ($IsWindows ? ';' : ':') + $Path

Start-PodeServer -Threads 3 {
    Add-PodeEndpoint -Address localhost -Port 8092 -Protocol Http
}

Platform

  • OS: Windows/Linux
  • Versions:
    • Pode: 2.7.2
    • PowerShell: 7.3.1
@Badgerati
Copy link
Owner

The commits above should fix the module loading order for modules that use RequiredModules.

For the loading of Pode when it's saved to non-PSModulePath directory, this was more interesting. Pode is actually loaded as the very first module in the runspaces, but it's done so via [initialsessionstate]::ImportPSModule(...). While this method does accept a path to the module, it annoyingly only accepts .psm1 files. This causes the imported Pode module to have a version of 0.0 within the runspaces - which obviously doesn't match to Pode.Web's 2.6.0 requirement.

When Pode starts importing the other module's into it's runspaces, Pode.Web will then force re-import the Pode module if it's found at one of the paths from PSModulePath (as you found).

What I've done is to check if the Pode module being used is not from one of the PSModulePaths, and if the "version" is "0.0". If this is the case, a second forced import is done before all other modules for Pode, to import the correct psd1 so the version matches.

It's not eloquent by any means 😂 and should only affect anyone loading Pode from a non-PSModulePath location. I did try dynamically updating PSModulePath but for some reason it just didn't want to work for me - it kept failing on "cannot find version". The way implemented is arguably a little better, as it will import the module from the originally specified location, and not the first path in PSModulePath that has a Pode module in it.

@ili101
Copy link
Contributor Author

ili101 commented Jan 22, 2023

It works with psd1 https://github.com/ili101/Pode/commits/Issue-1046
The problem is that in the runspace scope we expose all the internal functions to the "user"/"pode '.' scripts" by using the psm1.
When loading it with the psd1 we need to either make the functions public or do something like:
. (Get-Module -Name Pode) { <private function> } else you get a lot of not fund functions 500 errors.

@Badgerati
Copy link
Owner

Interesting, when I tried I got an "invalid file error" rather than a "function not found". I'll try again later, must've been doing something stupid.

If it loads psd1 files then, I wonder if we could have a second Pode.Internal.psd1 file that uses the same Pode.psm1 but this time that psd1 allows everything to export - unlike the main Pode.psd1. Then in the [initialsessionstate] we import Pode.psd1 first then Pode.Internal.psd1 🤔

@Badgerati
Copy link
Owner

Hi @ili101, I tried again and loading via psd1 worked! I must've been doing something daft before.

I tried with a second Pode.Internal.psd1 file and while it does work, since it references the same Pode.psm1 file PowerShell remove the Pode module imported with Pode.Internal instead.

What I've done in the above commit is add the new Pode.Internal.psd1 but also a Pode.Internal.psm1 for loading all functions. Tested with some of the examples, and Pode.Web examples, and works.

@Badgerati Badgerati self-assigned this Jan 27, 2023
@Badgerati Badgerati added this to the 2.8.1 milestone Jan 27, 2023
@Badgerati Badgerati modified the milestones: 2.8.1, 2.8.0 Jan 27, 2023
@Badgerati Badgerati moved this from Backlog to In Progress in 🚀 Pode Roadmap Jan 27, 2023
@github-project-automation github-project-automation bot moved this from In Progress to Done in 🚀 Pode Roadmap Feb 1, 2023
@Badgerati Badgerati mentioned this issue Feb 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants