Functions/Import-BT_Module.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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
<#
.SYNOPSIS
    This function installs and imports the correct edition (Beta/Prod) of a BitTitan.Runbooks module.
#>

function Import-BT_Module {
    [CmdletBinding(PositionalBinding=$true, DefaultParameterSetName="performModuleVersionCheckNotSpecified")]
    param (
        # The name of the module to import.
        [Parameter(Mandatory=$true, ParameterSetName="performModuleVersionCheckSpecified", Position=0)]
        [Parameter(Mandatory=$true, ParameterSetName="performModuleVersionCheckNotSpecified", Position=0)]
        [ValidateNotNullOrEmpty()]
        [String]$moduleName,

        # Select whether to perform a module version check when installing a module.
        [Parameter(Mandatory=$false, ParameterSetName="performModuleVersionCheckSpecified")]
        [Switch]$performModuleVersionCheck,

        # Select whether to suppress information messages.
        [Parameter(Mandatory=$false, ParameterSetName="performModuleVersionCheckSpecified")]
        [Parameter(Mandatory=$false, ParameterSetName="performModuleVersionCheckNotSpecified")]
        [ValidateNotNull()]
        [Switch]$quiet
    )

    # Set the default value for $performModuleVersionCheck
    if ($PSCmdlet.ParameterSetName -eq "performModuleVersionCheckNotSpecified") {
        # Use the global default parameter value if it is set
        if ($null -ne $Global:PSDefaultParameterValues["Import-BT_Module:PerformModuleVersionCheck"]) {
            $performModuleVersionCheck = $Global:PSDefaultParameterValues["Import-BT_Module:PerformModuleVersionCheck"]
        }
        else {
            $performModuleVersionCheck = [Switch]::Present
        }
    }

    # Retrieve the BitTitan Runbook Environment settings
    if ($Global:PSDefaultParameterValues.ContainsKey("*-BT_*:Environment")) {
        $environment = $Global:PSDefaultParameterValues["*-BT_*:Environment"]
    }
    else {
        $environment = "Beta"
    }
    if ($Global:PSDefaultParameterValues.ContainsKey("*-BT_*:IsRunningOnLocalMachine")) {
        $isRunningOnLocalMachine = $Global:PSDefaultParameterValues["*-BT_*:IsRunningOnLocalMachine"]
    }
    else {
        $isRunningOnLocalMachine = $false
    }

    # Import based on the environment and whether it is running on the local machine
    try {
        if ($isRunningOnLocalMachine) {
            # Import the module
            Import-Module -Name $moduleName -Force -Global

            # Import any nested modules
            $nestedModuleFolderPath = "$((Get-Module -ListAvailable $moduleName)[0].ModuleBase)\NestedModules"
            if (Test-Path -Path $nestedModuleFolderPath -ErrorAction SilentlyContinue) {
                foreach ($nestedModule in (Get-ChildItem "$($nestedModuleFolderPath)\*" -Directory)) {
                    Import-Module -Name $nestedModule.FullName -Force -Global
                }
            }

            # Verify imported module
            $importedModule = Get-Module -Name $moduleName
            if ($importedModule) {
                if (!$quiet) {
                    Write-Information "Imported '$($moduleName)' ($(if ($environment -eq 'BT') { 'Prod' } else { 'Beta' })) from the local machine."
                }
            }
            else {
                throw "Failed to import '$($moduleName)' ($(if ($environment -eq 'BT') { 'Prod' } else { 'Beta' })) from the local machine."
            }
        }

        # Running on the platform
        else {
            $userModulesPath = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules"

            # Running on the Prod platform
            if ($environment -eq "BT") {
                # Retrieve the currently installed modules
                $currentlyInstalledModules = Get-ChildItem $userModulesPath -Directory | Where-Object { $_.FullName -like "*$($moduleName)*" }

                # Track the current module version
                $moduleVersion = ""

                # The module is currently installed
                if ($currentlyInstalledModules) {
                    # Only check the module version if directed
                    if ($performModuleVersionCheck) {
                        # Retrieve the versions of the currently installed module and the latest module
                        $installedModuleVersion = [Version](Get-ChildItem "$($userModulesPath)\$($moduleName)" -Directory | Sort-Object -Property { [Version]$_.Name } -Descending)[0].Name
                        $latestModuleVersion = [Version](Find-Module $moduleName).Version
                        $moduleVersion = $latestModuleVersion

                        # The currently installed module is not the latest version, install the latest version
                        if ($installedModuleVersion -lt $latestModuleVersion) {
                            Install-Module -Name $moduleName -Scope CurrentUser -AllowClobber -Force
                            if (!$quiet) {
                                # Retrieve the version which was just installed
                                $newlyInstalledModuleVersion = (Get-ChildItem "$($userModulesPath)\$($moduleName)" -Directory | Sort-Object -Property { [Version]$_.Name } -Descending)[0].Name
                                Write-Information "Installed '$($moduleName)' version $($newlyInstalledModuleVersion) to replace version $($installedModuleVersion) from the PowerShell Gallery."
                            }
                            $moduleVersion = $newlyInstalledModuleVersion
                        }
                    }
                    else {
                        if (!$quiet) {
                            Write-Warning "Skipping the module version check for '$($moduleName)', and importing the currently installed version. The imported module may not be up to date."
                        }
                    }
                }

                # The module is not currently installed, install the module
                else {
                    Install-Module -Name $moduleName -Scope CurrentUser -AllowClobber -Force
                    if (!$quiet) {
                        # Retrieve the version which was installed
                        # Retrieve the highest version currently installed if there is more than one present
                        $installedModuleVersion = (Get-ChildItem "$($userModulesPath)\$($moduleName)" -Directory | Sort-Object -Property { [Version]$_.Name } -Descending)[0].Name
                        Write-Information "Installed '$($moduleName)' version $($installedModuleVersion) from the PowerShell Gallery."
                    }
                    $moduleVersion = $installedModuleVersion
                }

                # Import the module
                Import-Module -Name "$($userModulesPath)\$($moduleName)" -Force -Global

                # Import any nested modules
                $nestedModuleFolderPath = "$($userModulesPath)\$($moduleName)\$($moduleVersion)\NestedModules"
                if (Test-Path -Path $nestedModuleFolderPath -ErrorAction SilentlyContinue) {
                    foreach ($nestedModule in (Get-ChildItem "$($nestedModuleFolderPath)\*" -Directory)) {
                        Import-Module -Name $nestedModule.FullName -Force -Global
                    }
                }

                # Verify that the module has been imported
                $importedModule = Get-Module -Name $moduleName
                if ($importedModule) {
                    if (!$quiet) {
                        Write-Information "Imported '$($moduleName)' version $($importedModule.Version) from the local machine."
                    }
                }
                else {
                    throw "Failed to import '$($moduleName)' from the local machine."
                }
            }

            # Running on the Beta platform
            else {
                # Retrieve the currently installed modules
                $currentlyInstalledModules = Get-ChildItem $userModulesPath -Directory | Where-Object { $_.FullName -like "*$($moduleName)*" }

                # Track the current module version
                $moduleVersion = ""

                # The module is already installed
                if ($currentlyInstalledModules) {
                    # Only check the module version if directed
                    if ($performModuleVersionCheck) {
                        # Retrieve the versions of the currently installed module and the latest module
                        $installedModuleVersion = [Version](Get-ChildItem "$($userModulesPath)\$($moduleName)" -Directory | Sort-Object -Property { [Version]$_.Name } -Descending)[0].Name
                        $latestModuleVersion = [Version](Find-Module $moduleName).Version
                        $moduleVersion = $latestModuleVersion

                        # The currently installed module is not the latest version, install the latest version
                        if ($installedModuleVersion -lt $latestModuleVersion) {
                            Install-Module -Name "$($moduleName).Beta" -Scope CurrentUser -AllowClobber -Force

                            # Remove the ".Beta" from the names of the Beta module files
                            $item = Get-Item -Path "$($userModulesPath)\$($moduleName).Beta\*\$($moduleName).Beta.psd1"
                            Move-Item -Path $item.FullName -Destination ($item.FullName -Replace "$($moduleName).Beta.psd1", "$($moduleName).psd1" ) -Force
                            $item = Get-Item -Path "$($userModulesPath)\$($moduleName).Beta\*\$($moduleName).Beta.psm1"
                            Move-Item -Path $item.FullName -Destination ($item.FullName -Replace "$($moduleName).Beta.psm1", "$($moduleName).psm1" ) -Force

                            # Remove the ".Beta" from the name of the Beta module folder
                            Move-Item -Path "$($userModulesPath)\$($moduleName).Beta\" -Destination "$($userModulesPath)\$($moduleName)\" -Force
                            if (!$quiet) {
                                # Retrieve the version which was just installed
                                $newlyInstalledModuleVersion = (Get-ChildItem "$($userModulesPath)\$($moduleName)" -Directory | Sort-Object -Property { [Version]$_.Name } -Descending)[0].Name
                                Write-Information "Installed '$($moduleName).Beta' version $($newlyInstalledModuleVersion) to replace version $($installedModuleVersion) from the PowerShell Gallery as '$($moduleName)'."
                            }
                            $moduleVersion = $newlyInstalledModuleVersion
                        }
                    }
                    else {
                        if (!$quiet) {
                            Write-Warning "Skipping the module version check for '$($moduleName)', and importing the currently installed version. The imported module may not be up to date."
                        }
                    }
                }

                # The module is not currently installed, install the module
                else {
                    Install-Module -Name "$($moduleName).Beta" -Scope CurrentUser -AllowClobber -Force

                    # Remove the ".Beta" from the names of the Beta module files
                    $item = Get-Item -Path "$($userModulesPath)\$($moduleName).Beta\*\$($moduleName).Beta.psd1"
                    Move-Item -Path $item.FullName -Destination ($item.FullName -Replace "$($moduleName).Beta.psd1", "$($moduleName).psd1" ) -Force
                    $item = Get-Item -Path "$($userModulesPath)\$($moduleName).Beta\*\$($moduleName).Beta.psm1"
                    Move-Item -Path $item.FullName -Destination ($item.FullName -Replace "$($moduleName).Beta.psm1", "$($moduleName).psm1" ) -Force

                    # Remove the ".Beta" from the name of the Beta module folder
                    Move-Item -Path "$($userModulesPath)\$($moduleName).Beta\" -Destination "$($userModulesPath)\$($moduleName)\" -Force
                    if (!$quiet) {
                        # Retrieve the version which was just installed
                        $newlyInstalledModuleVersion = (Get-ChildItem "$($userModulesPath)\$($moduleName)" -Directory | Sort-Object -Property { [Version]$_.Name } -Descending)[0].Name
                        Write-Information "Installed '$($moduleName).Beta' version $($newlyInstalledModuleVersion) from the PowerShell Gallery as '$($moduleName)'."
                    }
                    $moduleVersion = $newlyInstalledModuleVersion
                }

                # Import the Beta module
                Import-Module -Name "$($userModulesPath)\$($moduleName)" -Force -Global

                # Import any nested modules
                $nestedModuleFolderPath = "$($userModulesPath)\$($moduleName)\$($moduleVersion)\NestedModules"
                if (Test-Path -Path $nestedModuleFolderPath -ErrorAction SilentlyContinue) {
                    foreach ($nestedModule in (Get-ChildItem "$($nestedModuleFolderPath)\*" -Directory)) {
                        Import-Module -Name $nestedModule.FullName -Force -Global
                    }
                }

                # Verify imported module
                $importedModule = Get-Module -Name $moduleName
                if ($importedModule) {
                    if (!$quiet) {
                        Write-Information "Imported '$($moduleName)' (Beta) version $($importedModule.Version) from the local machine."
                    }
                }
                else {
                    throw "Failed to import '$($moduleName)' (Beta) from the local machine."
                }
            }
        }
    }
    catch {
        Write-Error "Exception occurred on line $($_.InvocationInfo.ScriptLineNumber): `r`n$($_.Exception.Message)"
    }
}