Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Hidi users configure CSDL to OpenAPI conversion settings #1064

Merged
merged 7 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal class TransformCommandHandler : ICommandHandler
public Option<string?> VersionOption { get; set; }
public Option<OpenApiFormat?> FormatOption { get; set; }
public Option<bool> TerseOutputOption { get; set; }
public Option<string> SettingsFileOption { get; set; }
public Option<LogLevel> LogLevelOption { get; set; }
public Option<string> FilterByOperationIdsOption { get; set; }
public Option<string> FilterByTagsOption { get; set; }
Expand All @@ -42,6 +43,7 @@ public async Task<int> InvokeAsync(InvocationContext context)
string? version = context.ParseResult.GetValueForOption(VersionOption);
OpenApiFormat? format = context.ParseResult.GetValueForOption(FormatOption);
bool terseOutput = context.ParseResult.GetValueForOption(TerseOutputOption);
string settingsFile = context.ParseResult.GetValueForOption(SettingsFileOption);
LogLevel logLevel = context.ParseResult.GetValueForOption(LogLevelOption);
bool inlineLocal = context.ParseResult.GetValueForOption(InlineLocalOption);
bool inlineExternal = context.ParseResult.GetValueForOption(InlineExternalOption);
Expand All @@ -54,7 +56,7 @@ public async Task<int> InvokeAsync(InvocationContext context)
var logger = loggerFactory.CreateLogger<OpenApiService>();
try
{
await OpenApiService.TransformOpenApiDocument(openapi, csdl, csdlFilter, output, cleanOutput, version, format, terseOutput, logLevel, inlineLocal, inlineExternal, filterbyoperationids, filterbytags, filterbycollection, cancellationToken);
await OpenApiService.TransformOpenApiDocument(openapi, csdl, csdlFilter, output, cleanOutput, version, format, terseOutput, settingsFile, logLevel, inlineLocal, inlineExternal, filterbyoperationids, filterbytags, filterbycollection, cancellationToken);

return 0;
}
Expand Down
9 changes: 9 additions & 0 deletions src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,20 @@
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="Microsoft.OData.Edm" Version="7.12.5" />
<PackageReference Include="Microsoft.OpenApi.OData" Version="1.2.0-preview6" />
<PackageReference Include="System.CommandLine.Hosting" Version="0.4.0-alpha.22114.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Microsoft.OpenApi.Readers\Microsoft.OpenApi.Readers.csproj" />
<ProjectReference Include="..\Microsoft.OpenApi\Microsoft.OpenApi.csproj" />
</ItemGroup>

<!-- Make internals available for Unit Testing -->
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Microsoft.OpenApi.Hidi.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
<!-- End Unit test Internals -->

</Project>
26 changes: 22 additions & 4 deletions src/Microsoft.OpenApi.Hidi/OpenApiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
using System.Xml.Xsl;
using System.Xml;
using System.Reflection;
using Microsoft.Extensions.Configuration;
using System.Runtime.CompilerServices;

namespace Microsoft.OpenApi.Hidi
{
Expand All @@ -44,6 +46,7 @@ public static async Task TransformOpenApiDocument(
string? version,
OpenApiFormat? format,
bool terseOutput,
string settingsFile,
LogLevel logLevel,
bool inlineLocal,
bool inlineExternal,
Expand Down Expand Up @@ -98,7 +101,8 @@ CancellationToken cancellationToken
stream = ApplyFilter(csdl, csdlFilter, transform);
stream.Position = 0;
}
document = await ConvertCsdlToOpenApi(stream);

document = await ConvertCsdlToOpenApi(stream, settingsFile);
stopwatch.Stop();
logger.LogTrace("{timestamp}ms: Generated OpenAPI with {paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count);
}
Expand Down Expand Up @@ -304,25 +308,37 @@ public static async Task ValidateOpenApiDocument(
}
}

internal static IConfiguration GetConfiguration(string settingsFile)
{
settingsFile ??= "appsettings.json";

IConfiguration config = new ConfigurationBuilder()
.AddJsonFile(settingsFile, true)
.Build();

return config;
}

/// <summary>
/// Converts CSDL to OpenAPI
/// </summary>
/// <param name="csdl">The CSDL stream.</param>
/// <returns>An OpenAPI document.</returns>
public static async Task<OpenApiDocument> ConvertCsdlToOpenApi(Stream csdl)
public static async Task<OpenApiDocument> ConvertCsdlToOpenApi(Stream csdl, string settingsFile = null)
{
using var reader = new StreamReader(csdl);
var csdlText = await reader.ReadToEndAsync();
var edmModel = CsdlReader.Parse(XElement.Parse(csdlText).CreateReader());


var config = GetConfiguration(settingsFile);
var settings = new OpenApiConvertSettings()
{
AddSingleQuotesForStringParameters = true,
AddEnumDescriptionExtension = true,
DeclarePathParametersOnPathItem = true,
EnableKeyAsSegment = true,
EnableOperationId = true,
ErrorResponsesAsDefault = false,
ErrorResponsesAsDefault = false,
PrefixEntityTypeNameBeforeKey = true,
TagDepth = 2,
EnablePagination = true,
Expand All @@ -335,6 +351,8 @@ public static async Task<OpenApiDocument> ConvertCsdlToOpenApi(Stream csdl)
EnableCount = true,
UseSuccessStatusCodeRange = true
};
config.GetSection("OpenApiConvertSettings").Bind(settings);

OpenApiDocument document = edmModel.ConvertToOpenApi(settings);

document = FixReferences(document);
Expand Down
11 changes: 11 additions & 0 deletions src/Microsoft.OpenApi.Hidi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@
// Licensed under the MIT license.

using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Hosting;
using System.CommandLine.Parsing;

using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Hidi.Handlers;

Expand Down Expand Up @@ -41,6 +47,9 @@ static async Task Main(string[] args)
var terseOutputOption = new Option<bool>("--terse-output", "Produce terse json output");
terseOutputOption.AddAlias("--to");

var settingsFileOption = new Option<string>("--settings-path", "The configuration file with CSDL conversion settings.");
settingsFileOption.AddAlias("--sp");

var logLevelOption = new Option<LogLevel>("--log-level", () => LogLevel.Information, "The log level to use when logging messages to the main output.");
logLevelOption.AddAlias("--ll");

Expand Down Expand Up @@ -81,6 +90,7 @@ static async Task Main(string[] args)
versionOption,
formatOption,
terseOutputOption,
settingsFileOption,
logLevelOption,
filterByOperationIdsOption,
filterByTagsOption,
Expand All @@ -99,6 +109,7 @@ static async Task Main(string[] args)
VersionOption = versionOption,
FormatOption = formatOption,
TerseOutputOption = terseOutputOption,
SettingsFileOption = settingsFileOption,
LogLevelOption = logLevelOption,
FilterByOperationIdsOption = filterByOperationIdsOption,
FilterByTagsOption = filterByTagsOption,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
</ItemGroup>

<ItemGroup>
<None Update="UtilityFiles\appsettingstest.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="UtilityFiles\postmanCollection_ver1.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down
26 changes: 23 additions & 3 deletions test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.OpenApi.Hidi;
using Microsoft.OpenApi.OData;
using Microsoft.OpenApi.Services;
using Xunit;

Expand Down Expand Up @@ -51,5 +50,26 @@ public async Task ReturnFilteredOpenApiDocBasedOnOperationIdsAndInputCsdlDocumen
Assert.NotEmpty(subsetOpenApiDocument.Paths);
Assert.Equal(expectedPathCount, subsetOpenApiDocument.Paths.Count);
}

[Theory]
[InlineData("UtilityFiles/appsettingstest.json")]
[InlineData(null)]
public void ReturnOpenApiConvertSettingsWhenSettingsFileIsProvided(string filePath)
{
// Arrange
var config = OpenApiService.GetConfiguration(filePath);

// Act and Assert
var settings = config.GetSection("OpenApiConvertSettings").Get<OpenApiConvertSettings>();

if (filePath == null)
{
Assert.Null(settings);
}
else
{
Assert.NotNull(settings);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"OpenApiConvertSettings": {
"AddSingleQuotesForStringParameters": "true",
"AddEnumDescriptionExtension": "true",
"DeclarePathParametersOnPathItem": "true",
"EnableKeyAsSegment": "true",
"EnableOperationId": "true",
"ErrorResponsesAsDefault": "false",
"PrefixEntityTypeNameBeforeKey": "true",
"TagDepth": 2,
"EnablePagination": "true",
"EnableDiscriminatorValue": "true",
"EnableDerivedTypesReferencesForRequestBody": "false",
"EnableDerivedTypesReferencesForResponses": "false",
"ShowRootPath": "false",
"ShowLinks": "false",
"ExpandDerivedTypesNavigationProperties": "false",
"EnableCount": "true",
"UseSuccessStatusCodeRange": "true"
}
}