Skip to content
This repository was archived by the owner on Sep 27, 2019. It is now read-only.

Commit 9594978

Browse files
authored
Support latest version of AutoRest in PSSwagger (#313)
* Support latest version of AutoRest in PSSwagger - Added required parameter changes to support AutoRest.cmd. - Removed dependency on AutoRest.CSharp.dll. - Added required logic in Get-CSharpModelName function to escape C# reserved words and also to remove special characters as per AutoRest functionality. - Updated run-tests.ps1 to install and use NodeJS and other minor changes. - Updated Readme with updated instructions and other info. * Using NodeJS '7.10.0' as there are some perf issues in AutoRest with NodeJS '8.4.0'.
1 parent 7d6c8b9 commit 9594978

7 files changed

+192
-155
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# Tests related files and folders
1717
/Tests/Generated/
1818
/Tests/NodeModules/
19+
/Tests/package-lock.json
1920
/Tests/ScenarioTestResults.xml
2021
/Tests/pesterCommand.ps1
2122
/Tests/dotnet-install.*

PSSwagger/PSSwagger.psm1

+47-13
Original file line numberDiff line numberDiff line change
@@ -585,8 +585,8 @@ function ConvertTo-CsharpCode
585585
Write-Verbose -Message $LocalizedData.GenerateCodeUsingAutoRest
586586
$info = $SwaggerDict['Info']
587587

588-
$autoRestExePath = "AutoRest"
589-
if (-not (get-command -name $autoRestExePath)) {
588+
$AutoRestCommand = Get-Command -Name AutoRest -ErrorAction Ignore | Select-Object -First 1 -ErrorAction Ignore
589+
if (-not $AutoRestCommand) {
590590
throw $LocalizedData.AutoRestNotInPath
591591
}
592592

@@ -631,31 +631,67 @@ function ConvertTo-CsharpCode
631631
}
632632

633633
$tempCodeGenSettingsPath = ''
634+
# Latest AutoRest inconsistently appends 'Client' to the specified infoName to generated the client name.
635+
# We need to override the client name to ensure that generated PowerShell cmdlets work fine.
636+
$ClientName = $info['infoName']
634637
try {
635638
if ($info.ContainsKey('CodeGenFileRequired') -and $info.CodeGenFileRequired) {
636639
# Some settings need to be overwritten
637640
# Write the following parameters: AddCredentials, CodeGenerator, Modeler
638641
$tempCodeGenSettings = @{
639642
AddCredentials = $true
640-
CodeGenerator = $codeGenerator
641-
Modeler = $swaggerMetaDict['AutoRestModeler']
643+
CodeGenerator = $codeGenerator
644+
Modeler = $swaggerMetaDict['AutoRestModeler']
645+
ClientName = $ClientName
642646
}
643647

644648
$tempCodeGenSettingsPath = "$(Join-Path -Path (Get-XDGDirectory -DirectoryType Cache) -ChildPath (Get-Random)).json"
645649
$tempCodeGenSettings | ConvertTo-Json | Out-File -FilePath $tempCodeGenSettingsPath
646650

647651
$autoRestParams = @('-Input', $swaggerMetaDict['SwaggerSpecPath'], '-OutputDirectory', $generatedCSharpPath, '-Namespace', $NameSpace, '-CodeGenSettings', $tempCodeGenSettingsPath)
648-
} else {
652+
}
653+
elseif ( ($AutoRestCommand.Name -eq 'AutoRest.exe') -or
654+
($swaggerMetaDict['AutoRestModeler'] -eq 'CompositeSwagger')) {
649655
# None of the PSSwagger-required params are being overwritten, just call the CLI directly to avoid the extra disk op
650-
$autoRestParams = @('-Input', $swaggerMetaDict['SwaggerSpecPath'], '-OutputDirectory', $generatedCSharpPath, '-Namespace', $NameSpace, '-AddCredentials', $true, '-CodeGenerator', $codeGenerator, '-Modeler', $swaggerMetaDict['AutoRestModeler'])
656+
$autoRestParams = @('-Input', $swaggerMetaDict['SwaggerSpecPath'],
657+
'-OutputDirectory', $generatedCSharpPath,
658+
'-Namespace', $NameSpace,
659+
'-AddCredentials', $true,
660+
'-CodeGenerator', $codeGenerator,
661+
'-ClientName', $ClientName
662+
'-Modeler', $swaggerMetaDict['AutoRestModeler']
663+
)
664+
}
665+
else {
666+
# See https://aka.ms/autorest/cli for AutoRest.cmd options.
667+
$autoRestParams = @(
668+
"--input-file=$($swaggerMetaDict['SwaggerSpecPath'])",
669+
"--output-folder=$generatedCSharpPath",
670+
"--namespace=$NameSpace",
671+
'--add-credentials',
672+
'--clear-output-folder=true',
673+
"--override-client-name=$ClientName"
674+
'--verbose',
675+
'--csharp'
676+
)
677+
678+
if ($codeGenerator -eq 'Azure.CSharp') {
679+
$autoRestParams += '--azure-arm'
680+
}
681+
682+
if (('continue' -eq $DebugPreference) -or
683+
('inquire' -eq $DebugPreference)) {
684+
$autoRestParams += '--debug'
685+
}
651686
}
652687

653688
Write-Verbose -Message $LocalizedData.InvokingAutoRestWithParams
654-
for ($i = 0; $i -lt $autoRestParams.Length; $i += 2) {
655-
Write-Verbose -Message ($LocalizedData.AutoRestParam -f ($autoRestParams[$i], $autoRestParams[$i+1]))
689+
Write-Verbose -Message $($autoRestParams | Out-String)
690+
691+
$autorestMessages = & AutoRest $autoRestParams
692+
if ($autorestMessages) {
693+
Write-Verbose -Message $($autorestMessages | Out-String)
656694
}
657-
658-
$null = & $autoRestExePath $autoRestParams
659695
if ($LastExitCode)
660696
{
661697
throw $LocalizedData.AutoRestError
@@ -691,9 +727,7 @@ function ConvertTo-CsharpCode
691727

692728
# As of 3/2/2017, there's a version mismatch between the latest Microsoft.Rest.ClientRuntime.Azure package and the latest AzureRM.Profile package
693729
# So we have to hardcode Microsoft.Rest.ClientRuntime.Azure to at most version 3.3.4
694-
$modulePostfix = $info['infoName']
695-
$NameSpace = $info.namespace
696-
$fullModuleName = $Namespace + '.' + $modulePostfix
730+
$fullModuleName = $Namespace + '.' + $ClientName
697731
$cliXmlTmpPath = Get-TemporaryCliXmlFilePath -FullModuleName $fullModuleName
698732
try {
699733
Export-CliXml -InputObject $PathFunctionDetails -Path $cliXmlTmpPath

PSSwagger/SwaggerUtils.psm1

+28-61
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,26 @@ if(-not (Get-OperatingSystemInfo).IsCore)
4242

4343
$script:IgnoredAutoRestParameters = @(@('Modeler', 'm'), @('AddCredentials'), @('CodeGenerator', 'g'))
4444
$script:PSSwaggerDefaultNamespace = "Microsoft.PowerShell"
45+
$script:CSharpReservedWords = @(
46+
'abstract', 'as', 'async', 'await', 'base',
47+
'bool', 'break', 'byte', 'case', 'catch',
48+
'char', 'checked', 'class', 'const', 'continue',
49+
'decimal', 'default', 'delegate', 'do', 'double',
50+
'dynamic', 'else', 'enum', 'event', 'explicit',
51+
'extern', 'false', 'finally', 'fixed', 'float',
52+
'for', 'foreach', 'from', 'global', 'goto',
53+
'if', 'implicit', 'in', 'int', 'interface',
54+
'internal', 'is', 'lock', 'long', 'namespace',
55+
'new', 'null', 'object', 'operator', 'out',
56+
'override', 'params', 'private', 'protected', 'public',
57+
'readonly', 'ref', 'return', 'sbyte', 'sealed',
58+
'short', 'sizeof', 'stackalloc', 'static', 'string',
59+
'struct', 'switch', 'this', 'throw', 'true',
60+
'try', 'typeof', 'uint', 'ulong', 'unchecked',
61+
'unsafe', 'ushort', 'using', 'virtual', 'void',
62+
'volatile', 'while', 'yield', 'var'
63+
)
64+
4565

4666
function ConvertTo-SwaggerDictionary {
4767
[CmdletBinding()]
@@ -1641,42 +1661,6 @@ function Get-Response
16411661

16421662
return $responseBody, $outputType
16431663
}
1644-
1645-
<#
1646-
1647-
Get-ToolsPath
1648-
1649-
#>
1650-
function Get-ToolsPath {
1651-
[string]$AutoRestToolsPath = $null
1652-
1653-
# Note: DLLs are automatically downloaded and extracted into the folder
1654-
# "$env:USERPROFILE/.autorest/plugins/autorest/$VERSION" if they do not
1655-
# exist for newer versions of autorest.
1656-
[string]$basePath = Join-Path -Path $env:USERPROFILE -ChildPath ".autorest" | Join-Path -ChildPath "plugins" | Join-Path -ChildPath "autorest"
1657-
1658-
1659-
if(Test-Path $basePath) { # Try to load newer version of autorest
1660-
$versions = @(Get-ChildItem -Directory $basePath | ForEach-Object {[System.Version]$_.Name} | Sort-Object -Descending)
1661-
1662-
if($versions.Length -ne 0) {
1663-
[string]$version = $versions[0] # Get newest
1664-
$AutoRestToolsPath = Join-Path -Path $basePath -ChildPath $version
1665-
}
1666-
} else { # Fallback to old version of autorest
1667-
$AutoRestToolsPath = Get-Command -Name 'AutoRest.exe' |
1668-
Select-Object -First 1 -ErrorAction Ignore |
1669-
ForEach-Object {Split-Path -LiteralPath $_.Source}
1670-
}
1671-
1672-
if (-not ($AutoRestToolsPath))
1673-
{
1674-
throw $LocalizedData.AutoRestNotInPath
1675-
}
1676-
1677-
return $AutoRestToolsPath
1678-
}
1679-
16801664
function Get-CSharpModelName
16811665
{
16821666
param(
@@ -1685,34 +1669,17 @@ function Get-CSharpModelName
16851669
$Name
16861670
)
16871671

1688-
if (-not $script:CSharpCodeNamerLoadAttempted) {
1689-
$script:CSharpCodeNamerLoadAttempted = $true
1690-
$script:CSharpCodeNamer = New-ObjectFromDependency -TypeNames @('AutoRest.CSharp.CodeNamerCs', 'AutoRest.CSharp.CSharpCodeNamer') -AssemblyName 'AutoRest.CSharp.dll' -AssemblyResolver {
1691-
param(
1692-
[string]
1693-
$AssemblyName
1694-
)
1695-
1696-
[string]$AutoRestToolsPath = Get-ToolsPath
1697-
1698-
$AssemblyFilePath = Join-Path -Path $AutoRestToolsPath -ChildPath $AssemblyName
1699-
if(-not $AssemblyFilePath -or -not (Test-Path -LiteralPath $AssemblyFilePath -PathType Leaf))
1700-
{
1701-
throw ($LocalizedData.PathNotFound -f $AssemblyFilePath)
1702-
}
1672+
# Below logic is as per AutoRest
1673+
$Name = $Name -replace '[[]]','Sequence'
1674+
# Remove special characters
1675+
$Name = $Name -replace '[^a-zA-Z0-9_-]',''
17031676

1704-
Add-Type -LiteralPath $AssemblyFilePath
1705-
}
1677+
# AutoRest appends 'Model' to the definition name when it is a C# reserved word.
1678+
if($script:CSharpReservedWords -contains $Name) {
1679+
$Name += 'Model'
17061680
}
17071681

1708-
if($script:CSharpCodeNamer)
1709-
{
1710-
return $script:CSharpCodeNamer.GetTypeName($Name)
1711-
}
1712-
else
1713-
{
1714-
return $Name.Replace('[','').Replace(']','')
1715-
}
1682+
return Get-PascalCasedString -Name $Name
17161683
}
17171684

17181685
<# Create an object from an external dependency with possible type name changes. Optionally resolve the external dependency using a delegate.

README.md

+9-13
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,18 @@ A PowerShell module with commands to generate the PowerShell commands for a give
3333
## Dependencies
3434
| Dependency | Version | Description |
3535
| ----------------| ----------- | -------------------------- |
36-
| AutoRest | 0.17.3 | Tool to generate C# SDK from Swagger spec |
36+
| AutoRest | 0.17.3 or newer | Tool to generate C# SDK from Swagger spec |
37+
| CSC.exe (Microsoft.Net.Compilers) | 2.3.1 or newer | C# Compiler to generate C# SDK assembly on Windows PowerShell |
3738
| Newtonsoft.Json | Full CLR: 6.0.8, Core CLR: 9.0.1 | NuGet package containing Newtonsoft.Json assembly, required for all modules |
38-
| Microsoft.Rest.ClientRuntime | 2.3.4 | NuGet package containing Microsoft.Rest.ClientRuntime assembly, required for all modules |
39-
| Microsoft.Rest.ClientRuntime.Azure | 3.3.4 | NuGet package containing Microsoft.Rest.ClientRuntime.Azure assembly, required for Microsoft Azure modules |
40-
| AzureRM.Profile | * | Module containing authentication helpers, required for Microsoft Azure modules on PowerShell |
39+
| Microsoft.Rest.ClientRuntime | 2.3.4 or newer | NuGet package containing Microsoft.Rest.ClientRuntime assembly, required for all modules |
40+
| Microsoft.Rest.ClientRuntime.Azure | 3.3.4 or newer | NuGet package containing Microsoft.Rest.ClientRuntime.Azure assembly, required for Microsoft Azure modules |
41+
| AzureRM.Profile | 2.0.0 or newer | Module containing authentication helpers, required for Microsoft Azure modules on PowerShell |
4142
| AzureRM.Profile.NetCore.Preview | * | Module containing authentication helpers, required for Microsoft Azure modules on PowerShell Core |
4243

4344
## Usage
4445
NOTE: In the short term, for best performance, the operation IDs in your Open API specifications should be of the form "<Noun>_<Verb><Suffix>". For example, the operation ID "Resource_GetByName" gets a resource named Resource by name.
4546
1. Get PSSwagger!
46-
* Install from PowerShellGallery.com:
47+
* Install from PowerShellGallery.com
4748
```powershell
4849
Install-Module -Name PSSwagger
4950
```
@@ -53,17 +54,12 @@ NOTE: In the short term, for best performance, the operation IDs in your Open AP
5354
```
5455
5556
2. Ensure AutoRest is installed and available in $env:PATH
56-
- Install AutoRest version 0.17.3
57+
- Follow the instructions provided at [AutoRest github repository](https://github.com/Azure/Autorest#installing-autorest).
58+
- Ensure AutoRest.cmd path is in $env:Path
5759
```powershell
58-
Install-Package -Name AutoRest -Source https://www.nuget.org/api/v2 -RequiredVersion 0.17.3 -Scope CurrentUser
59-
```
60-
- Add AutoRest.exe path to $env:Path
61-
```powershell
62-
$package = Get-Package -Name AutoRest -RequiredVersion 0.17.3
63-
$env:path += ";$(Split-Path $package.Source -Parent)\tools"
60+
$env:path += ";$env:APPDATA\npm"
6461
Get-Command -Name AutoRest
6562
```
66-
6763
3. Ensure CSC.exe is installed and available in $env:PATH
6864
- If CSC.exe is not installed already, install Microsoft.Net.Compilers package
6965
```powershell

Tests/PSSwagger.Unit.Tests.ps1

+14
Original file line numberDiff line numberDiff line change
@@ -239,5 +239,19 @@ Describe "PSSwagger Unit Tests" -Tag @('BVT', 'DRT', 'UnitTest', 'P0') {
239239
Get-HeaderContent -SwaggerDict @{Info = @{Header = $ValidHeaderFilePath}} | Should BeExactly $HeaderFileContent
240240
}
241241
}
242+
243+
Context "Get-CSharpModelName Unit Tests" {
244+
It "Get-CSharpModelNamee should remove special characters" {
245+
Get-CSharpModelName -Name @"
246+
SomeTypeWithSpecialCharacters ~!@#$%^&*()_+|}{:"<>?,./;'][\=-``
247+
"@ | Should BeExactly 'SomeTypeWithSpecialCharacters'
248+
}
249+
It "Get-CSharpModelNamee should replace [] with Sequence" {
250+
Get-CSharpModelName -Name 'foo[]' | Should BeExactly 'FooSequence'
251+
}
252+
It "Get-CSharpModelNamee should append 'Model' for C# reserved words" {
253+
Get-CSharpModelName -Name 'break' | Should BeExactly 'BreakModel'
254+
}
255+
}
242256
}
243257
}

0 commit comments

Comments
 (0)