Private/Invoke-ModuleInstall.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
<#
.SYNOPSIS Install module with dependent modules in required version .PARAMETER Name Exact name of the module .PARAMETER Guid GUID of the mmodule .PARAMETER MaximumVersion Maximum module version .PARAMETER RequiredVersion Required module version .PARAMETER Version Most likely minimum module version .PARAMETER Credential Credential to repository .PARAMETER Repository Name of the repository .PARAMETER SkipImport When is set import-module will be skipped. #> function Invoke-ModuleInstall { [CmdLetBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $true, HelpMessage = "Exact name of the module")] [string] $Name, [Parameter(Mandatory = $false, HelpMessage = "GUID of the mmodule")] [string] $Guid, [Parameter(Mandatory = $false, HelpMessage = "Maximum module version")] [Version] $MaximumVersion, [Parameter(Mandatory = $false, HelpMessage = "Required module version")] [Version] $RequiredVersion, [Parameter(Mandatory = $false, HelpMessage = "Most likely minimum module version")] [Version] $Version, [Parameter(Mandatory = $false, HelpMessage = "Repository Credential")] [PSCredential] $Credential = $null, [Parameter(Mandatory = $false, HelpMessage = "Repository name")] [string] $Repository = $null, [Parameter(Mandatory = $false, HelpMessage = "When is set import-module will be skipped.")] [switch] $SkipImport ) $ErrorActionPreference = 'Stop' Write-Verbose '-- begin - Invoke-ModuleInstall --' Write-Verbose "Name: $Name" Write-Verbose "Guid: $Guid" Write-Verbose "MaximumVersion: $MaximumVersion" Write-Verbose "RequiredVersion: $RequiredVersion" Write-Verbose "Version: $Version" Write-Verbose "Repository: $Repository" if ($SkipImport.IsPresent) { Write-Verbose "SkipImport: True" } else { Write-Verbose "SkipImport: False" } [Hashtable] $InstallModuleParam = @{ Name = $Name } if (![string]::IsNullOrEmpty($Guid)) { $InstallModuleParam += @{Guid = $Guid } } if (![string]::IsNullOrEmpty($MaximumVersion)) { $InstallModuleParam += @{MaximumVersion = $MaximumVersion } } if (![string]::IsNullOrEmpty($RequiredVersion)) { # Only when is set RequiredVersion we do need add Prefix into Import-Module paramters $InstallModuleParam += @{RequiredVersion = $RequiredVersion } } if (![string]::IsNullOrEmpty($Version)) { $InstallModuleParam += @{Version = $Version } } if ($null -ne $Credential) { $InstallModuleParam += @{Credential = $Credential } } if ($null -ne $Repository) { $InstallModuleParam += @{Repository = $Repository } } Write-Verbose ($InstallModuleParam | Out-String) $FoundModule = Find-ModuleForInstall ` @InstallModuleParam ` -Verbose:$VerbosePreference ` -Debug:$DebugPreference if (![String]::IsNullOrEmpty($FoundModule) -and ![String]::IsNullOrEmpty($FoundModule.Repository)) { Write-Verbose "Found: [$($FoundModule.Repository)] is not null Version [$($FoundModule.Version)]" } else { Write-Verbose "Module [$Name] not found or Repository is not set." } # Create hastable for check of installed modules $GetInstalledParam = $InstallModuleParam.Clone() if ($GetInstalledParam.ContainsKey('Credential')) { $GetInstalledParam.Remove('Credential') } if ($GetInstalledParam.ContainsKey('Repository')) { $GetInstalledParam.Remove('Repository') } $ModuleInstalled = Get-InstalledModule @GetInstalledParam -ea SilentlyContinue [boolean] $ShouldInstall = $false if (-not([string]::IsNullOrEmpty($ModuleInstalled)) ` -and -not([string]::IsNullOrEmpty($ModuleInstalled.Version))) { Write-Verbose "The module $Name is alredy installed in version $($ModuleInstalled.Version)" [string] $psd1Path = Join-Path -Path $ModuleInstalled.InstalledLocation -ChildPath ('{0}.psd1' -f $ModuleInstalled.Name) [string] $RequiredMd5 = Get-OriAzBopModuleMd5FromTag -Path $psd1Path -Verbose:$VerbosePreference -Debug:$DebugPreference Write-Verbose "Expected MD5 in the manifest is [$RequiredMd5]." if (-not([string]::IsNullOrEmpty($RequiredMd5)) ` -and -not(Test-OriAzBopModuleComplete -Path $psd1Path -RequiredMd5 $RequiredMd5 -Verbose:$VerbosePreference -Debug:$DebugPreference)) { Write-Verbose "Real MD5 of the module id different than is expected." $ShouldInstall = $true } # Versions should be compared in proper type # Note: Original ($ModuleInstalled.Version -lt $FoundModule.Version) is not working if (-not([string]::IsNullOrEmpty($FoundModule.Version)) ` -and ([Version] $ModuleInstalled.Version -lt [Version] $FoundModule.Version)) { Write-Verbose "The module $Name is alredy installed in version $($ModuleInstalled.Version), but found acceptable version for upgrade $($FoundModule.Version) " $ShouldInstall = $true } } else { Write-Verbose "The module $Name is NOT installed" $ShouldInstall = $true } if ($ShouldInstall) { Write-Verbose "Install-Module param:" Write-Verbose (ConvertTo-Json $InstallModuleParam) # Sometimes, specially on servers, the installation process is failing. # There has been spotted problems when more processes under the same user is trying to install same module in the same time, # but it can ge more general issue. # Therefore seems to be usefull to use the retry exeception funtion and collect such errors when simple retry can fix the problem. Invoke-OriAzExrExceptionRetry ` -ListedExceptions @('Access to the path*is denied.', 'Administrator rights are required to install or update.') ` -ScriptBlockToRun { Install-Module @InstallModuleParam ` -Force ` -Confirm:$false ` -Verbose:$VerbosePreference ` -Debug:$DebugPreference } ` -MaxRetry 30 ` -SleepTimeInSec 10 # re-Load after the installation $ModuleInstalled = Get-InstalledModule @GetInstalledParam -ea SilentlyContinue } else { Write-Verbose "Module aready exists" Write-Verbose ("Module is already installed in Version: {0} on path: {1}" -f $ModuleInstalled.Version, $ModuleInstalled.InstalledLocation) } [PSCustomObject] $DependencyMap = Invoke-ResolveDependency ` -InstalledLocation $ModuleInstalled.InstalledLocation ` -Credential $Credential ` -Repository $Repository ` -SkipImport:$SkipImport ` -Verbose:$VerbosePreference ` -Debug:$DebugPreference [PSCustomObject] $toReturn = @{ InstalledLocation = Join-Path -Path $ModuleInstalled.InstalledLocation -ChildPath ('{0}.psd1' -f $ModuleInstalled.Name) ModuleFilter = $GetInstalledParam DependencyMap = $DependencyMap } Write-Verbose '-- end - Invoke-ModuleInstall --' return $toReturn } |