GithubHelp home page GithubHelp logo

jasperfx / oakton Goto Github PK

View Code? Open in Web Editor NEW
296.0 296.0 37.0 17.06 MB

Parsing and Utilities for Command Line Tools in .Net

Home Page: http://jasperfx.github.io/oakton

License: Apache License 2.0

Batchfile 0.02% C# 97.10% Shell 0.03% HTML 2.42% CSS 0.34% JavaScript 0.07% PowerShell 0.02%

oakton's People

Contributors

agross avatar aidanjryan avatar bdukes avatar bitbonk avatar devhb avatar ejsmith avatar gitter-badger avatar jeremydmiller avatar jokokko avatar kuanpak avatar lfoust avatar mgroves avatar mysticmind avatar ndcomplete avatar ondrejvicar avatar oskardudycz avatar pondidum avatar raleighbuckner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oakton's Issues

Wrong help generated for dictionaries

Generated help for dictionaries is wrong, as it includes 4 dashes (----) instead of 2

public class RunInput {

  [Description("The connection string", Name = "connection-string")]
  public string ConnectionString { get; set; }

  [Description("Check scripts to be applied, but do not run them")]
  [FlagAlias("dry-run")]
  public bool DryRunFlag { get; set; }

  [Description("An optional list of variables to be used in scripts")]
  public Dictionary<string, string> VarFlag { get; set; } = new Dictionary<string, string>();
}
run - Create or update a database
└── Create or update a database
    └── dotnet run -- run <connectionstring>
        ├── [-d, --dry-run]
        └── [----var:<prop> <value>]

I guess this happens as a result of

private static readonly string LONG_FLAG_PREFIX = "--";

return new FlagAliases
{
ShortForm = (SHORT_FLAG_PREFIX + oneLetterName),
LongForm = LONG_FLAG_PREFIX + name.ToLower(),
LongFormOnly = longFormOnly
};

var flagAliases = InputParser.ToFlagAliases(Member);
_prefix = flagAliases.LongForm + ":";

and finally

return $"[--{_prefix}<prop> <value>]";

Console application doesn't exit when using RunOaktonCommands for HostBuilder

When using code below the application remains running after Startup.StartAsync completed. When I replace .RunOaktonCommands(args); with .RunConsoleAsync(); it shuts down fine

       static Task<int> Main(string[] args)
        {
            var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
                .Build();

            return CreateHostBuilder(args).ConfigureLogging(logging =>
                {
                    logging.ClearProviders();
                }
                )
                .UseSerilog()
                .ConfigureServices((_, services) =>
                {
                    services.AddDescription<OaktonConfigDescription>();
                    services.AddHostedService<Startup>();
                }
                ).RunOaktonCommands(args); 
        }

New Oakton.AspNetCore extension for AspNetCore command runners

Well underway and most of the code is copied straight over from Jasper.

The initial feature set:

  • "run" command that adds extra options for running AspNetCore apps with variable environment flags, config values, and logging levels
  • Extension method on WebHostBuilder to run Oakton commands
  • Tests;)
  • Documentation

Duplicate short flag alias when 2 argument properties start with the same alphabet

If we take the example as below, both properties start with S and no custom flag alias are defined. For this case, s is being generated as the short flag alias for both the properties.

public class ProjectionInput
{
    [Description("If specified, only execute against the named Marten store. Does not apply with only one store")]
    public string StoreFlag { get; set; }
 
    [Description("If specified, use this shard timeout value for daemon")]
    public string ShardTimeoutFlag { get; set; }
}

I think for these cases, we should only add a long flag and ignore short flags. The workaround is to explicitly define the flag alias.

New "stateful resource" model

New command line for generically interacting with stateful resources like Rabbit MQ, databases, etc. at the command line.

Should be able to:

  • Set up resources
  • Teardown resources
  • Clear resource state
  • Check the resource, which would feed right into an environment check

Optional arguments broken in 2.0

afc4f12#diff-1653881f4444af532bfaf6787fb0c0f4

This commit broke possibility of optional arguments

-            var command = Build(commandName);
+            var usages = new UsageGraph(_commandTypes[commandName]);

This change missing "configuration" of usages in constructor of command and always validate on "default" usage with all arguments.

This change in behavior was intended?

Should not parse flags from IEnumerable<string>

I'm trying to forward args to a BenchmarkDotNet method:

BenchmarkSwitcher.Run(string[] args, ...)

BenchmarkDotNet expects war Main(string[] args) args and is run in the following manner:

dotnet run -c Release -- --job short --runtimes clr core --filter *BenchmarkClass1*

My input class looks as follows:

public class BenchInput : RickInput
{
    [Description("BenchmarkDotNet Run args")]
    public IEnumerable<string> Args { get; set; }
}

Is there a way to use Oakton to propagate string args[] "verbatim" ?

Usage breaks logging

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Oakton;
using Serilog;
using Serilog.Events;

namespace LegacyEnterpriseSync
{
    public class Program
    {
	    public static Task<int> Main(string[] args)
	    {
		    Log.Logger = new LoggerConfiguration()
			    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
			    .MinimumLevel.Debug()
			    .Enrich.FromLogContext()
			    .WriteTo.Console()
			    .CreateLogger();

		    try
		    {
			    Log.Information("Starting web host");
			    return CreateHostBuilder(args).RunOaktonCommands(args);
			    // CreateHostBuilder(args).Build().Run();
			    // return Task.FromResult(0);
		    }
		    catch (Exception ex)
		    {
			    Log.Fatal(ex, "Host terminated unexpectedly");
			    return Task.FromResult(1);
		    }
		    finally
		    {
			    Log.CloseAndFlush();
		    }
	    }

	    public static IHostBuilder CreateHostBuilder(string[] args) =>
		    Host
			    .CreateDefaultBuilder(args)
			    .UseSerilog((context, servicesProvider, loggingConfig) =>
			    {
				    loggingConfig.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
					    .MinimumLevel.Debug()
					    .Enrich.FromLogContext()
					    .WriteTo.Console();
			    })
			    .ConfigureAppConfiguration(configBuilder => { configBuilder.AddEnvironmentVariables(); })
			    .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
    }
}

The app runs, but request logging, etc. is not printing to the console. Only that first message before the Oakton function's call.

When I instead use:

CreateHostBuilder(args).Build().Run();
return Task.FromResult(0);

All the logging takes place as expected. I have tried with and without the 2 stage logger initialization using the lambda:

(context, servicesProvider, loggingConfig) =>
{
    loggingConfig.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
	    .MinimumLevel.Debug()
	    .Enrich.FromLogContext()
	    .WriteTo.Console();
}

Accept RegisterCommand(typeof(T))

Hi!

First of all, super cool library. Thanks for sharing it.

Currently, it seems there is two ways to register commands on CommandFactory::

RegisterCommand<T>()
RegisterCommands(Assembly assembly)

I need register by Type not using generics.

RegisterCommand(typeof(T))

Would you accept a pull request for that?

Thanks again.

Build out the new dotnet-assembly-info command line tool

Be a decent sample app, and it's something we want anyway.

Nice if you could:

  • Poke in a description
  • Read the git commit sha (reverse engineer from old FubuRake code)
  • Push in version pattern and build number
  • Flag to have it look up the version from the project.json file
  • Flag to write a version to the project.json file? See what Corey did in Marten

Here's what we write out as the CommonAssemblyInfo.cs file in fubumvc:

puts "Writing src/CommonAssemblyInfo.cs..."
File.open('src/CommonAssemblyInfo.cs', 'w') do |file|
file.write "using System.Reflection;\n"
file.write "using System.Runtime.InteropServices;\n"
file.write "[assembly: AssemblyDescription("#{options[:description]}")]\n"
file.write "[assembly: AssemblyProduct("#{options[:product_name]}")]\n"
file.write "[assembly: AssemblyCopyright("#{options[:copyright]}")]\n"
file.write "[assembly: AssemblyTrademark("#{options[:trademark]}")]\n"
file.write "[assembly: AssemblyVersion("#{options[:version]}")]\n"
file.write "[assembly: AssemblyFileVersion("#{options[:file_version]}")]\n"
file.write "[assembly: AssemblyInformationalVersion("#{options[:informational_version]}")]\n"
end

end

"Activator" for resource setup

This will need to be explicitly configured. Do similar to the ApplyChangesOnStartup in Marten, but make it more general on resources

Mandatory arguments

Hi,
First of all, thank for sharing your project.

It is possible to mark some arguments as mandatory ?

mandatory in the sense that if they are missing then we have an error.

Usage with optional arguments broken

Trying out the library. Copy pasted the Getting Started example. The usage with optional arguments does not work.

When running:

dotnet run -- "Alex Smith"

it always shows the Invalid Usage until you specify the color as well:

dotnet run -- "Alex Smith" Green

Support for System.ComponentModel.DataAnnotations.DisplayAttribute

The included DescriptionAttribute is nice and simple but it would be nice to be able to put my command descriptions in resources and potentially translate them.

I've just done some (albeit very quick) checking and the System.ComponentModel.Annotations nuget package seems to support all the platforms oakton targets and that should make it possible to set the description on a command with a line like the following:

_commandType.ForAttribute<DisplayAttribute>(att => { _description = att.GetDescription(); });

Did you have specific reasons for not doing this in the first place or has it just not been needed yet? Would you be interested in a PR if I implemented it?

New "Describe" command

New addition to Oakton.AspNetCore to add self descriptive services to the application to "describe" itself. This is taken from the DescribeCommand in Jasper and will replace that.

Use an interface like this?

    /// <summary>
    /// Use this to provide diagnostic information about your application
    /// Jasper will discover and use any service registered in the IoC
    /// container that implements this interface
    /// </summary>
    public interface IDescribeMyself
    {
        Task Describe(TextWriter writer);
        string Title {get;}
    }

The new Oakton.AspNetcore command will loop through all of these and spit it out to the screen and/or a file.

opts file

Opt in by adding it as an option to CommandExecutor.

Work by adding each line to the beginning of the command line. Make sure that you can override commands.

Test that:

  • It's applied if it exists
  • Nothing happens if it's not
  • Can override
  • multiple lines

Name/Value flags

Thinking a syntax like:

--prop:Key Value

and

public class SomeInput
{
    public Dictionary<string, string> Props {get;set;}
}

Cannot set environment because IHost is already constructed in .NET 6 web app

Symptom

Running a command like dotnet run -- db-patch file.sql --environment Staging results in the following error:

image

Context

I tried to set up my .NET 6 web application as described in the docs. In summary, my Program.cs file looks like the following:

var builder = WebApplication.CreateBuilder(args);
builder.Host.ApplyOaktonExtensions();
// ... other changes in the host builder (e.g. builder.Services.AddAuthentication())
var app = builder.Build();
// ... changes in the app (e.g. app.UseAuthentication())
return await app.RunOaktonCommands(args);

My development environment is a macOS with Apple silicon.

Usage of opts file

I cannot figure out usage of the .opts file.

I have commands that have flags. When I make an .opts file that contains some of these flags, Oakton tells me:
Invalid usage Unknown argument or flag for value

When I include the command in the .opts file, Oakton tells me the same thing. How should I use the .opts file?

Incidentally, I love this library! :-)

[FlagAlias] can it be used for arguments?

The documentation shows an example of where [FlagAlias] is used on a property called "c", which is an argument, not a flag. When I use [FlagAlias] on my arguments, it doesn't work. Since it doesn't work, I have no way of making a required named parameter. I'd certainly like to be explicit about names on all my parameters while having a way to mark them required, because a lot of parameters can make the command unruly and unreadable.

.NET 6?

How do I get this to work in .NET 6?

"describe" command throws exception when configuration values contain "["

Oakton version: 4.6.1

Error can be reproduced by below code and appsettings.json.

C# code:

using Oakton;

var builder = WebApplication.CreateBuilder(args);
builder.Host.ApplyOaktonExtensions();

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

return await app.RunOaktonCommands(args);

appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ProblemConfig": "value with [bracket]"
}

When run dotnet run describe, it will throw below exception:

ERROR: System.InvalidOperationException: Could not find color or style 'bracket'.

Solution

I've submitted a PR #69 for fixing this issue by applying EscapeMarkup().

Sub-commands?

I'm wondering if there is currently any supported way to use sub-commands?

I'm thinking of the way the Docker CLI works, for example:

docker container rm abc
docker volume ls

We can break down the first example like:

docker  container  rm             abc
^ app   ^command   ^ sub-command  ^ args

I thought perhaps command aliases could have a space in them, which could make this work:

[Description("List volumes", Name = "volume ls")]
public class ListVolumesCommand : OaktonAsyncCommand<ListVolumeInput>

Unfortunately this doesn't work, and I guess it would break handling of enumerable arguments.

Arguments and flags do not handle negative numbers

Hi there,
I've been trying to use this great tool for some command line apps we write. Most of the functionality works quite well. However, I can't seem to be able to parse negative numbers properly. Specifically, multi-digit ones seem to cause the most trouble (I am wrapping in quotes, and that does seem to make single digit negative numbers happy).

I've created a simple repo with xunit tests that shows this behaviour:
https://github.com/chrispellett/OaktonCommandParsingSandbox

Any help would be greatly appreciated.

Thanks!

Environment Check command in AspNetCore extension

Ability to do environment checks on startup of the app.

  • Basic environment check model. Already underway
  • Built in file existence check for file existing
  • Built in directory read check
  • Separate command to only do "env-check" to run all environment checks
  • Flag on "run" command to execute the checks
  • Built in service registration requirement

2.0 Documentation Updates

  • Only supporting netstandard 2.0 and net 4.6+
  • RegisterCommand(type)
  • Extension assembly discovery
  • Better command factory mechanics
  • AspNetCore extension
  • Environment Checks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.