Created
November 3, 2016 22:17
-
-
Save Jaykul/8ba1fa42111438a802983d0f36ad38da to your computer and use it in GitHub Desktop.
ModuleSpec dependency failure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#.Synopsis | |
# Generate a bunch of test modules to demonstrate ModuleSpec "cyclic dependency" bug | |
#.Example | |
# Write-ModuleSpecRepro | |
# | |
# Uses the default values to create a series of modules which will fail to import | |
#.Example | |
# Write-ModuleSpecRepro -Depth 6 -ModuleSpec First2 | |
# | |
# Creates a series of modules where only two modules have specified the versions of their dependencies, | |
# and yet, they will fail to import. | |
[CmdletBinding(SupportsShouldProcess,ConfirmImpact="High")] | |
param( | |
# How many modules to create. Defaults to 5 | |
# Note that each module depends on the previous modules | |
# and all modules depend on Microsoft.PowerShell.Core | |
$Depth = 5, | |
# A folder path to use to create the modules in (defaults to $Env:Temp\ModuleTest) | |
$TestFolder = $(Join-Path $Env:Temp "ModuleTest"), | |
# A name to use when creating modules (defaults to "Test" so you get "Test1", "Test2", etc) | |
$ModuleNameBase = "Test", | |
# Where to use full ModuleSpec instead of just the module name. | |
# TEST NOTES: | |
# A value of "None" allows you to specify a -Depth over 100 with no errors | |
# A value of "All" or "Last2" causes an error at -Depth 5 | |
# A value of "First2" causes an error at -Depth 6 | |
[ValidateSet("All","None","First2","Last2")] | |
[string]$ModuleSpec = "All" | |
) | |
# Make sure the folder exists (and remember if we created it) | |
$Created = $false | |
if(!(Test-Path $TestFolder)) { | |
$Created = $true | |
$null = mkdir $TestFolder -Force | |
} | |
$TestFolder = Resolve-Path $TestFolder | |
# Update PSModulePath if we need to | |
if($Env:PSModulePath.Split([IO.Path]::DirectorySeparatorChar) -notcontains $TestFolder) { | |
$Env:PSModulePath += ";$TestFolder" | |
} | |
Push-Location $TestFolder | |
$LastModule = @() | |
foreach($Level in 1..$Depth) { | |
$ModuleName = "${ModuleNameBase}$Level" | |
$ModulePath = Join-Path $ModuleName $ModuleName | |
# Make a module: | |
# 1. Make a folder | |
$null = mkdir $ModuleName -Force | |
# 2. Make a script file | |
Set-Content -Path "$ModulePath.psm1" -Value "function Test-$moduleName { Get-Module '$moduleName' } " | |
# 3. Make a manifest | |
if(!$LastModule) { | |
# The first one is simple | |
New-ModuleManifest "$ModulePath.psd1" -RootModule "$ModuleName.psm1" | |
} else { | |
switch($ModuleSpec) { | |
"All" { | |
New-ModuleManifest "$ModulePath.psd1" -RootModule "$ModuleName.psm1" -RequiredModules $LastModule | |
} | |
"None" { | |
New-ModuleManifest "$ModulePath.psd1" -RootModule "$ModuleName.psm1" -RequiredModules $LastModule.ModuleName | |
} | |
"First2" { | |
if($Level -in 2,3) { | |
New-ModuleManifest "$ModulePath.psd1" -RootModule "$ModuleName.psm1" -RequiredModules $LastModule | |
} else { | |
New-ModuleManifest "$ModulePath.psd1" -RootModule "$ModuleName.psm1" -RequiredModules $LastModule.ModuleName | |
} | |
} | |
"Last2" { | |
if($Level -in ($Depth-1),($Depth-2)) { | |
New-ModuleManifest "$ModulePath.psd1" -RootModule "$ModuleName.psm1" -RequiredModules $LastModule | |
} else { | |
New-ModuleManifest "$ModulePath.psd1" -RootModule "$ModuleName.psm1" -RequiredModules $LastModule.ModuleName | |
} | |
} | |
} | |
} | |
# Rig it so each module depends on all the previous modules | |
$LastModule += @{ ModuleName = $ModuleName; ModuleVersion = '1.0' } | |
} | |
Get-Module $ModuleNameBase* -List | Format-Table ModuleType, Name, Version, RequiredModules -AutoSize | |
try { | |
$null = Import-Module "${ModuleNameBase}$Depth" -PassThru | |
Write-Warning "Success!" | |
Remove-Module $ModuleNameBase* | |
& "Test-${ModuleNameBase}$Depth" | |
} catch { | |
Write-Warning "Failure!" | |
Write-Error $_ | |
} finally { | |
# Cleanup | |
Remove-Module $ModuleNameBase* | |
Write-Host "Cleanup?" -ForegroundColor Cyan | |
if($Created) { | |
if($PSCmdlet.ShouldProcess("Removed the folder '$TestFolder' and it's children.", | |
"Should we remove the folder '$TestFolder' and all it's children?", | |
"Removing $TestFolder")) { | |
Pop-Location | |
Remove-Item $TestFolder -Recurse | |
} | |
} else { | |
if(Test-Path $ModuleNameBase*) { | |
foreach($folder in Get-ChildItem $ModuleNameBase* -Directory) { | |
if($PSCmdlet.ShouldProcess("Removed the folder '$($folder.FullName)' and it's children.", | |
"Should we remove the folder '$($folder.FullName)' and all it's children?", | |
"Removing $ModuleNameBase* folders from $pwd")) { | |
Remove-Item $folder -Recurse | |
} | |
} | |
} | |
Pop-Location | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment