From 93464f44aa1caf384b8a94dcc76a600eae6b2ac3 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 1 Aug 2022 10:45:28 +0300 Subject: [PATCH 1/5] Bumps up System.Commandline API to v2.0.0-beta4.22272.1 and resolve breaking change --- .../Handlers/TransformCommandHandler.cs | 73 +++++++++++++++++++ .../Handlers/ValidateCommandHandler.cs | 49 +++++++++++++ .../Microsoft.OpenApi.Hidi.csproj | 14 ++-- src/Microsoft.OpenApi.Hidi/Program.cs | 28 +++++-- 4 files changed, 152 insertions(+), 12 deletions(-) create mode 100644 src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs create mode 100644 src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs new file mode 100644 index 000000000..8123f4620 --- /dev/null +++ b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.CommandLine; +using System.CommandLine.Invocation; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; + +namespace Microsoft.OpenApi.Hidi.Handlers +{ + internal class TransformCommandHandler : ICommandHandler + { + public Option DescriptionOption { get; set; } + public Option CsdlOption { get; set; } + public Option CsdlFilterOption { get; set; } + public Option OutputOption { get; set; } + public Option CleanOutputOption { get; set; } + public Option VersionOption { get; set; } + public Option FormatOption { get; set; } + public Option TerseOutputOption { get; set; } + public Option LogLevelOption { get; set; } + public Option FilterByOperationIdsOption { get; set; } + public Option FilterByTagsOption { get; set; } + public Option FilterByCollectionOption { get; set; } + public Option InlineLocalOption { get; set; } + public Option InlineExternalOption { get; set; } + + public int Invoke(InvocationContext context) + { + return InvokeAsync(context).GetAwaiter().GetResult(); + } + public async Task InvokeAsync(InvocationContext context) + { + string openapi = context.ParseResult.GetValueForOption(DescriptionOption); + string csdlFilter = context.ParseResult.GetValueForOption(CsdlFilterOption); + string csdl = context.ParseResult.GetValueForOption(CsdlOption); + FileInfo output = context.ParseResult.GetValueForOption(OutputOption); + bool cleanOutput = context.ParseResult.GetValueForOption(CleanOutputOption); + string? version = context.ParseResult.GetValueForOption(VersionOption); + OpenApiFormat? format = context.ParseResult.GetValueForOption(FormatOption); + bool terseOutput = context.ParseResult.GetValueForOption(TerseOutputOption); + LogLevel logLevel = context.ParseResult.GetValueForOption(LogLevelOption); + bool inlineLocal = context.ParseResult.GetValueForOption(InlineLocalOption); + bool inlineExternal = context.ParseResult.GetValueForOption(InlineExternalOption); + string filterbyoperationids = context.ParseResult.GetValueForOption(FilterByOperationIdsOption); + string filterbytags = context.ParseResult.GetValueForOption(FilterByTagsOption); + string filterbycollection = context.ParseResult.GetValueForOption(FilterByCollectionOption); + CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetService(typeof(CancellationToken)); + + var logger = Logger.ConfigureLogger(logLevel); + + try + { + await OpenApiService.TransformOpenApiDocument(openapi, csdl, csdlFilter, output, cleanOutput, version, format, terseOutput, logLevel, inlineLocal, inlineExternal, filterbyoperationids, filterbytags, filterbycollection, cancellationToken); + + return 0; + } + catch (Exception ex) + { +#if DEBUG + logger.LogCritical(ex, ex.Message); + throw; // so debug tools go straight to the source of the exception when attached +#else + logger.LogCritical( ex.Message); + return 1; +#endif + } + } + } +} diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs new file mode 100644 index 000000000..84ffcc122 --- /dev/null +++ b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.CommandLine; +using System.CommandLine.Invocation; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; + +namespace Microsoft.OpenApi.Hidi.Handlers +{ + internal class ValidateCommandHandler : ICommandHandler + { + public Option DescriptionOption { get; set; } + public Option LogLevelOption { get; set; } + + public int Invoke(InvocationContext context) + { + return InvokeAsync(context).GetAwaiter().GetResult(); + } + public async Task InvokeAsync(InvocationContext context) + { + string openapi = context.ParseResult.GetValueForOption(DescriptionOption); + LogLevel logLevel = context.ParseResult.GetValueForOption(LogLevelOption); + CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetService(typeof(CancellationToken)); + + + var logger = Logger.ConfigureLogger(logLevel); + + try + { + await OpenApiService.ValidateOpenApiDocument(openapi, logLevel, cancellationToken); + return 0; + } + catch (Exception ex) + { +#if DEBUG + logger.LogCritical(ex, ex.Message); + throw; // so debug tools go straight to the source of the exception when attached +#else + logger.LogCritical( ex.Message); + Environment.Exit(1); + return 1; +#endif + } + } + } +} diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index cee484046..e48cecc8b 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -37,13 +37,13 @@ - - - - - - - + + + + + + + diff --git a/src/Microsoft.OpenApi.Hidi/Program.cs b/src/Microsoft.OpenApi.Hidi/Program.cs index c8ba8fdcd..88c72fa8b 100644 --- a/src/Microsoft.OpenApi.Hidi/Program.cs +++ b/src/Microsoft.OpenApi.Hidi/Program.cs @@ -1,12 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using System; using System.CommandLine; using System.IO; -using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Microsoft.OpenApi.Hidi.Handlers; namespace Microsoft.OpenApi.Hidi { @@ -66,7 +65,11 @@ static async Task Main(string[] args) logLevelOption }; - validateCommand.SetHandler(OpenApiService.ValidateOpenApiDocument, descriptionOption, logLevelOption); + validateCommand.Handler = new ValidateCommandHandler + { + DescriptionOption = descriptionOption, + LogLevelOption = logLevelOption + }; var transformCommand = new Command("transform") { @@ -86,8 +89,23 @@ static async Task Main(string[] args) inlineExternalOption }; - transformCommand.SetHandler ( - OpenApiService.TransformOpenApiDocument, descriptionOption, csdlOption, csdlFilterOption, outputOption, cleanOutputOption, versionOption, formatOption, terseOutputOption, logLevelOption, inlineLocalOption, inlineExternalOption, filterByOperationIdsOption, filterByTagsOption, filterByCollectionOption); + transformCommand.Handler = new TransformCommandHandler + { + DescriptionOption = descriptionOption, + CsdlOption = csdlOption, + CsdlFilterOption = csdlFilterOption, + OutputOption = outputOption, + CleanOutputOption = cleanOutputOption, + VersionOption = versionOption, + FormatOption = formatOption, + TerseOutputOption = terseOutputOption, + LogLevelOption = logLevelOption, + FilterByOperationIdsOption = filterByOperationIdsOption, + FilterByTagsOption = filterByTagsOption, + FilterByCollectionOption = filterByCollectionOption, + InlineLocalOption = inlineLocalOption, + InlineExternalOption = inlineExternalOption + }; rootCommand.Add(transformCommand); rootCommand.Add(validateCommand); From 8a91397ceb4a9ebe7d5de38c47d668e13e6cbd2e Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 1 Aug 2022 10:46:07 +0300 Subject: [PATCH 2/5] Add logger class for easy reuse and clean up code --- src/Microsoft.OpenApi.Hidi/Logger.cs | 35 ++++++++++++++++++++ src/Microsoft.OpenApi.Hidi/OpenApiService.cs | 34 ++++--------------- 2 files changed, 42 insertions(+), 27 deletions(-) create mode 100644 src/Microsoft.OpenApi.Hidi/Logger.cs diff --git a/src/Microsoft.OpenApi.Hidi/Logger.cs b/src/Microsoft.OpenApi.Hidi/Logger.cs new file mode 100644 index 000000000..cca906949 --- /dev/null +++ b/src/Microsoft.OpenApi.Hidi/Logger.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Extensions.Logging; + +namespace Microsoft.OpenApi.Hidi +{ + public class Logger + { + public static ILogger ConfigureLogger(LogLevel logLevel) + { + // Configure logger options +#if DEBUG + logLevel = logLevel > LogLevel.Debug ? LogLevel.Debug : logLevel; +#endif + + using var loggerFactory = LoggerFactory.Create((builder) => + { + builder + .AddSimpleConsole(c => + { + c.IncludeScopes = true; + }) +#if DEBUG + .AddDebug() +#endif + .SetMinimumLevel(logLevel); + }); + + var logger = loggerFactory.CreateLogger(); + + return logger; + } + } +} diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 8e1838d95..79b518507 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -26,7 +26,6 @@ using System.Threading; using System.Xml.Xsl; using System.Xml; -using System.Runtime.CompilerServices; using System.Reflection; namespace Microsoft.OpenApi.Hidi @@ -36,7 +35,7 @@ public class OpenApiService /// /// Implementation of the transform command /// - public static async Task TransformOpenApiDocument( + public static async Task TransformOpenApiDocument( string openapi, string csdl, string csdlFilter, @@ -54,8 +53,7 @@ public static async Task TransformOpenApiDocument( CancellationToken cancellationToken ) { - using var loggerFactory = ConfigureLoggerInstance(loglevel); - var logger = loggerFactory.CreateLogger(); + var logger = Logger.ConfigureLogger(loglevel); try { @@ -212,18 +210,11 @@ CancellationToken cancellationToken logger.LogTrace($"Finished serializing in {stopwatch.ElapsedMilliseconds}ms"); textWriter.Flush(); } - return 0; } catch (Exception ex) { -#if DEBUG - logger.LogCritical(ex, ex.Message); -#else - logger.LogCritical(ex.Message); - -#endif - return 1; - } + throw new InvalidOperationException($"Could not transform the document, reason: {ex.Message}", ex); + } } private static XslCompiledTransform GetFilterTransform() @@ -249,18 +240,15 @@ private static Stream ApplyFilter(string csdl, string entitySetOrSingleton, XslC return stream; } - - /// /// Implementation of the validate command /// - public static async Task ValidateOpenApiDocument( + public static async Task ValidateOpenApiDocument( string openapi, LogLevel loglevel, CancellationToken cancellationToken) { - using var loggerFactory = ConfigureLoggerInstance(loglevel); - var logger = loggerFactory.CreateLogger(); + var logger = Logger.ConfigureLogger(loglevel); try { @@ -308,19 +296,11 @@ public static async Task ValidateOpenApiDocument( logger.LogTrace("Finished walking through the OpenApi document. Generating a statistics report.."); logger.LogInformation(statsVisitor.GetStatisticsReport()); } - - return 0; } catch (Exception ex) { -#if DEBUG - logger.LogCritical(ex, ex.Message); -#else - logger.LogCritical(ex.Message); -#endif - return 1; + throw new InvalidOperationException($"Could not validate the document, reason: {ex.Message}", ex); } - } /// From a3b4b0d425d3a65791812e920df90baa7ddab687 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 3 Aug 2022 11:27:45 +0300 Subject: [PATCH 3/5] Clean up code --- src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs index 84ffcc122..194a1eba8 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs @@ -40,7 +40,6 @@ public async Task InvokeAsync(InvocationContext context) throw; // so debug tools go straight to the source of the exception when attached #else logger.LogCritical( ex.Message); - Environment.Exit(1); return 1; #endif } From 02570f58a9c8de39f1a211cc9180f944d0d359ef Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 3 Aug 2022 17:16:21 +0300 Subject: [PATCH 4/5] Refactor code --- .../Handlers/TransformCommandHandler.cs | 4 ++-- .../Handlers/ValidateCommandHandler.cs | 4 ++-- src/Microsoft.OpenApi.Hidi/Logger.cs | 8 ++------ src/Microsoft.OpenApi.Hidi/OpenApiService.cs | 16 ++++++++-------- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs index 8123f4620..e8d9431de 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs @@ -50,8 +50,8 @@ public async Task InvokeAsync(InvocationContext context) string filterbycollection = context.ParseResult.GetValueForOption(FilterByCollectionOption); CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetService(typeof(CancellationToken)); - var logger = Logger.ConfigureLogger(logLevel); - + using var loggerFactory = Logger.ConfigureLogger(logLevel); + var logger = loggerFactory.CreateLogger(); try { await OpenApiService.TransformOpenApiDocument(openapi, csdl, csdlFilter, output, cleanOutput, version, format, terseOutput, logLevel, inlineLocal, inlineExternal, filterbyoperationids, filterbytags, filterbycollection, cancellationToken); diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs index 194a1eba8..2faa771ea 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs @@ -26,8 +26,8 @@ public async Task InvokeAsync(InvocationContext context) CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetService(typeof(CancellationToken)); - var logger = Logger.ConfigureLogger(logLevel); - + using var loggerFactory = Logger.ConfigureLogger(logLevel); + var logger = loggerFactory.CreateLogger(); try { await OpenApiService.ValidateOpenApiDocument(openapi, logLevel, cancellationToken); diff --git a/src/Microsoft.OpenApi.Hidi/Logger.cs b/src/Microsoft.OpenApi.Hidi/Logger.cs index cca906949..2b02e9600 100644 --- a/src/Microsoft.OpenApi.Hidi/Logger.cs +++ b/src/Microsoft.OpenApi.Hidi/Logger.cs @@ -7,14 +7,14 @@ namespace Microsoft.OpenApi.Hidi { public class Logger { - public static ILogger ConfigureLogger(LogLevel logLevel) + public static ILoggerFactory ConfigureLogger(LogLevel logLevel) { // Configure logger options #if DEBUG logLevel = logLevel > LogLevel.Debug ? LogLevel.Debug : logLevel; #endif - using var loggerFactory = LoggerFactory.Create((builder) => + return LoggerFactory.Create((builder) => { builder .AddSimpleConsole(c => @@ -26,10 +26,6 @@ public static ILogger ConfigureLogger(LogLevel logLevel) #endif .SetMinimumLevel(logLevel); }); - - var logger = loggerFactory.CreateLogger(); - - return logger; } } } diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 0d2d5d531..c37c9479d 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -44,7 +44,7 @@ public static async Task TransformOpenApiDocument( string? version, OpenApiFormat? format, bool terseOutput, - LogLevel loglevel, + LogLevel logLevel, bool inlineLocal, bool inlineExternal, string filterbyoperationids, @@ -53,8 +53,8 @@ public static async Task TransformOpenApiDocument( CancellationToken cancellationToken ) { - var logger = Logger.ConfigureLogger(loglevel); - + using var loggerFactory = Logger.ConfigureLogger(logLevel); + var logger = loggerFactory.CreateLogger(); try { if (string.IsNullOrEmpty(openapi) && string.IsNullOrEmpty(csdl)) @@ -246,11 +246,11 @@ private static Stream ApplyFilter(string csdl, string entitySetOrSingleton, XslC /// public static async Task ValidateOpenApiDocument( string openapi, - LogLevel loglevel, + LogLevel logLevel, CancellationToken cancellationToken) { - var logger = Logger.ConfigureLogger(loglevel); - + using var loggerFactory = Logger.ConfigureLogger(logLevel); + var logger = loggerFactory.CreateLogger(); try { if (string.IsNullOrEmpty(openapi)) @@ -578,7 +578,7 @@ private static ILoggerFactory ConfigureLoggerInstance(LogLevel loglevel) loglevel = loglevel > LogLevel.Debug ? LogLevel.Debug : loglevel; #endif - return LoggerFactory.Create((builder) => { + return Microsoft.Extensions.Logging.LoggerFactory.Create((builder) => { builder .AddSimpleConsole(c => { c.IncludeScopes = true; From f0a0eb84a445b2760eab119cd668468a5d0be5cd Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Thu, 4 Aug 2022 14:31:38 +0300 Subject: [PATCH 5/5] Revert packages to stable versions --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 71570a9c4..c35c40209 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -37,10 +37,10 @@ - - - - + + + +