PSSwagger.psm1
######################################################################################### # # Copyright (c) Microsoft Corporation. All rights reserved. # # Licensed under the MIT license. # # PSSwagger Module # ######################################################################################### Microsoft.PowerShell.Core\Set-StrictMode -Version Latest $SubScripts = @( 'PSSwagger.Constants.ps1' ) $SubScripts | ForEach-Object {. (Join-Path -Path $PSScriptRoot -ChildPath $_) -Force} $SubModules = @( 'SwaggerUtils.psm1', 'Utilities.psm1', 'Paths.psm1', 'Definitions.psm1' ) $SubModules | ForEach-Object {Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath $_) -Force -Scope Local -DisableNameChecking} Microsoft.PowerShell.Utility\Import-LocalizedData LocalizedData -filename PSSwagger.Resources.psd1 <# .SYNOPSIS PowerShell command to generate the PowerShell commands for a given RESTful Web Services using Swagger/OpenAPI documents. .DESCRIPTION PowerShell command to generate the PowerShell commands for a given RESTful Web Services using Swagger/OpenAPI documents. .EXAMPLE PS> New-PSSwaggerModule -SpecificationUri 'https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/arm-batch/2015-12-01/swagger/BatchManagement.json' -Path 'C:\GeneratedModules\' -Name 'AzBatchManagement' -UseAzureCsharpGenerator Generates a PS Module for the specified SpecificationUri. .EXAMPLE PS> New-PSSwaggerModule -SpecificationPath 'C:\SwaggerSpecs\BatchManagement.json' -Path 'C:\GeneratedModules\' -Name 'AzBatchManagement' -UseAzureCsharpGenerator Generates a PS Module for the specified SpecificationPath. .PARAMETER SpecificationPath Full Path to a Swagger based JSON spec. .PARAMETER SpecificationUri Uri to a Swagger based JSON spec. .PARAMETER Path Full Path to a file where the commands are exported to. .PARAMETER Name Name of the module to be generated. A folder with this name will be created in the location specified by Path parameter. .PARAMETER Version Version of the generated PowerShell module. .PARAMETER DefaultCommandPrefix Prefix value to be prepended to cmdlet noun or to cmdlet name without verb. .PARAMETER NoAssembly Switch to disable saving the precompiled module assembly and instead enable dynamic compilation. .PARAMETER PowerShellCorePath Path to PowerShell.exe for PowerShell Core. Only required if PowerShell Core not installed via MSI in the default path. .PARAMETER IncludeCoreFxAssembly Switch to additionally compile the module's binary component for Core CLR. .PARAMETER InstallToolsForAllUsers User wants to install local tools for all users. .PARAMETER TestBuild Switch to disable optimizations during build of full CLR binary component. .PARAMETER SymbolPath Path to save the generated C# code and PDB file. Defaults to $Path\symbols. .PARAMETER ConfirmBootstrap Automatically consent to downloading nuget.exe or NuGet packages as required. .PARAMETER UseAzureCsharpGenerator Switch to specify whether AzureCsharp code generator is required. By default, this command uses CSharp code generator. .INPUTS .OUTPUTS .NOTES .LINK #> function New-PSSwaggerModule { [CmdletBinding()] param( [Parameter(Mandatory = $true, ParameterSetName = 'SwaggerPath')] [string] $SpecificationPath, [Parameter(Mandatory = $true, ParameterSetName = 'SwaggerURI')] [Uri] $SpecificationUri, [Parameter(Mandatory = $true)] [string] $Path, [Parameter(Mandatory = $true)] [string] $Name, [Parameter(Mandatory = $false)] [Version] $Version = '0.0.1', [Parameter(Mandatory = $false)] [string] $DefaultCommandPrefix, [Parameter()] [switch] $UseAzureCsharpGenerator, [Parameter()] [switch] $NoAssembly, [Parameter()] [string] $PowerShellCorePath, [Parameter()] [switch] $IncludeCoreFxAssembly, [Parameter()] [switch] $InstallToolsForAllUsers, [Parameter()] [switch] $TestBuild, [Parameter()] [string] $SymbolPath, [Parameter()] [switch] $ConfirmBootstrap ) if ($NoAssembly -and $IncludeCoreFxAssembly) { $message = $LocalizedData.ParameterSetNotAllowed -f ('IncludeCoreFxAssembly', 'NoAssembly') throw $message return } if ($NoAssembly -and $TestBuild) { $message = $LocalizedData.ParameterSetNotAllowed -f ('TestBuild', 'NoAssembly') throw $message return } if ($NoAssembly -and $PowerShellCorePath) { $message = $LocalizedData.ParameterSetNotAllowed -f ('PowerShellCorePath', 'NoAssembly') throw $message return } if ($NoAssembly -and $SymbolPath) { $message = $LocalizedData.ParameterSetNotAllowed -f ('SymbolPath', 'NoAssembly') throw $message return } $SwaggerSpecFilePaths = @() $AutoRestModeler = 'Swagger' if ($PSCmdlet.ParameterSetName -eq 'SwaggerURI') { # Ensure that if the URI is coming from github, it is getting the raw content if($SpecificationUri.Host -eq 'github.com'){ $SpecificationUri = "https://raw.githubusercontent.com$($SpecificationUri.AbsolutePath.Replace('/blob/','/'))" $message = $LocalizedData.ConvertingSwaggerSpecToGithubContent -f ($SpecificationUri) Write-Verbose -Message $message -Verbose } $TempPath = Join-Path -Path (Get-XDGDirectory -DirectoryType Cache) -ChildPath (Get-Random) $null = New-Item -Path $TempPath -ItemType Directory -Force -Confirm:$false -WhatIf:$false $SwaggerFileName = Split-Path -Path $SpecificationUri -Leaf $SpecificationPath = Join-Path -Path $TempPath -ChildPath $SwaggerFileName $message = $LocalizedData.SwaggerSpecDownloadedTo -f ($SpecificationUri, $SpecificationPath) Write-Verbose -Message $message $ev = $null Invoke-WebRequest -Uri $SpecificationUri -OutFile $SpecificationPath -ErrorVariable ev if($ev) { return } $jsonObject = ConvertFrom-Json -InputObject ((Get-Content -Path $SpecificationPath) -join [Environment]::NewLine) -ErrorAction Stop if((Get-Member -InputObject $jsonObject -Name 'Documents') -and ($jsonObject.Documents.Count)) { $AutoRestModeler = 'CompositeSwagger' $BaseSwaggerUri = "$SpecificationUri".Substring(0, "$SpecificationUri".LastIndexOf('/')) foreach($document in $jsonObject.Documents) { $FileName = Split-Path -Path $document -Leaf $DocumentFolderPrefix = (Split-Path -Path $document -Parent).Replace('/', [System.IO.Path]::DirectorySeparatorChar).TrimStart('.') $DocumentFolderPath = Join-Path -Path $TempPath -ChildPath $DocumentFolderPrefix if(-not (Test-Path -LiteralPath $DocumentFolderPath -PathType Container)) { $null = New-Item -Path $DocumentFolderPath -ItemType Container -Force -Confirm:$false -WhatIf:$false } $SwaggerDocumentPath = Join-Path -Path $DocumentFolderPath -ChildPath $FileName $ev = $null Invoke-WebRequest -Uri $($BaseSwaggerUri + $($document.replace('\','/').TrimStart('.'))) -OutFile $SwaggerDocumentPath -ErrorVariable ev if($ev) { return } $SwaggerSpecFilePaths += $SwaggerDocumentPath } } else { $SwaggerSpecFilePaths += $SpecificationPath } } $outputDirectory = Microsoft.PowerShell.Management\Resolve-Path -Path $Path | Select-Object -First 1 -ErrorAction Ignore $outputDirectory = "$outputDirectory".TrimEnd('\').TrimEnd('/') if (-not $SymbolPath) { $SymbolPath = Join-Path -Path $Path -ChildPath "symbols" } if (-not $outputDirectory -or (-not (Test-path -Path $outputDirectory -PathType Container))) { throw $LocalizedData.PathNotFound -f ($Path) return } # Validate swagger path and composite swagger paths if (-not (Test-path -Path $SpecificationPath)) { throw $LocalizedData.SwaggerSpecPathNotExist -f ($SpecificationPath) return } # Get the PowerShell Metadata if .psmeta.json file is available. $PSMetaJsonObject = $null $PSMetaFilePath = [regex]::replace($SpecificationPath, ".json$", ".psmeta.json") if (Test-Path -Path $PSMetaFilePath -PathType Leaf) { $PSMetaJsonObject = ConvertFrom-Json -InputObject ((Get-Content -Path $PSMetaFilePath) -join [Environment]::NewLine) -ErrorAction Stop } if ($PSCmdlet.ParameterSetName -eq 'SwaggerPath') { $jsonObject = ConvertFrom-Json -InputObject ((Get-Content -Path $SpecificationPath) -join [Environment]::NewLine) -ErrorAction Stop if((Get-Member -InputObject $jsonObject -Name 'Documents') -and ($jsonObject.Documents.Count)) { $AutoRestModeler = 'CompositeSwagger' $SwaggerBaseDir = Split-Path -Path $SpecificationPath -Parent foreach($document in $jsonObject.Documents) { $FileName = Split-Path -Path $document -Leaf if(Test-Path -Path $document -PathType Leaf) { $SwaggerSpecFilePaths += $document } elseif(Test-Path -Path (Join-Path -Path $SwaggerBaseDir -ChildPath $document) -PathType Leaf) { $SwaggerSpecFilePaths += Join-Path -Path $SwaggerBaseDir -ChildPath $document } else { throw $LocalizedData.PathNotFound -f ($document) return } } } else { $SwaggerSpecFilePaths += $SpecificationPath } } $frameworksToCheckDependencies = @('net4') if ($IncludeCoreFxAssembly) { if ((-not (Get-OperatingSystemInfo).IsCore) -and (-not $PowerShellCorePath)) { $psCore = Get-PSSwaggerMsi -Name "PowerShell*" -MaximumVersion "6.0.0.11" | Sort-Object -Property Version -Descending if ($null -ne $psCore) { # PSCore exists via MSI, but the MSI provider doesn't seem to provide an install path # First check the default path (for now, just Windows) $psCore | ForEach-Object { if (-not $PowerShellCorePath) { $message = $LocalizedData.FoundPowerShellCoreMsi -f ($($_.Version)) Write-Verbose -Message $message $possiblePsPath = (Join-Path -Path "$env:ProgramFiles" -ChildPath "PowerShell" | Join-Path -ChildPath "$($_.Version)" | Join-Path -ChildPath "PowerShell.exe") if (Test-Path -Path $possiblePsPath) { $PowerShellCorePath = $possiblePsPath } } } } } if (-not $PowerShellCorePath) { throw $LocalizedData.MustSpecifyPsCorePath } if ((Get-Item $PowerShellCorePath).PSIsContainer) { $PowerShellCorePath = Join-Path -Path $PowerShellCorePath -ChildPath "PowerShell.exe" } if (-not (Test-Path -Path $PowerShellCorePath)) { $message = $LocalizedData.PsCorePathNotFound -f ($PowerShellCorePath) throw $message } $frameworksToCheckDependencies += 'netstandard1' } $userConsent = Initialize-PSSwaggerLocalTool -AllUsers:$InstallToolsForAllUsers -Azure:$UseAzureCsharpGenerator -Framework $frameworksToCheckDependencies -AcceptBootstrap:$ConfirmBootstrap $DefinitionFunctionsDetails = @{} $PowerShellCodeGen = @{ CodeGenerator = "" Path = "" NoAssembly = "" PowerShellCorePath = "" IncludeCoreFxAssembly = "" TestBuild = "" SymbolPath = "" ConfirmBootstrap = "" AdditionalFilesPath = "" ServiceType = "" CustomAuthCommand = "" HostOverrideCommand = "" NoAuthChallenge = $false NameSpacePrefix = '' } # Parse the JSON and populate the dictionary $ConvertToSwaggerDictionary_params = @{ SwaggerSpecPath = $SpecificationPath ModuleName = $Name ModuleVersion = $Version DefaultCommandPrefix = $DefaultCommandPrefix SwaggerSpecFilePaths = $SwaggerSpecFilePaths DefinitionFunctionsDetails = $DefinitionFunctionsDetails AzureSpec = $UseAzureCsharpGenerator PowerShellCodeGen = $PowerShellCodeGen PSMetaJsonObject = $PSMetaJsonObject } $swaggerDict = ConvertTo-SwaggerDictionary @ConvertToSwaggerDictionary_params Get-PowerShellCodeGenSettings -Path $SpecificationPath -CodeGenSettings $PowerShellCodeGen -PSMetaJsonObject $PSMetaJsonObject if(-not $PSMetaJsonObject) { foreach ($additionalSwaggerSpecPath in $SwaggerSpecFilePaths) { Get-PowerShellCodeGenSettings -Path $additionalSwaggerSpecPath -CodeGenSettings $PowerShellCodeGen } } # Expand partner metadata if ($PowerShellCodeGen['ServiceType']) { $partnerFilePath = Join-Path -Path $PSScriptRoot -ChildPath "ServiceTypes" | Join-Path -ChildPath "$($PowerShellCodeGen['ServiceType'].ToLowerInvariant()).PSMeta.json" if (-not (Test-Path -Path $partnerFilePath -PathType Leaf)) { Write-Warning -Message ($LocalizedData.ServiceTypeMetadataFileNotFound -f $partnerFilePath) } else { Get-PowerShellCodeGenSettings -Path $partnerFilePath -CodeGenSettings $PowerShellCodeGen } } $nameSpace = $swaggerDict['info'].NameSpace $models = $swaggerDict['info'].Models if($PSVersionTable.PSVersion -lt '5.0.0') { if (-not $outputDirectory.EndsWith($Name, [System.StringComparison]::OrdinalIgnoreCase)) { $outputDirectory = Join-Path -Path $outputDirectory -ChildPath $Name $SymbolPath = Join-Path -Path $SymbolPath -ChildPath $Name } } else { $ModuleNameandVersionFolder = Join-Path -Path $Name -ChildPath $Version if ($outputDirectory.EndsWith($Name, [System.StringComparison]::OrdinalIgnoreCase)) { $outputDirectory = Join-Path -Path $outputDirectory -ChildPath $ModuleVersion $SymbolPath = Join-Path -Path $SymbolPath -ChildPath $ModuleVersion } elseif (-not $outputDirectory.EndsWith($ModuleNameandVersionFolder, [System.StringComparison]::OrdinalIgnoreCase)) { $outputDirectory = Join-Path -Path $outputDirectory -ChildPath $ModuleNameandVersionFolder $SymbolPath = Join-Path -Path $SymbolPath -ChildPath $ModuleNameandVersionFolder } } $null = New-Item -ItemType Directory $outputDirectory -Force -ErrorAction Stop -Confirm:$false -WhatIf:$false $null = New-Item -ItemType Directory $SymbolPath -Force -ErrorAction Stop -Confirm:$false -WhatIf:$false $swaggerMetaDict = @{ OutputDirectory = $outputDirectory UseAzureCsharpGenerator = $UseAzureCsharpGenerator SwaggerSpecPath = $SpecificationPath SwaggerSpecFilePaths = $SwaggerSpecFilePaths AutoRestModeler = $AutoRestModeler PowerShellCodeGen = $PowerShellCodeGen } $ParameterGroupCache = @{} $PathFunctionDetails = @{} foreach($FilePath in $SwaggerSpecFilePaths) { $jsonObject = ConvertFrom-Json -InputObject ((Get-Content -Path $FilePath) -join [Environment]::NewLine) -ErrorAction Stop if(Get-Member -InputObject $jsonObject -Name 'Definitions') { # Handle the Definitions $jsonObject.Definitions.PSObject.Properties | ForEach-Object { Get-SwaggerSpecDefinitionInfo -JsonDefinitionItemObject $_ ` -Namespace $Namespace ` -DefinitionFunctionsDetails $DefinitionFunctionsDetails ` -Models $models } } if(Get-Member -InputObject $jsonObject -Name 'Paths') { # Handle the Paths $jsonObject.Paths.PSObject.Properties | ForEach-Object { Get-SwaggerSpecPathInfo -JsonPathItemObject $_ ` -PathFunctionDetails $PathFunctionDetails ` -SwaggerDict $swaggerDict ` -SwaggerMetaDict $swaggerMetaDict ` -DefinitionFunctionsDetails $DefinitionFunctionsDetails ` -ParameterGroupCache $ParameterGroupCache ` -PSMetaJsonObject $PSMetaJsonObject } } if(Get-Member -InputObject $jsonObject -Name 'x-ms-paths') { # Handle extended paths $jsonObject.'x-ms-paths'.PSObject.Properties | ForEach-Object { Get-SwaggerSpecPathInfo -JsonPathItemObject $_ ` -PathFunctionDetails $PathFunctionDetails ` -SwaggerDict $swaggerDict ` -SwaggerMetaDict $swaggerMetaDict ` -DefinitionFunctionsDetails $DefinitionFunctionsDetails ` -ParameterGroupCache $ParameterGroupCache ` -PSMetaJsonObject $PSMetaJsonObject } } } $codePhaseResult = ConvertTo-CsharpCode -SwaggerDict $swaggerDict ` -SwaggerMetaDict $swaggerMetaDict ` -PowerShellCorePath $PowerShellCorePath ` -InstallToolsForAllUsers:$InstallToolsForAllUsers ` -UserConsent:$userConsent ` -TestBuild:$TestBuild ` -PathFunctionDetails $PathFunctionDetails ` -NoAssembly:$NoAssembly ` -SymbolPath $SymbolPath $PathFunctionDetails = $codePhaseResult.PathFunctionDetails $generatedCSharpFilePath = $codePhaseResult.GeneratedCSharpPath # Need to expand the definitions early as parameter flattening feature requires the parameters list of the definition/model types. Expand-SwaggerDefinition -DefinitionFunctionsDetails $DefinitionFunctionsDetails -NameSpace $NameSpace -Models $Models $FunctionsToExport = @() $FunctionsToExport += New-SwaggerSpecPathCommand -PathFunctionDetails $PathFunctionDetails ` -SwaggerMetaDict $swaggerMetaDict ` -SwaggerDict $swaggerDict ` -DefinitionFunctionsDetails $DefinitionFunctionsDetails $FunctionsToExport += New-SwaggerDefinitionCommand -DefinitionFunctionsDetails $DefinitionFunctionsDetails ` -SwaggerMetaDict $swaggerMetaDict ` -NameSpace $nameSpace ` -Models $models $RootModuleFilePath = Join-Path $outputDirectory "$Name.psm1" $testCoreModuleRequirements = '' $testFullModuleRequirements = '' if ($UseAzureCSharpGenerator) { $testCoreModuleRequirements = '. (Join-Path -Path $PSScriptRoot "Test-CoreRequirements.ps1")' + [Environment]::NewLine + " " $testFullModuleRequirements = '. (Join-Path -Path $PSScriptRoot "Test-FullRequirements.ps1")' + [Environment]::NewLine + " " } Out-File -FilePath $RootModuleFilePath ` -InputObject $ExecutionContext.InvokeCommand.ExpandString($RootModuleContents)` -Encoding ascii ` -Force ` -Confirm:$false ` -WhatIf:$false New-ModuleManifestUtility -Path $outputDirectory ` -FunctionsToExport $FunctionsToExport ` -Info $swaggerDict['info'] Copy-Item (Join-Path -Path "$PSScriptRoot" -ChildPath "Generated.Resources.psd1") (Join-Path -Path "$outputDirectory" -ChildPath "$Name.Resources.psd1") -Force Copy-Item (Join-Path -Path "$PSScriptRoot" -ChildPath "GeneratedHelpers.psm1") (Join-Path -Path "$outputDirectory" -ChildPath "GeneratedHelpers.psm1") -Force Copy-Item (Join-Path -Path "$PSScriptRoot" -ChildPath "Test-CoreRequirements.ps1") (Join-Path -Path "$outputDirectory" -ChildPath "Test-CoreRequirements.ps1") -Force Copy-Item (Join-Path -Path "$PSScriptRoot" -ChildPath "Test-FullRequirements.ps1") (Join-Path -Path "$outputDirectory" -ChildPath "Test-FullRequirements.ps1") -Force Write-Verbose -Message ($LocalizedData.SuccessfullyGeneratedModule -f $Name,$outputDirectory) } #region Module Generation Helpers function ConvertTo-CsharpCode { param ( [Parameter(Mandatory=$true)] [hashtable] $SwaggerDict, [Parameter(Mandatory = $true)] [hashtable] $SwaggerMetaDict, [Parameter()] [string] $PowerShellCorePath, [Parameter()] [switch] $InstallToolsForAllUsers, [Parameter()] [switch] $UserConsent, [Parameter()] [switch] $TestBuild, [Parameter(Mandatory=$true)] [hashtable] $PathFunctionDetails, [Parameter()] [switch] $NoAssembly, [Parameter()] [string] $SymbolPath ) Write-Verbose -Message $LocalizedData.GenerateCodeUsingAutoRest $info = $SwaggerDict['Info'] $autoRestExePath = "AutoRest" if (-not (get-command -name $autoRestExePath)) { throw $LocalizedData.AutoRestNotInPath } $outputDirectory = $SwaggerMetaDict['outputDirectory'] $nameSpace = $info.NameSpace $generatedCSharpPath = Join-Path -Path $outputDirectory -ChildPath "Generated.Csharp" $codeGenerator = "CSharp" if ($SwaggerMetaDict['UseAzureCsharpGenerator']) { $codeGenerator = "Azure.CSharp" } $clrPath = Join-Path -Path $outputDirectory -ChildPath 'ref' | Join-Path -ChildPath 'fullclr' if (-not (Test-Path -Path $clrPath)) { $null = New-Item -Path $clrPath -ItemType Directory -Force -Confirm:$false -WhatIf:$false } $outAssembly = "$NameSpace.dll" # Delete the previously generated assembly, even if -NoAssembly is specified if (Test-Path -Path (Join-Path -Path $clrPath -ChildPath $outAssembly)) { $null = Remove-Item -Path (Join-Path -Path $clrPath -ChildPath $outAssembly) -Force } # Clean old generated code for when operations change or the command is re-run (Copy-Item can't clobber) # Note that we don't need to require this as empty as this folder is generated by PSSwagger, not a user folder if (Test-Path -Path $generatedCSharpPath) { $null = Remove-Item -Path $generatedCSharpPath -Recurse -Force } if ($NoAssembly) { $outAssembly = '' } $return = @{ GeneratedCSharpPath = $generatedCSharpPath } $tempCodeGenSettingsPath = '' try { if ($info.ContainsKey('CodeGenFileRequired') -and $info.CodeGenFileRequired) { # Some settings need to be overwritten # Write the following parameters: AddCredentials, CodeGenerator, Modeler $tempCodeGenSettings = @{ AddCredentials = $true CodeGenerator = $codeGenerator Modeler = $swaggerMetaDict['AutoRestModeler'] } $tempCodeGenSettingsPath = "$(Join-Path -Path (Get-XDGDirectory -DirectoryType Cache) -ChildPath (Get-Random)).json" $tempCodeGenSettings | ConvertTo-Json | Out-File -FilePath $tempCodeGenSettingsPath $autoRestParams = @('-Input', $swaggerMetaDict['SwaggerSpecPath'], '-OutputDirectory', $generatedCSharpPath, '-Namespace', $NameSpace, '-CodeGenSettings', $tempCodeGenSettingsPath) } else { # None of the PSSwagger-required params are being overwritten, just call the CLI directly to avoid the extra disk op $autoRestParams = @('-Input', $swaggerMetaDict['SwaggerSpecPath'], '-OutputDirectory', $generatedCSharpPath, '-Namespace', $NameSpace, '-AddCredentials', $true, '-CodeGenerator', $codeGenerator, '-Modeler', $swaggerMetaDict['AutoRestModeler']) } Write-Verbose -Message $LocalizedData.InvokingAutoRestWithParams for ($i = 0; $i -lt $autoRestParams.Length; $i += 2) { Write-Verbose -Message ($LocalizedData.AutoRestParam -f ($autoRestParams[$i], $autoRestParams[$i+1])) } $null = & $autoRestExePath $autoRestParams if ($LastExitCode) { throw $LocalizedData.AutoRestError } } finally { if ($tempCodeGenSettingsPath -and (Test-Path -Path $tempCodeGenSettingsPath)) { $null = Remove-Item -Path $tempCodeGenSettingsPath -Force -ErrorAction Ignore } } Write-Verbose -Message $LocalizedData.GenerateAssemblyFromCode if ($info.ContainsKey('CodeOutputDirectory') -and $info.CodeOutputDirectory) { $null = Copy-Item -Path $info.CodeOutputDirectory -Destination $generatedCSharpPath -Filter "*.cs" -Recurse -ErrorAction Ignore } $allCSharpFiles= Get-ChildItem -Path "$generatedCSharpPath\*.cs" ` -Recurse ` -File ` -Exclude Program.cs,TemporaryGeneratedFile* | Where-Object DirectoryName -notlike '*Azure.Csharp.Generated*' $allCodeFiles = @() foreach ($file in $allCSharpFiles) { $newFileName = Join-Path -Path $file.Directory -ChildPath "$($file.BaseName).Code.ps1" $null = Move-Item -Path $file.FullName -Destination $newFileName -Force $allCodeFiles += $newFileName } $allCSharpFilesArrayString = "@('"+ $($allCodeFiles -join "','") + "')" # Compile full CLR (PSSwagger requires to be invoked from full PowerShell) $codeCreatedByAzureGenerator = [bool]$SwaggerMetaDict['UseAzureCsharpGenerator'] # As of 3/2/2017, there's a version mismatch between the latest Microsoft.Rest.ClientRuntime.Azure package and the latest AzureRM.Profile package # So we have to hardcode Microsoft.Rest.ClientRuntime.Azure to at most version 3.3.4 $modulePostfix = $info['infoName'] $NameSpace = $info.namespace $fullModuleName = $Namespace + '.' + $modulePostfix $cliXmlTmpPath = Get-TemporaryCliXmlFilePath -FullModuleName $fullModuleName try { Export-CliXml -InputObject $PathFunctionDetails -Path $cliXmlTmpPath $dependencies = Get-PSSwaggerExternalDependencies -Azure:$codeCreatedByAzureGenerator -Framework 'net4' $microsoftRestClientRuntimeAzureRequiredVersion = if ($dependencies.ContainsKey('Microsoft.Rest.ClientRuntime.Azure')) { $dependencies['Microsoft.Rest.ClientRuntime.Azure'].RequiredVersion } else { '' } $command = "Import-Module '$PSScriptRoot\PSSwaggerUtility'; Add-PSSwaggerClientType -OutputAssemblyName '$outAssembly' `` -ClrPath '$clrPath' `` -CSharpFiles $allCSharpFilesArrayString `` -CodeCreatedByAzureGenerator:`$$codeCreatedByAzureGenerator `` -MicrosoftRestClientRuntimeAzureRequiredVersion '$microsoftRestClientRuntimeAzureRequiredVersion' `` -MicrosoftRestClientRuntimeRequiredVersion '$($dependencies['Microsoft.Rest.ClientRuntime'].RequiredVersion)' `` -NewtonsoftJsonRequiredVersion '$($dependencies['Newtonsoft.Json'].RequiredVersion)' `` -AllUsers:`$$InstallToolsForAllUsers `` -BootstrapConsent:`$$UserConsent `` -TestBuild:`$$TestBuild `` -SymbolPath $SymbolPath; if('$outAssembly') { # Load the generated assembly to extract the extended metadata `$AssemblyPath = Join-Path -Path '$clrPath' -ChildPath '$outAssembly' if(Test-Path -Path `$AssemblyPath -PathType Leaf) { Add-Type -Path `$AssemblyPath } } Import-Module `"`$(Join-Path -Path `"$PSScriptRoot`" -ChildPath `"Paths.psm1`")` -DisableNameChecking; Set-ExtendedCodeMetadata -MainClientTypeName $fullModuleName `` -CliXmlTmpPath $cliXmlTmpPath" $success = & "powershell" -command "& {$command}" $codeReflectionResult = Import-CliXml -Path $cliXmlTmpPath if ($codeReflectionResult.ContainsKey('VerboseMessages') -and $codeReflectionResult.VerboseMessages -and ($codeReflectionResult.VerboseMessages.Count -gt 0)) { $verboseMessages = $codeReflectionResult.VerboseMessages -Join [Environment]::NewLine Write-Verbose -Message $verboseMessages } if ($codeReflectionResult.ContainsKey('WarningMessages') -and $codeReflectionResult.WarningMessages -and ($codeReflectionResult.WarningMessages.Count -gt 0)) { $warningMessages = $codeReflectionResult.WarningMessages -Join [Environment]::NewLine Write-Warning -Message $warningMessages } if ((Test-AssemblyCompilationSuccess -Output ($success | Out-String))) { $message = $LocalizedData.GeneratedAssembly -f ($outAssembly) Write-Verbose -Message $message } else { # This should be enough to let the user know we failed to generate their module's assembly. if (-not $outAssembly) { $outAssembly = "$NameSpace.dll" } $message = $LocalizedData.UnableToGenerateAssembly -f ($outAssembly) Throw $message } if (-not $codeReflectionResult.Result -or $codeReflectionResult.ErrorMessages.Count -gt 0) { $errorMessage = (,($LocalizedData.MetadataExtractFailed) + $codeReflectionResult.ErrorMessages) -Join [Environment]::NewLine throw $errorMessage } $return.PathFunctionDetails = $codeReflectionResult.Result } finally { if (Test-Path -Path $cliXmlTmpPath) { $null = Remove-Item -Path $cliXmlTmpPath } } # If we're not going to save the assembly, no need to generate the core CLR one now if ($PowerShellCorePath -and (-not $NoAssembly)) { if (-not $outAssembly) { $outAssembly = "$NameSpace.dll" } # Compile core CLR $clrPath = Join-Path -Path $outputDirectory -ChildPath 'ref' | Join-Path -ChildPath 'coreclr' if (Test-Path (Join-Path -Path $outputDirectory -ChildPath $outAssembly)) { $null = Remove-Item -Path $outAssembly -Force } if (-not (Test-Path -Path $clrPath)) { $null = New-Item $clrPath -ItemType Directory -Force -Confirm:$false -WhatIf:$false } $dependencies = Get-PSSwaggerExternalDependencies -Azure:$codeCreatedByAzureGenerator -Framework 'netstandard1' $microsoftRestClientRuntimeAzureRequiredVersion = if ($dependencies.ContainsKey('Microsoft.Rest.ClientRuntime.Azure')) { $dependencies['Microsoft.Rest.ClientRuntime.Azure'].RequiredVersion } else { '' } $command = "Import-Module '$PSScriptRoot\PSSwaggerUtility'; Add-PSSwaggerClientType -OutputAssemblyName '$outAssembly' `` -ClrPath '$clrPath' `` -CSharpFiles $allCSharpFilesArrayString `` -MicrosoftRestClientRuntimeAzureRequiredVersion '$microsoftRestClientRuntimeAzureRequiredVersion' `` -MicrosoftRestClientRuntimeRequiredVersion '$($dependencies['Microsoft.Rest.ClientRuntime'].RequiredVersion)' `` -NewtonsoftJsonRequiredVersion '$($dependencies['Newtonsoft.Json'].RequiredVersion)' `` -CodeCreatedByAzureGenerator:`$$codeCreatedByAzureGenerator `` -BootstrapConsent:`$$UserConsent" $success = & "$PowerShellCorePath" -command "& {$command}" if ((Test-AssemblyCompilationSuccess -Output ($success | Out-String))) { $message = $LocalizedData.GeneratedAssembly -f ($outAssembly) Write-Verbose -Message $message } else { $message = $LocalizedData.UnableToGenerateAssembly -f ($outAssembly) Throw $message } } return $return } function Test-AssemblyCompilationSuccess { param( [Parameter(Mandatory = $true)] [string] $Output ) Write-Verbose -Message ($LocalizedData.AssemblyCompilationResult -f ($Output)) $tokens = $Output.Split(' ') return ($tokens[$tokens.Count-1].Trim().EndsWith('True')) } function New-ModuleManifestUtility { param( [Parameter(Mandatory = $true)] [string] $Path, [Parameter(Mandatory = $true)] [string[]] $FunctionsToExport, [Parameter(Mandatory=$true)] [hashtable] $Info ) $FormatsToProcess = Get-ChildItem -Path "$Path\$GeneratedCommandsName\FormatFiles\*.ps1xml" ` -File ` -ErrorAction Ignore | Foreach-Object { $_.FullName.Replace($Path, '.') } $NewModuleManifest_params = @{ Path = "$(Join-Path -Path $Path -ChildPath $Info.ModuleName).psd1" ModuleVersion = $Info.Version Description = $Info.Description CopyRight = $info.LicenseName Author = $info.ContactEmail NestedModules = @('PSSwaggerUtility') RootModule = "$($Info.ModuleName).psm1" FormatsToProcess = $FormatsToProcess FunctionsToExport = $FunctionsToExport CmdletsToExport = @() AliasesToExport = @() VariablesToExport = @() } if($Info.DefaultCommandPrefix) { $NewModuleManifest_params['DefaultCommandPrefix'] = $Info.DefaultCommandPrefix } if($PSVersionTable.PSVersion -ge '5.0.0') { # Below parameters are not available on PS 3 and 4 versions. if($Info.ProjectUri) { $NewModuleManifest_params['ProjectUri'] = $Info.ProjectUri } if($Info.LicenseUri) { $NewModuleManifest_params['LicenseUri'] = $Info.LicenseUri } } New-ModuleManifest @NewModuleManifest_params } #endregion Export-ModuleMember -Function New-PSSwaggerModule, New-PSSwaggerMetadataFile # SIG # Begin signature block # MIIasAYJKoZIhvcNAQcCoIIaoTCCGp0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUqIIiB8129iPHjf6xGhwaLDLZ # vKagghWDMIIEwzCCA6ugAwIBAgITMwAAALfuAa/68MeouwAAAAAAtzANBgkqhkiG # 9w0BAQUFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw # HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwHhcNMTYwOTA3MTc1ODQ1 # WhcNMTgwOTA3MTc1ODQ1WjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjENMAsGA1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNO # OkJCRUMtMzBDQS0yREJFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT # ZXJ2aWNlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuCMjQSw3ep1m # SndFRK0xgVRgm9wSl3i2llRtDdxzAWN9gQtYAE3hJP0/pV/7HHkshYPfMIRf7Pm/ # dxSsAN+7ATnNUk+wpe46rfe0FDNxoE6CYaiMSNjKcMXH55bGXNnwrrcsMaZrVXzS # IQcmAhUQw1jdLntbdTyCAwJ2UqF/XmVtWV/U466G8JP8VGLddeaucY0YKhgYwMnt # Sp9ElCkVDcUP01L9pgn9JmKUfD3yFt2p1iZ9VKCrlla10JQwe7aNW7xjzXxvcvlV # IXeA4QSabo4dq8HUh7JoYMqh3ufr2yNgTs/rSxG6D5ITcI0PZkH4PYjO2GbGIcOF # RVOf5RxVrwIDAQABo4IBCTCCAQUwHQYDVR0OBBYEFJZnqouaH5kw+n1zGHTDXjCT # 5OMAMB8GA1UdIwQYMBaAFCM0+NlSRnAK7UD7dvuzK7DDNbMPMFQGA1UdHwRNMEsw # SaBHoEWGQ2h0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3Rz # L01pY3Jvc29mdFRpbWVTdGFtcFBDQS5jcmwwWAYIKwYBBQUHAQEETDBKMEgGCCsG # AQUFBzAChjxodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY3Jv # c29mdFRpbWVTdGFtcFBDQS5jcnQwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZI # hvcNAQEFBQADggEBAG7J+Fdd7DgxG6awnA8opmQfW5DHnNDC/JPLof1sA8Nqczym # cnWIHmlWhqA7TUy4q02lKenO+R/vbmHna1BrC/KkczAyhOzkI2WFU3PeYubv8EjK # fYPmrNvS8fCsHJXj3N6fuFwXkHmCVBjTchK93auG09ckBYx5Mt4zW0TUbbw4/QAZ # X64rbut6Aw/C1bpxqBb8vvMssBB9Hw2m8ApFTApaEVOE/sKemVlq0VIo0fCXqRST # Lb6/QOav3S8S+N34RBNx/aKKOFzBDy6Ni45QvtRfBoNX3f4/mm4TFdNs+SeLQA+0 # oBs7UgdoxGSpX6vsWaH8dtlBw3NZK7SFi9bBMI4wggTtMIID1aADAgECAhMzAAAB # QJap7nBW/swHAAEAAAFAMA0GCSqGSIb3DQEBBQUAMHkxCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xIzAhBgNVBAMTGk1pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBMB4XDTE2MDgxODIwMTcxN1oXDTE3MTEwMjIwMTcxN1owgYMxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xDTALBgNVBAsTBE1PUFIx # HjAcBgNVBAMTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjCCASIwDQYJKoZIhvcNAQEB # BQADggEPADCCAQoCggEBANtLi+kDal/IG10KBTnk1Q6S0MThi+ikDQUZWMA81ynd # ibdobkuffryavVSGOanxODUW5h2s+65r3Akw77ge32z4SppVl0jII4mzWSc0vZUx # R5wPzkA1Mjf+6fNPpBqks3m8gJs/JJjE0W/Vf+dDjeTc8tLmrmbtBDohlKZX3APb # LMYb/ys5qF2/Vf7dSd9UBZSrM9+kfTGmTb1WzxYxaD+Eaxxt8+7VMIruZRuetwgc # KX6TvfJ9QnY4ItR7fPS4uXGew5T0goY1gqZ0vQIz+lSGhaMlvqqJXuI5XyZBmBre # ueZGhXi7UTICR+zk+R+9BFF15hKbduuFlxQiCqET92ECAwEAAaOCAWEwggFdMBMG # A1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBSc5ehtgleuNyTe6l6pxF+QHc7Z # ezBSBgNVHREESzBJpEcwRTENMAsGA1UECxMETU9QUjE0MDIGA1UEBRMrMjI5ODAz # K2Y3ODViMWMwLTVkOWYtNDMxNi04ZDZhLTc0YWU2NDJkZGUxYzAfBgNVHSMEGDAW # gBTLEejK0rQWWAHJNy4zFha5TJoKHzBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8v # Y3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNDb2RTaWdQQ0Ff # MDgtMzEtMjAxMC5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRw # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY0NvZFNpZ1BDQV8wOC0z # MS0yMDEwLmNydDANBgkqhkiG9w0BAQUFAAOCAQEAa+RW49cTHSBA+W3p3k7bXR7G # bCaj9+UJgAz/V+G01Nn5XEjhBn/CpFS4lnr1jcmDEwxxv/j8uy7MFXPzAGtOJar0 # xApylFKfd00pkygIMRbZ3250q8ToThWxmQVEThpJSSysee6/hU+EbkfvvtjSi0lp # DimD9aW9oxshraKlPpAgnPWfEj16WXVk79qjhYQyEgICamR3AaY5mLPuoihJbKwk # Mig+qItmLPsC2IMvI5KR91dl/6TV6VEIlPbW/cDVwCBF/UNJT3nuZBl/YE7ixMpT # Th/7WpENW80kg3xz6MlCdxJfMSbJsM5TimFU98KNcpnxxbYdfqqQhAQ6l3mtYDCC # BbwwggOkoAMCAQICCmEzJhoAAAAAADEwDQYJKoZIhvcNAQEFBQAwXzETMBEGCgmS # JomT8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEtMCsGA1UE # AxMkTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDgz # MTIyMTkzMloXDTIwMDgzMTIyMjkzMloweTELMAkGA1UEBhMCVVMxEzARBgNVBAgT # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEjMCEGA1UEAxMaTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQ # Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCycllcGTBkvx2aYCAg # Qpl2U2w+G9ZvzMvx6mv+lxYQ4N86dIMaty+gMuz/3sJCTiPVcgDbNVcKicquIEn0 # 8GisTUuNpb15S3GbRwfa/SXfnXWIz6pzRH/XgdvzvfI2pMlcRdyvrT3gKGiXGqel # cnNW8ReU5P01lHKg1nZfHndFg4U4FtBzWwW6Z1KNpbJpL9oZC/6SdCnidi9U3RQw # WfjSjWL9y8lfRjFQuScT5EAwz3IpECgixzdOPaAyPZDNoTgGhVxOVoIoKgUyt0vX # T2Pn0i1i8UU956wIAPZGoZ7RW4wmU+h6qkryRs83PDietHdcpReejcsRj1Y8wawJ # XwPTAgMBAAGjggFeMIIBWjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTLEejK # 0rQWWAHJNy4zFha5TJoKHzALBgNVHQ8EBAMCAYYwEgYJKwYBBAGCNxUBBAUCAwEA # ATAjBgkrBgEEAYI3FQIEFgQU/dExTtMmipXhmGA7qDFvpjy82C0wGQYJKwYBBAGC # NxQCBAweCgBTAHUAYgBDAEEwHwYDVR0jBBgwFoAUDqyCYEBWJ5flJRP8KuEKU5VZ # 5KQwUAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br # aS9jcmwvcHJvZHVjdHMvbWljcm9zb2Z0cm9vdGNlcnQuY3JsMFQGCCsGAQUFBwEB # BEgwRjBEBggrBgEFBQcwAoY4aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9j # ZXJ0cy9NaWNyb3NvZnRSb290Q2VydC5jcnQwDQYJKoZIhvcNAQEFBQADggIBAFk5 # Pn8mRq/rb0CxMrVq6w4vbqhJ9+tfde1MOy3XQ60L/svpLTGjI8x8UJiAIV2sPS9M # uqKoVpzjcLu4tPh5tUly9z7qQX/K4QwXaculnCAt+gtQxFbNLeNK0rxw56gNogOl # VuC4iktX8pVCnPHz7+7jhh80PLhWmvBTI4UqpIIck+KUBx3y4k74jKHK6BOlkU7I # G9KPcpUqcW2bGvgc8FPWZ8wi/1wdzaKMvSeyeWNWRKJRzfnpo1hW3ZsCRUQvX/Ta # rtSCMm78pJUT5Otp56miLL7IKxAOZY6Z2/Wi+hImCWU4lPF6H0q70eFW6NB4lhhc # yTUWX92THUmOLb6tNEQc7hAVGgBd3TVbIc6YxwnuhQ6MT20OE049fClInHLR82zK # wexwo1eSV32UjaAbSANa98+jZwp0pTbtLS8XyOZyNxL0b7E8Z4L5UrKNMxZlHg6K # 3RDeZPRvzkbU0xfpecQEtNP7LN8fip6sCvsTJ0Ct5PnhqX9GuwdgR2VgQE6wQuxO # 7bN2edgKNAltHIAxH+IOVN3lofvlRxCtZJj/UBYufL8FIXrilUEnacOTj5XJjdib # Ia4NXJzwoq6GaIMMai27dmsAHZat8hZ79haDJLmIz2qoRzEvmtzjcT3XAH5iR9HO # iMm4GPoOco3Boz2vAkBq/2mbluIQqBC0N1AI1sM9MIIGBzCCA++gAwIBAgIKYRZo # NAAAAAAAHDANBgkqhkiG9w0BAQUFADBfMRMwEQYKCZImiZPyLGQBGRYDY29tMRkw # FwYKCZImiZPyLGQBGRYJbWljcm9zb2Z0MS0wKwYDVQQDEyRNaWNyb3NvZnQgUm9v # dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcwNDAzMTI1MzA5WhcNMjEwNDAz # MTMwMzA5WjB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw # HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwggEiMA0GCSqGSIb3DQEB # AQUAA4IBDwAwggEKAoIBAQCfoWyx39tIkip8ay4Z4b3i48WZUSNQrc7dGE4kD+7R # p9FMrXQwIBHrB9VUlRVJlBtCkq6YXDAm2gBr6Hu97IkHD/cOBJjwicwfyzMkh53y # 9GccLPx754gd6udOo6HBI1PKjfpFzwnQXq/QsEIEovmmbJNn1yjcRlOwhtDlKEYu # J6yGT1VSDOQDLPtqkJAwbofzWTCd+n7Wl7PoIZd++NIT8wi3U21StEWQn0gASkdm # EScpZqiX5NMGgUqi+YSnEUcUCYKfhO1VeP4Bmh1QCIUAEDBG7bfeI0a7xC1Un68e # eEExd8yb3zuDk6FhArUdDbH895uyAc4iS1T/+QXDwiALAgMBAAGjggGrMIIBpzAP # BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQjNPjZUkZwCu1A+3b7syuwwzWzDzAL # BgNVHQ8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwgZgGA1UdIwSBkDCBjYAUDqyC # YEBWJ5flJRP8KuEKU5VZ5KShY6RhMF8xEzARBgoJkiaJk/IsZAEZFgNjb20xGTAX # BgoJkiaJk/IsZAEZFgltaWNyb3NvZnQxLTArBgNVBAMTJE1pY3Jvc29mdCBSb290 # IENlcnRpZmljYXRlIEF1dGhvcml0eYIQea0WoUqgpa1Mc1j0BxMuZTBQBgNVHR8E # STBHMEWgQ6BBhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9k # dWN0cy9taWNyb3NvZnRyb290Y2VydC5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsG # AQUFBzAChjhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY3Jv # c29mdFJvb3RDZXJ0LmNydDATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkqhkiG9w0B # AQUFAAOCAgEAEJeKw1wDRDbd6bStd9vOeVFNAbEudHFbbQwTq86+e4+4LtQSooxt # YrhXAstOIBNQmd16QOJXu69YmhzhHQGGrLt48ovQ7DsB7uK+jwoFyI1I4vBTFd1P # q5Lk541q1YDB5pTyBi+FA+mRKiQicPv2/OR4mS4N9wficLwYTp2OawpylbihOZxn # LcVRDupiXD8WmIsgP+IHGjL5zDFKdjE9K3ILyOpwPf+FChPfwgphjvDXuBfrTot/ # xTUrXqO/67x9C0J71FNyIe4wyrt4ZVxbARcKFA7S2hSY9Ty5ZlizLS/n+YWGzFFW # 6J1wlGysOUzU9nm/qhh6YinvopspNAZ3GmLJPR5tH4LwC8csu89Ds+X57H2146So # dDW4TsVxIxImdgs8UoxxWkZDFLyzs7BNZ8ifQv+AeSGAnhUwZuhCEl4ayJ4iIdBD # 6Svpu/RIzCzU2DKATCYqSCRfWupW76bemZ3KOm+9gSd0BhHudiG/m4LBJ1S2sWo9 # iaF2YbRuoROmv6pH8BJv/YoybLL+31HIjCPJZr2dHYcSZAI9La9Zj7jkIeW1sMpj # tHhUBdRBLlCslLCleKuzoJZ1GtmShxN1Ii8yqAhuoFuMJb+g74TKIdbrHk/Jmu5J # 4PcBZW+JC33Iacjmbuqnl84xKf8OxVtc2E0bodj6L54/LlUWa8kTo/0xggSXMIIE # kwIBATCBkDB5MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSMw # IQYDVQQDExpNaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQQITMwAAAUCWqe5wVv7M # BwABAAABQDAJBgUrDgMCGgUAoIGwMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEE # MBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBQV # BEZVkFArwLsYLIFqYKtIVYyN1jBQBgorBgEEAYI3AgEMMUIwQKAWgBQAUABvAHcA # ZQByAFMAaABlAGwAbKEmgCRodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vUG93ZXJT # aGVsbCAwDQYJKoZIhvcNAQEBBQAEggEABhVg5PNDPonOvQGHEuQB7SINs/WpekJS # 2dR3svzzYN7vyxjYwkdKyYkEsek1aP25j3r4AJPgOzjYhv9uJ44qAl6gy5qoy05U # sTggRgxLM3JDv38lPYgjs6WDIT16Q87JUJvGIOA0I7qPvocwyKMnRnr8o3VNscXm # ThdX3cDRP0nVQjT1EuqyzkLtGaSV0T5Gs0HNtQqJ0Nm3SVEI4VvIkats17DHRR26 # v+Mscf1Vz3GZmFdaIatJFzR9SQdIvqGsbnVE95TXqlWpxZlMX5CNrby9xa76ar0H # YpmlSClzqftPSn72O5+W+6A2hArY/aSfVvJNWPkaMSWgaB18e6St2qGCAigwggIk # BgkqhkiG9w0BCQYxggIVMIICEQIBATCBjjB3MQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMSEwHwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQ # Q0ECEzMAAAC37gGv+vDHqLsAAAAAALcwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJ # AzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE3MDgwODE3MzUyMVowIwYJ # KoZIhvcNAQkEMRYEFF+wykVoxoZkEQPO8E+abLKN1DDJMA0GCSqGSIb3DQEBBQUA # BIIBAG/U1wtM2vK68n0eS3CqGbOQUL2+0JPSwuIpr0OD2w4raTrAwEa/Q9COPGny # 7nWUpdJSydQ4BXpcmOJsLCWKnExu/KAx075ktvTViSOSCPh64EN/SO2+jx3UO+Cn # kzTYt42d0wKDbDOs1jAbhBIuWwinSUKe+N4Q3Kli6xRE3ghCKn79vTk/0XLpL0S5 # NKHPab/ceVmP2qsw3qwtma/qouvAeDueq3iL7jTpNxs0Mey3FdY8tMnC5oHiMKci # s+BesdCWWkrQT5iGRryO2VNamtppVCS/wxUXa1pB31ztz87Wsgbdu1e9hj7KUDyi # J4oQin5H9DjHdp4EaQ04syDuwkM= # SIG # End signature block |