-
Notifications
You must be signed in to change notification settings - Fork 65
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
Cli parser fixups #116
Cli parser fixups #116
Changes from 6 commits
54b7cd5
c289504
4d93c8c
01f497d
cfefca2
4c980b4
82aea30
2ec178a
57a0914
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,11 +7,14 @@ | |
// ----------------------------------------------------------------------- | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
using CommandLine; | ||
using CommandLine.Text; | ||
|
||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.AspNetCore.Server.Kestrel.Core; | ||
|
@@ -57,21 +60,30 @@ public static void Main(string[] args) | |
{ | ||
string executableFilePath = null; | ||
Uri optimizerAddressUri = null; | ||
IEnumerable<string> extraArgs = null; | ||
|
||
var cliOptsParseResult = CommandLine.Parser.Default.ParseArguments<CliOptions>(args) | ||
var cliOptsParser = new Parser(with => with.HelpWriter = null); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We add custom help output handling with |
||
var cliOptsParseResult = cliOptsParser.ParseArguments<CliOptions>(args) | ||
.WithParsed(parsedOptions => | ||
{ | ||
executableFilePath = parsedOptions.Executable; | ||
optimizerAddressUri = parsedOptions.OptimizerUri; | ||
extraArgs = parsedOptions.ExtraArgs; | ||
}); | ||
if (cliOptsParseResult.Tag == ParserResultType.NotParsed) | ||
{ | ||
// CommandLine already prints the help text for us in this case. | ||
// | ||
Console.Error.WriteLine("Failed to parse command line options."); | ||
Environment.Exit(1); | ||
cliOptsParseResult.WithNotParsed(errs => ShowUsageHelp( | ||
cliOptsParseResult, | ||
errors: errs, | ||
msg: "Failed to parse command line options.")); | ||
} | ||
else if (extraArgs != null && extraArgs.Any()) | ||
{ | ||
ShowUsageHelp(cliOptsParseResult, msg: "Extra arguments found."); | ||
bpkroth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
cliOptsParser.Dispose(); | ||
|
||
// Check for the executable before setting up any shared memory to | ||
// reduce cleanup issues. | ||
// | ||
|
@@ -220,6 +232,71 @@ public static void Main(string[] args) | |
Console.WriteLine("Mlos.Agent exited."); | ||
} | ||
|
||
private static void ShowUsageHelp<T>(ParserResult<T> parserResult, IEnumerable<Error> errors = null, string msg = null) | ||
{ | ||
if (msg != null) | ||
{ | ||
Console.Error.WriteLine(msg); | ||
Console.Error.WriteLine(string.Empty); | ||
bpkroth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
if (errors == null) | ||
{ | ||
errors = new List<Error>(); | ||
} | ||
|
||
HelpText helpText = null; | ||
if (errors.IsVersion()) | ||
{ | ||
helpText = HelpText.AutoBuild(parserResult); | ||
} | ||
else | ||
{ | ||
helpText = HelpText.AutoBuild( | ||
parserResult, | ||
onError: ht => | ||
{ | ||
return HelpText.DefaultParsingErrorsHandler(parserResult, ht); | ||
}, | ||
e => e); | ||
helpText.AddNewLineBetweenHelpSections = true; | ||
helpText.AddPreOptionsLines(new[] | ||
{ | ||
// Use a single long line of text to let the help output get wrapped automatically for us. | ||
bpkroth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"The Mlos.Agent.Server acts as an external agent for MLOS integrated components, allowing them to " | ||
+ "send it messages over shared memory, which it can process and use to interface with an optimizer " | ||
+ "service to tune the components over their shared memory communication channels.", | ||
string.Empty, | ||
|
||
// Indent the actual commands to make them stand out a bit more. | ||
// Note: The help out preserves the indent across wrapping. | ||
"usage mode 1: Wait for an application to register over global shared memory, without an optimizer.", | ||
" dotnet Mlos.Agent.Server.dll", | ||
string.Empty, | ||
|
||
"usage mode 2: Wait for an application to register over global shared memory, and prepare to " | ||
+ "communicate with an MLOS optimizer listening at the given Grpc URI.", | ||
" dotnet Mlos.Agent.Server.dll --optimizer-uri http://localhost:50051", | ||
string.Empty, | ||
|
||
"usage mode 3: Start an executable to communicate over freshly prepared global shared memory.", | ||
" dotnet Mlos.Agent.Server.dll --executable path/to/executable", | ||
string.Empty, | ||
|
||
"usage mode 4: Start an executable to communicate over freshly prepared global shared memory and " | ||
+ "prepare to communicate with an MLOS optimizer listening at the given Grpc URI.", | ||
" dotnet Mlos.Agent.Server.dll --executable path/to/executable --optimizer-uri http://localhost:50051", | ||
string.Empty, | ||
|
||
"Note: the optimizer service used in these examples can be started using the 'start_optimizer_microservice " | ||
+ "launch --port 50051' command from the mlos Python module.", | ||
}); | ||
} | ||
|
||
Console.WriteLine(helpText); | ||
Environment.Exit(1); | ||
} | ||
|
||
/// <summary> | ||
/// The command line options for this application. | ||
/// </summary> | ||
|
@@ -230,6 +307,13 @@ private class CliOptions | |
|
||
[Option("optimizer-uri", Required = false, Default = null, HelpText = "A URI to connect to the MLOS Optimizer service over GRPC (e.g. 'http://localhost:50051').")] | ||
public Uri OptimizerUri { get; set; } | ||
|
||
/// <remarks> | ||
/// Just used to detect any extra arguments so we can throw a warning. | ||
/// See Also: https://github.com/microsoft/MLOS/issues/112. | ||
/// </remarks> | ||
[CommandLine.Value(0)] | ||
public IEnumerable<string> ExtraArgs { get; set; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This option unfortunately isn't hidden and leaves a weird |
||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixup for the default debugger experience.
If this options are enabled by default, the command will fail.
In the future we can consider to add a
preLaunchTask
that starts the optimizer service.