From e35e17a04dea99a56123908cda4f29444d2aaaf3 Mon Sep 17 00:00:00 2001 From: Kyle Ruddy Date: Thu, 10 Jan 2019 09:44:58 -0500 Subject: [PATCH] Update Save-PowerCLI.ps1 Updating function with v2 additions: - Dynamic RequiredVersion parameter - Simple parameter to handle the nested version folders - Address the potential of downloading multiple module folders twice --- Scripts/Save-PowerCLI.ps1 | 202 +++++++++++++++++++++++++++----------- 1 file changed, 146 insertions(+), 56 deletions(-) diff --git a/Scripts/Save-PowerCLI.ps1 b/Scripts/Save-PowerCLI.ps1 index 8aa3230..e9127bc 100644 --- a/Scripts/Save-PowerCLI.ps1 +++ b/Scripts/Save-PowerCLI.ps1 @@ -1,57 +1,147 @@ function Save-PowerCLI { -<# -.SYNOPSIS - Function which can be used to easily download specific versions of PowerCLI from an online gallery -.DESCRIPTION - Downloads a specific version of PowerCLI and all the dependencies at the appropriate version -.NOTES - Author: 1.0 - Dimitar Milov -.PARAMETER RequiredVersion - Specify the PowerCLI version -.PARAMETER Path - Directory path where the modules should be downloaded -.PARAMETER Repository - Repository to access the PowerCLI modules -.EXAMPLE - Save-PowerCLI -RequiredVersion '10.0.0.7895300' -Path .\Downloads\ - Downloads PowerCLI 10.0.0 to the Downloads folder -#> - param( - [Parameter(Mandatory = $true)] - [version]$RequiredVersion, - - [Parameter(Mandatory = $true)] - [ValidateScript( { Test-Path $_} )] - [string] - $Path, - - [Parameter()] - [string]$Repository = 'PSGallery' - ) - $powercliModuleName = 'VMware.PowerCLI' - $desiredPowerCLIModule = Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion - if (-not $desiredPowerCLIModule) { - throw "'VMware.PowerCLI' with version $RequiredVersion' was not found." - } - - $depsOrder = 'VMware.VimAutomation.Sdk', 'VMware.VimAutomation.Common', 'VMware.Vim', 'VMware.VimAutomation.Cis.Core', 'VMware.VimAutomation.Core', 'VMware.VimAutomation.Nsxt', 'VMware.VimAutomation.Vmc', 'VMware.VimAutomation.Vds', 'VMware.VimAutomation.Srm', 'VMware.ImageBuilder', 'VMware.VimAutomation.Storage', 'VMware.VimAutomation.StorageUtility', 'VMware.VimAutomation.License', 'VMware.VumAutomation', 'VMware.VimAutomation.HorizonView', 'VMware.DeployAutomation', 'VMware.VimAutomation.vROps', 'VMware.VimAutomation.PCloud' - $orderedDependncies = @() - foreach ($depModuleName in $depsOrder) { - $orderedDependncies += $desiredPowerCLIModule.Dependencies | ? {$_.Name -eq $depModuleName} - } - - # Save PowerCLI Module Version - Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion | Save-Module -Path $Path - - # Save dependencies with minimum version - foreach ($dependency in $orderedDependncies) { - Find-Module $dependency.Name -RequiredVersion $dependency.MinimumVersion | Save-Module -Path $Path - } - - # Remove newer dependencies versoin - foreach ($dependency in $orderedDependncies) { - Get-ChildItem -Path (Join-Path $path $dependency.Name) | ` - Where-Object {$_.Name -ne $dependency.MinimumVersion} | ` - Remove-Item -Confirm:$false -Force -Recurse - } -} \ No newline at end of file + <# + .SYNOPSIS + Advanced function which can be used to easily download specific versions of PowerCLI from an online gallery + .DESCRIPTION + Downloads a specific version of PowerCLI and all the dependencies at the appropriate version + .NOTES + Author: 1.0 - Dimitar Milov + Author: 2.0 - Kyle Ruddy, @kmruddy + .PARAMETER RequiredVersion + Dynamic parameter used to specify the PowerCLI version + .PARAMETER Path + Directory path where the modules should be downloaded + .PARAMETER Repository + Repository to access the PowerCLI modules + .PARAMETER Simple + Switch used to specify the nested version folders should be removed (therefore adding PowerShell 3/4 compatibility) + .EXAMPLE + Save-PowerCLI -RequiredVersion '10.0.0.7895300' -Path .\Downloads\ + Downloads PowerCLI 10.0.0 to the Downloads folder + .EXAMPLE + Save-PowerCLI -RequiredVersion '6.5.2.6268016' -Path .\Downloads\ -Simple + Downloads PowerCLI 6.5.2 to the Downloads folder and removes the nested version folders + #> + [CmdletBinding(SupportsShouldProcess = $True)] + param( + [Parameter(Mandatory = $true, Position = 1)] + [ValidateScript( { Test-Path $_} )] + $Path, + [Parameter(Mandatory = $false, Position = 2)] + [string]$Repository = 'PSGallery', + [Parameter(Mandatory = $false, Position = 3)] + [Switch]$Simple + ) + DynamicParam + { + # Set the dynamic parameters name + $ParameterName = 'RequiredVersion' + + # Create the dictionary + $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary + + # Create the collection of attributes + $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] + + # Create and set the parameters' attributes + $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute + $ParameterAttribute.ValueFromPipeline = $true + $ParameterAttribute.ValueFromPipelineByPropertyName = $true + $ParameterAttribute.Mandatory = $true + $ParameterAttribute.Position = 0 + + # Add the attributes to the attributes collection + $AttributeCollection.Add($ParameterAttribute) + + # Generate and set the ValidateSet + $pcliVersions = Find-Module -Name 'VMware.PowerCLI' -AllVersions + $arrSet = $pcliVersions | select-Object -ExpandProperty Version + $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet) + + # Add the ValidateSet to the attributes collection + $AttributeCollection.Add($ValidateSetAttribute) + + # Create and return the dynamic parameter + $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection) + $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) + return $RuntimeParameterDictionary + } + + begin { + $powercliModuleName = 'VMware.PowerCLI' + $desiredPowerCLIModule = Find-Module -Name $powercliModuleName -RequiredVersion $RequiredVersion -Repository $Repository + + $depsOrder = 'VMware.VimAutomation.Sdk', 'VMware.VimAutomation.Common', 'VMware.Vim', 'VMware.VimAutomation.Cis.Core', 'VMware.VimAutomation.Core', 'VMware.VimAutomation.Nsxt', 'VMware.VimAutomation.Vmc', 'VMware.VimAutomation.Vds', 'VMware.VimAutomation.Srm', 'VMware.ImageBuilder', 'VMware.VimAutomation.Storage', 'VMware.VimAutomation.StorageUtility', 'VMware.VimAutomation.License', 'VMware.VumAutomation', 'VMware.VimAutomation.HorizonView', 'VMware.DeployAutomation', 'VMware.VimAutomation.vROps', 'VMware.VimAutomation.PCloud' + $orderedDependencies = @() + foreach ($depModuleName in $depsOrder) { + $orderedDependencies += $desiredPowerCLIModule.Dependencies | Where-Object {$_.Name -eq $depModuleName} + } + + foreach ($remainingDep in $desiredPowerCLIModule.Dependencies) { + if ($orderedDependencies.Name -notcontains $remainingDep.Name) { + $orderedDependencies += $remainingDep + } + + } + } + + process { + # Save PowerCLI Module Version + $desiredPowerCLIModule | Save-Module -Path $Path + + # Working with the depenent modules + foreach ($dependency in $orderedDependencies) { + if (Get-ChildItem -Path (Join-Path $path $dependency.Name) | Where-Object {$_.Name -ne $dependency.MinimumVersion}) { + # Save dependencies with minimum version + Find-Module $dependency.Name -RequiredVersion $dependency.MinimumVersion | Save-Module -Path $Path + + # Remove newer dependencies version + Get-ChildItem -Path (Join-Path $path $dependency.Name) | Where-Object {$_.Name -ne $dependency.MinimumVersion} | Remove-Item -Confirm:$false -Force -Recurse + } + } + } + + end { + if ($Simple) { + + function FolderCleanup { + param( + [Parameter(Mandatory = $true, Position = 0)] + [ValidateScript( { Test-Path $_} )] + $ParentFolder, + [Parameter(Mandatory = $true, Position = 1)] + [String]$ModuleName, + [Parameter(Mandatory = $true, Position = 2)] + $Version + ) + + + $topFolder = Get-Item -Path (Join-Path $ParentFolder $ModuleName) + $versionFolder = $topFolder | Get-ChildItem -Directory | Where-Object {$_.Name -eq $Version} + $versionFolder | Get-ChildItem | Copy-Item -Destination $topFolder + + # Checking for any nested folders within the PowerCLI module version folder + if ($versionFolder| Get-ChildItem -Directory) { + + # Obtaining and storing the child items to a variable, then copying the items to the parent folder's nested folder + $nestFolder = $versionFolder| Get-ChildItem -Directory + foreach ($nestDir in $nestFolder) { + $nestDir | Get-ChildItem | Copy-Item -Destination (Join-Path $topFolder $nestDir.Name) + } + + } + + # Removing any of the former, no longer needed, directory structure + $versionFolder| Remove-Item -Recurse -Force + } + + FolderCleanup -ParentFolder $Path -ModuleName $desiredPowerCLIModule.Name -Version $desiredPowerCLIModule.Version + foreach ($cleanUp in $orderedDependencies) { + + FolderCleanup -ParentFolder $Path -ModuleName $cleanUp.Name -Version $cleanUp.MinimumVersion + } + + } + + } + } \ No newline at end of file