Install-RequiredModule.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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
<#PSScriptInfo
 
.VERSION 4.0.6
 
.GUID 6083ddaa-3951-4482-a9f7-fe115ddf8021
 
.AUTHOR Joel 'Jaykul' Bennett
 
.COMPANYNAME PoshCode
 
.COPYRIGHT Copyright 2019, Joel Bennett
 
.TAGS Install Modules Development ModuleBuilder
 
.LICENSEURI https://github.com/PoshCode/ModuleBuilder/blob/master/LICENSE
 
.PROJECTURI https://github.com/PoshCode/ModuleBuilder/
 
.ICONURI https://github.com/PoshCode/ModuleBuilder/blobl/resources/images/install.png
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
    4.0.6 Fix a double -Verbose problem
    4.0.5 Let the -Destination be non-empty (so we don't have to re-download every time)
    4.0.4 Fix PowerShell 5 .Where bug
    4.0.3 Fix module check when using -Destination to force all modules to be in destination
    4.0.2 Fix Remove-Module error
    4.0.1 Add logging outputs
    4.0.0 Breaking change: require the -Destination to start empty (allow -CleanDestination to clear it)
          Fix for adding the destination to PSModulePath multiple times
          Started testing this so I can ship it to PowerShellGet
    3.0.0 Breaking change: switch -SkipImport to -Import -- inverting the logic to NOT import by default
          Add -Destination parameter to support installing in a local tool path
    2.0.1 Squash mistaken "InstallError" message caused by Select-Object -First
          Clean up output that was unexpected
    2.0.0 Breaking change: use NuGetVersion to support wildcards like 3.*
          Improve the error messages around aborted or failed installs
    1.0.1 Fix "Version '3.4.0' of module 'Pester' is already installed"
    1.0.0 This is the first public release - it probably doesn't work right
 
.PRIVATEDATA
 
#>


<#
.SYNOPSIS
    Installs (and imports) modules listed in RequiredModules.psd1
.DESCRIPTION
    Parses a RequiredModules.psd1 listing modules and attempts to import those modules.
    If it can't find the module in the PSModulePath, attempts to install it from PowerShellGet.
 
    The RequiredModules list looks like this (uses nuget version range syntax):
    @{
        "PowerShellGet" = "2.0.4"
        "Configuration" = "[1.3.1,2.0)"
        "Pester" = "[4.4.2,4.7.0]"
    }
 
    https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards
 
.EXAMPLE
    Install-RequiredModule
 
    Runs the install interactively:
    - reads the default 'RequiredModules.psd1' from the current folder
    - prompts for each module that needs to be installed
.EXAMPLE
    Save-Script Install-RequiredModule -Path .
    ./Install-RequiredModule.ps1 -Path ./RequiredModules.psd1 -Confirm:$false
 
    This example shows how to use this in a build where you're downloading the script
    and then running it in automation (without "confirm" prompting)
#>

using namespace NuGet.Versioning
using namespace Microsoft.PowerShell.Commands
# NOTE: Requires -Module PowerShellGet is missing here because we assume the version included in PowerShell 5+ is good enough
# If you need a higher version (which you very well may) you should put that at the top of your RequiredModules manifest

[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param(
    # The path to a metadata file listing required modules. Defaults to "RequiredModules.psd1" (in the current working directory).
    [Parameter(Position = 0)]
    [Alias("Path")]
    [string]$RequiredModulesFile = "RequiredModules.psd1",

    # If set, the local tools Destination path will be cleared and recreated
    [Parameter(ParameterSetName = "LocalTools")]
    [Switch]$CleanDestination,

    # If set, saves the modules to a local path rather than installing them to the scope
    [Parameter(ParameterSetName="LocalTools", Position = 0)]
    [string]$Destination,

    # The scope in which to install the modules (defaults to "CurrentUser")
    [ValidateSet("CurrentUser", "AllUsers")]
    $Scope = "CurrentUser",

    # Suppress normal host information output
    [Switch]$Quiet,

    # If set, the modules are download or installed but not imported
    [Switch]$Import
)

begin {
    [string[]]$InfoTags = @("Install")
    if (!$Quiet) {
        [string[]]$InfoTags += "PSHOST"
    }
    Write-Progress "Installing Required Modules from $RequiredModulesFile" -Id 0
    # we use this little hack to ensure NuGet types are available
    if (-not ("NuGet.Versioning.VersionRange" -as [Type])) {
        $EncodedCompressedFile = '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'

        $UncompressedFileBytes = [byte[]]::new(52488)
        $DeflatedStream = [System.IO.Compression.DeflateStream]::new(
            [IO.MemoryStream][Convert]::FromBase64String($EncodedCompressedFile),
            [IO.Compression.CompressionMode]::Decompress)
        $null = $DeflatedStream.Read($UncompressedFileBytes, 0, 52488)
        $null = [Reflection.Assembly]::Load($UncompressedFileBytes)

    }

    filter GetModuleVersion {
        # PowerShell does the wrong thing with MaximumVersion so we get all versions and check them
        [CmdletBinding()]param(
            [AllowNull()][string]$Destination,
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][string]$Name,
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][VersionRange]$Version
        )
        Write-Progress "Searching PSModulePath for '$Name' module with version '$Version'" -Id 1 -ParentId 0
        Write-Verbose "Searching PSModulePath for '$Name' module with version '$Version'"
        $Found = @(Get-Module $Name -ListAvailable -Verbose:$false).Where({
                    (!$Destination -or $_.ModuleBase.ToUpperInvariant().StartsWith($Destination.ToUpperInvariant())) -and
                    (
                        ($Version.Float -and $Version.Float.Satisfies($_.Version.ToString())) -or
                        (!$Version.Float -and $Version.Satisfies($_.Version.ToString()))
                    )
                    # Get returns modules in PSModulePath and then Version order, you're not necessarily getting the highest valid version
                }, "First", 1)
        if (-not $Found) {
            Write-Warning "Unable to find module '$Name' installed with version '$Version'"
        } else {
            Write-Verbose "Found '$Name' installed already with version '$($Found.Version)'"
            $Found
        }
    }

    filter FindModuleVersion {
        # PowerShellGet also does the wrong thing with MaximumVersion so we get all versions and check them
        [CmdletBinding()]param(
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][string]$Name,
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][VersionRange]$Version
        )
        Write-Progress "Searching PSRepository for '$Name' module with version '$Version'" -Id 1 -ParentId 0
        Write-Verbose "Searching PSRepository for '$Name' module with version '$Version'"

        $Found = @(Find-Module -Name $Name -AllVersions -Verbose:$false ).Where({
                    ($Version.Float -and $Version.Float.Satisfies($_.Version.ToString())) -or
                    (!$Version.Float -and $Version.Satisfies($_.Version.ToString()))
                }, "First", 1)

        if (-not $Found) {
            Write-Warning "Unable to resolve dependency '$Name' with version '$Version'"
        } else {
            Write-Verbose "Found '$Name' to install with version '$($Found.Version)'"
            $Found
        }
    }

    function ImportRequiredModulesFile {
        # Load a requirements file
        [CmdletBinding()]param(
            $RequiredModulesFile
        )

        $RequiredModulesFile = Convert-Path $RequiredModulesFile
        Write-Progress "Loading Required Module list from '$RequiredModulesFile'" -Id 1 -ParentId 0
        Write-Verbose "Loading Required Module list from '$RequiredModulesFile'"
        $LocalizedData = @{
            BaseDirectory = [IO.Path]::GetDirectoryName($RequiredModulesFile)
            FileName = [IO.Path]::GetFileNameWithoutExtension($RequiredModulesFile)
        }
        (Import-LocalizedData @LocalizedData).GetEnumerator().ForEach({
            [PSCustomObject]@{
                Name = $_.Key
                Version = [VersionRange]$_.Value
            }
        })
    }

    filter InstallModuleVersion {
        [CmdletBinding()]param(
            [AllowNull()][string]$Destination,
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][string]$Name,
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][string]$Version # This has to stay [string]
        )
        Write-Progress "Installing module '$($Name)' with version '$($Version)' from the PSGallery"
        Write-Verbose "Installing module '$($Name)' with version '$($Version)' from the PSGallery"
        if ($Destination) {
            Save-Module -Name $Name -RequiredVersion $Version -Path $Destination -ErrorAction Stop -Verbose:($VerbosePreference -eq "Continue")
        } else {
            $Preferences = @{
                Verbose            = $VerbosePreference -eq "Continue"
                Confirm            = $ConfirmPreference -ne "None"
                Scope              = $Scope
                Repository         = "PSGallery"
                SkipPublisherCheck = $true
                AllowClobber       = $true
                RequiredVersion    = $Version
                Name               = $Name
            }

            # Install missing modules with -AllowClobber and -SkipPublisherCheck because PowerShellGet requires both
            Install-Module @Preferences -ErrorAction Stop
        }

        if (GetModuleVersion @PSBoundParameters -WarningAction SilentlyContinue) {
            $PSCmdlet.WriteInformation("Installed module '$($Name)' with version '$($Version)' from the PSGallery", $InfoTags)
        } else {
            $PSCmdlet.WriteError(
                [System.Management.Automation.ErrorRecord]::new(
                    [Exception]::new("Failed to install module '$($Name)' with version '$($Version)' from the PSGallery"),
                    "InstallModuleDidnt",
                    "NotInstalled", $module))
        }
    }

    function Install-RequiredModule {
        [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = "High")]
        param(
            # The path to a metadata file listing required modules. Defaults to "RequiredModules.psd1" (in the current working directory).
            [Parameter(Position = 0)]
            [Alias("Path")]
            [string]$RequiredModulesFile = "RequiredModules.psd1",


            # If set, the local tools Destination path will be cleared and recreated
            [Parameter(ParameterSetName = "LocalTools")]
            [Switch]$CleanDestination,

            # If set, saves the modules to a local path rather than installing them to the scope
            [Parameter(ParameterSetName = "LocalTools", Position = 0)]
            [string]$Destination,

            # The scope in which to install the modules (defaults to "CurrentUser")
            [ValidateSet("CurrentUser", "AllUsers")]
            $Scope = "CurrentUser",

            # Suppress normal host information output
            [Switch]$Quiet,

            # If set, the modules are download or installed but not imported
            [Switch]$Import
        )

        if (-Not (Test-Path $RequiredModulesFile -PathType Leaf)) {
            $PSCmdlet.WriteError(
                [System.Management.Automation.ErrorRecord]::new(
                    [Exception]::new("RequiredModules file '$($RequiredModulesFile)' not found."),
                    "RequiredModules.psd1 Not Found",
                    "ResourceUnavailable", $RequiredModulesFile))
            return
        }

        if ($Destination) {
            if (-not (Test-Path $Destination -PathType Container)) {
                New-Item $Destination -ItemType Directory -ErrorAction Stop
                Write-Verbose "Created Destination directory: $(Convert-Path $Destination)"
            }
            # if (-not $CleanDestination) {
            # if (Get-ChildItem $Destination) {
            # $PSCmdlet.WriteError(
            # [System.Management.Automation.ErrorRecord]::new(
            # [Exception]::new("Destination folder '$($Destination)' not empty."),
            # "Destination Not Empty",
            # "ResourceUnavailable", $Destination))
            # return
            # }
            # }
            if ($CleanDestination -and (Get-ChildItem $Destination)) {
                Write-Warning "CleanDestination specified: Removing $($Destination) and all it's children:"
                try {
                    Remove-Item $Destination -Recurse -ErrorAction Stop # No -Force -- if this fails, you should handle it yourself
                    New-Item $Destination -ItemType Directory
                } catch {
                    $PSCmdlet.WriteError(
                        [System.Management.Automation.ErrorRecord]::new(
                            [Exception]::new("Failed to clean destination folder '$($Destination)'"),
                            "Destination Cannot Be Emptied",
                            "ResourceUnavailable", $Destination))
                    return
                }
            }
        }

        Write-Progress "Verifying PSRepository trust" -Id 1 -ParentId 0

        # Force Policy to Trusted so we can install without prompts and without -Force which is bad
        # TODO: Add support for all registered PSRepositories
        if ('Trusted' -ne ($Policy = (Get-PSRepository PSGallery).InstallationPolicy)) {
            Write-Verbose "Setting PSGallery Trusted"
            Set-PSRepository PSGallery -InstallationPolicy Trusted
        }

        if ($Destination) {
            # make sure we don't do this multiple times
            $RealDestination = Convert-Path $Destination
            if (-not (@($Env:PSModulePath.Split([IO.Path]::PathSeparator)) -contains $RealDestination)) {
                Write-Verbose "Adding $($RealDestination) to PSModulePath"
                $Env:PSModulePath = $RealDestination + [IO.Path]::PathSeparator + $Env:PSModulePath
            }
        }

        try {
            ImportRequiredModulesFile $RequiredModulesFile -OV Modules |
                Where-Object { -not ($_ | GetModuleVersion -Destination:$RealDestination -WarningAction SilentlyContinue) } |
                FindModuleVersion |
                InstallModuleVersion -Destination:$RealDestination -ErrorVariable InstallErrors
        } finally {
            # Put Policy back so we don't needlessly change environments permanently
            if ('Trusted' -ne $Policy) {
                Write-Verbose "Setting PSGallery Untrusted"
                Set-PSRepository PSGallery -InstallationPolicy $Policy
            }
        }
        Write-Progress "Importing Modules" -Id 1 -ParentId 0
        Write-Verbose "Importing Modules"

        if ($Import) {
            Remove-Module $Modules.Name -Force -ErrorAction Ignore
            $Modules | GetModuleVersion -OV InstalledModules | Import-Module -Passthru:(!$Quiet) -Verbose:$false
        } elseif ($InstallErrors) {
            Write-Warning "Module import skipped because of errors. `nSee error details in `$IRM_InstallErrors`nSee required modules in `$IRM_RequiredModules`nSee installed modules in `$IRM_InstalledModules"
            $global:IRM_InstallErrors = $InstallErrors
            $global:IRM_RequiredModules = $Modules
            $global:IRM_InstalledModules = $InstalledModules
        } else {
            Write-Warning "Module import skipped"
        }

        Write-Progress "Done" -Id 0 -Completed
    }
}
end {
    Install-RequiredModule @PSBoundParameters
}

# SIG # Begin signature block
# MIIXzgYJKoZIhvcNAQcCoIIXvzCCF7sCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUijp1YHfEj0+zFF31DzMGsOEH
# a6+gghMBMIID7jCCA1egAwIBAgIQfpPr+3zGTlnqS5p31Ab8OzANBgkqhkiG9w0B
# AQUFADCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIG
# A1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhh
# d3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcg
# Q0EwHhcNMTIxMjIxMDAwMDAwWhcNMjAxMjMwMjM1OTU5WjBeMQswCQYDVQQGEwJV
# UzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFu
# dGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMjCCASIwDQYJKoZIhvcN
# AQEBBQADggEPADCCAQoCggEBALGss0lUS5ccEgrYJXmRIlcqb9y4JsRDc2vCvy5Q
# WvsUwnaOQwElQ7Sh4kX06Ld7w3TMIte0lAAC903tv7S3RCRrzV9FO9FEzkMScxeC
# i2m0K8uZHqxyGyZNcR+xMd37UWECU6aq9UksBXhFpS+JzueZ5/6M4lc/PcaS3Er4
# ezPkeQr78HWIQZz/xQNRmarXbJ+TaYdlKYOFwmAUxMjJOxTawIHwHw103pIiq8r3
# +3R8J+b3Sht/p8OeLa6K6qbmqicWfWH3mHERvOJQoUvlXfrlDqcsn6plINPYlujI
# fKVOSET/GeJEB5IL12iEgF1qeGRFzWBGflTBE3zFefHJwXECAwEAAaOB+jCB9zAd
# BgNVHQ4EFgQUX5r1blzMzHSa1N197z/b7EyALt0wMgYIKwYBBQUHAQEEJjAkMCIG
# CCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMBIGA1UdEwEB/wQIMAYB
# Af8CAQAwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC50aGF3dGUuY29tL1Ro
# YXd0ZVRpbWVzdGFtcGluZ0NBLmNybDATBgNVHSUEDDAKBggrBgEFBQcDCDAOBgNV
# HQ8BAf8EBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0y
# MDQ4LTEwDQYJKoZIhvcNAQEFBQADgYEAAwmbj3nvf1kwqu9otfrjCR27T4IGXTdf
# plKfFo3qHJIJRG71betYfDDo+WmNI3MLEm9Hqa45EfgqsZuwGsOO61mWAK3ODE2y
# 0DGmCFwqevzieh1XTKhlGOl5QGIllm7HxzdqgyEIjkHq3dlXPx13SYcqFgZepjhq
# IhKjURmDfrYwggSjMIIDi6ADAgECAhAOz/Q4yP6/NW4E2GqYGxpQMA0GCSqGSIb3
# DQEBBQUAMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3Jh
# dGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNlcyBD
# QSAtIEcyMB4XDTEyMTAxODAwMDAwMFoXDTIwMTIyOTIzNTk1OVowYjELMAkGA1UE
# BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTQwMgYDVQQDEytT
# eW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIFNpZ25lciAtIEc0MIIBIjAN
# BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomMLOUS4uyOnREm7Dv+h8GEKU5Ow
# mNutLA9KxW7/hjxTVQ8VzgQ/K/2plpbZvmF5C1vJTIZ25eBDSyKV7sIrQ8Gf2Gi0
# jkBP7oU4uRHFI/JkWPAVMm9OV6GuiKQC1yoezUvh3WPVF4kyW7BemVqonShQDhfu
# ltthO0VRHc8SVguSR/yrrvZmPUescHLnkudfzRC5xINklBm9JYDh6NIipdC6Anqh
# d5NbZcPuF3S8QYYq3AhMjJKMkS2ed0QfaNaodHfbDlsyi1aLM73ZY8hJnTrFxeoz
# C9Lxoxv0i77Zs1eLO94Ep3oisiSuLsdwxb5OgyYI+wu9qU+ZCOEQKHKqzQIDAQAB
# o4IBVzCCAVMwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAO
# BgNVHQ8BAf8EBAMCB4AwcwYIKwYBBQUHAQEEZzBlMCoGCCsGAQUFBzABhh5odHRw
# Oi8vdHMtb2NzcC53cy5zeW1hbnRlYy5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly90
# cy1haWEud3Muc3ltYW50ZWMuY29tL3Rzcy1jYS1nMi5jZXIwPAYDVR0fBDUwMzAx
# oC+gLYYraHR0cDovL3RzLWNybC53cy5zeW1hbnRlYy5jb20vdHNzLWNhLWcyLmNy
# bDAoBgNVHREEITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMjAdBgNV
# HQ4EFgQURsZpow5KFB7VTNpSYxc/Xja8DeYwHwYDVR0jBBgwFoAUX5r1blzMzHSa
# 1N197z/b7EyALt0wDQYJKoZIhvcNAQEFBQADggEBAHg7tJEqAEzwj2IwN3ijhCcH
# bxiy3iXcoNSUA6qGTiWfmkADHN3O43nLIWgG2rYytG2/9CwmYzPkSWRtDebDZw73
# BaQ1bHyJFsbpst+y6d0gxnEPzZV03LZc3r03H0N45ni1zSgEIKOq8UvEiCmRDoDR
# EfzdXHZuT14ORUZBbg2w6jiasTraCXEQ/Bx5tIB7rGn0/Zy2DBYr8X9bCT2bW+IW
# yhOBbQAuOA2oKY8s4bL0WqkBrxWcLC9JG9siu8P+eJRRw4axgohd8D20UaF5Mysu
# e7ncIAkTcetqGVvP6KUwVyyJST+5z3/Jvz4iaGNTmr1pdKzFHTx/kuDDvBzYBHUw
# ggUwMIIEGKADAgECAhAECRgbX9W7ZnVTQ7VvlVAIMA0GCSqGSIb3DQEBCwUAMGUx
# CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
# dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9v
# dCBDQTAeFw0xMzEwMjIxMjAwMDBaFw0yODEwMjIxMjAwMDBaMHIxCzAJBgNVBAYT
# AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2Vy
# dC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNp
# Z25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD407Mcfw4R
# r2d3B9MLMUkZz9D7RZmxOttE9X/lqJ3bMtdx6nadBS63j/qSQ8Cl+YnUNxnXtqrw
# nIal2CWsDnkoOn7p0WfTxvspJ8fTeyOU5JEjlpB3gvmhhCNmElQzUHSxKCa7JGnC
# wlLyFGeKiUXULaGj6YgsIJWuHEqHCN8M9eJNYBi+qsSyrnAxZjNxPqxwoqvOf+l8
# y5Kh5TsxHM/q8grkV7tKtel05iv+bMt+dDk2DZDv5LVOpKnqagqrhPOsZ061xPeM
# 0SAlI+sIZD5SlsHyDxL0xY4PwaLoLFH3c7y9hbFig3NBggfkOItqcyDQD2RzPJ6f
# pjOp/RnfJZPRAgMBAAGjggHNMIIByTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud
# DwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzB5BggrBgEFBQcBAQRtMGsw
# JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcw
# AoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElE
# Um9vdENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNl
# cnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDov
# L2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBP
# BgNVHSAESDBGMDgGCmCGSAGG/WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93
# d3cuZGlnaWNlcnQuY29tL0NQUzAKBghghkgBhv1sAzAdBgNVHQ4EFgQUWsS5eyoK
# o6XqcQPAYPkt9mV1DlgwHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8w
# DQYJKoZIhvcNAQELBQADggEBAD7sDVoks/Mi0RXILHwlKXaoHV0cLToaxO8wYdd+
# C2D9wz0PxK+L/e8q3yBVN7Dh9tGSdQ9RtG6ljlriXiSBThCk7j9xjmMOE0ut119E
# efM2FAaK95xGTlz/kLEbBw6RFfu6r7VRwo0kriTGxycqoSkoGjpxKAI8LpGjwCUR
# 4pwUR6F6aGivm6dcIFzZcbEMj7uo+MUSaJ/PQMtARKUT8OZkDCUIQjKyNookAv4v
# cn4c10lFluhZHen6dGRrsutmQ9qzsIzV6Q3d9gEgzpkxYz0IGhizgZtPxpMQBvwH
# gfqL2vmCSfdibqFT+hKUGIUukpHqaGxEMrJmoecYpJpkUe8wggUwMIIEGKADAgEC
# AhALDZkX0sdOvwJhwzQTbV+7MA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVT
# MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
# b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25p
# bmcgQ0EwHhcNMTgwNzEyMDAwMDAwWhcNMTkwNzE2MTIwMDAwWjBtMQswCQYDVQQG
# EwJVUzERMA8GA1UECBMITmV3IFlvcmsxFzAVBgNVBAcTDldlc3QgSGVucmlldHRh
# MRgwFgYDVQQKEw9Kb2VsIEguIEJlbm5ldHQxGDAWBgNVBAMTD0pvZWwgSC4gQmVu
# bmV0dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMJb3Cf3n+/pFJiO
# hQqN5m54FpyIktMRWe5VyF8465BnAtzw3ivMyN+3k8IoXQhMxpCsY1TJbLyydNR2
# QzwEEtGfcTVnlAJdFFlBsgIdK43waaML5EG7tzNJKhHQDiN9bVhLPTXrit80eCTI
# RpOA7435oVG8erDpxhJUK364myUrmSyF9SbUX7uE09CJJgtB7vqetl4G+1j+iFDN
# Xi3bu1BFMWJp+TtICM+Zc5Wb+ZaYAE6V8t5GCyH1nlAI3cPjqVm8y5NoynZTfOhV
# bHiV0QI2K5WrBBboR0q6nd4cy6NJ8u5axi6CdUhnDMH20NN2I0v+2MBkgLAzxPrX
# kjnaEGECAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nEDwGD5LfZl
# dQ5YMB0GA1UdDgQWBBTiwur/NVanABEKwjZDB3g6SZN1mTAOBgNVHQ8BAf8EBAMC
# B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYvaHR0cDov
# L2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwNaAzoDGG
# L2h0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3Js
# MEwGA1UdIARFMEMwNwYJYIZIAYb9bAMBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8v
# d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQQBMIGEBggrBgEFBQcBAQR4MHYw
# JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBOBggrBgEFBQcw
# AoZCaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3Vy
# ZWRJRENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEL
# BQADggEBADNNHuRAdX0ddONqaUf3H3pwa1K016C02P90xDIyMvw+hiUb4Z/xewnY
# jyplspD0NQB9ca2pnNIy1KwjJryRgq8gl3epSiWTbViVn6VDK2h0JXm54H6hczQ8
# sEshCW53znNVUUUfxGsVM9kMcwITHYftciW0J+SsGcfuuAIuF1g47KQXKWOMcUQl
# yrP5t0ywotTVcg/1HWAPFE0V0sFy+Or4n81+BWXOLaCXIeeryLYncAVUBT1DI6lk
# peRUj/99kkn+hz1q4hHTtfNpMTOApP64EEFGKICKkJdvhs1PjtGa+QdAkhcInTxk
# t/hIJPUb1nO4CsKp1gaVsRkkbcStJ2kxggQ3MIIEMwIBATCBhjByMQswCQYDVQQG
# EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
# cnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBT
# aWduaW5nIENBAhALDZkX0sdOvwJhwzQTbV+7MAkGBSsOAwIaBQCgeDAYBgorBgEE
# AYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwG
# CisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBQH47JM
# nmMgMEG5RR6GiMIvoeaWJzANBgkqhkiG9w0BAQEFAASCAQDCPYvb9TZv2XzKsNky
# arKMwHRFzfch90d/CxOYu8+gFU2za1TK1eDzzr/nTpw44XFElHNu3QmAvbHJLRfm
# hjoZch5XNZjFi6OZg4aQOmzyMEXvF8BrJokygSQob+2dPYHm2FIJOwYruqlx0ebi
# WgLr5jI+Y8L7I4O3rWjNE1QtsBYrsDQm3SQxWZWH5Dq0fPFE9Zfeec2jbyZU/hLy
# zwk6HhmYrSQUF3PQdrDm0cSHwbt0cyX/ryg9Coqo4SWueTKWiDXnte6BsEsQ3Zn6
# SSOsfTBHy5Q0vEehGA6fWkj/0dJrVpum33BT9FO4DT2X8tX9AojSAMuDOMvkXOep
# Qg+noYICCzCCAgcGCSqGSIb3DQEJBjGCAfgwggH0AgEBMHIwXjELMAkGA1UEBhMC
# VVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTAwLgYDVQQDEydTeW1h
# bnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIENBIC0gRzICEA7P9DjI/r81bgTY
# apgbGlAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJ
# KoZIhvcNAQkFMQ8XDTE5MDYwNDIwMjAwMVowIwYJKoZIhvcNAQkEMRYEFEjIwDZR
# oxfOs9bJ84b3DLXa5vMeMA0GCSqGSIb3DQEBAQUABIIBAG8hfFzM3VtkUVGSIMU3
# IDNSvFbjC+fkx0EYvhZTDByaC7qwXZsHoVsv6mckyZ197mV1T+WFIFDtF4Uq6wwn
# jMIu19hf888i+LdH1vRPRK7MfmV/k2AHiXsxjqkTMexRW8BNEnW3wz9Q7+fMz3xQ
# MoMtVIhM+n+QAPtazhfJ+q3UatfU7eU2vWin0uNHbt1kPQlpJJ/T3iGaLfyG+Dbm
# TYcIwxU9AvT3AmX8KQLLoeJTcE0LVjdn3QBzgAkfpR1wu+ont4hVVpZAt7smAZLx
# p4yLu0sge7e4WX5WBAy+psEuzTzUMW66M6R104EIxwv65i7ftDAg/qrV9jqfZW3j
# mFQ=
# SIG # End signature block