From b4b9445f175da6426d934388dc7f4bf4cd197fae Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Sat, 29 Feb 2020 17:04:21 -0800 Subject: [PATCH] m8s comands working in tye (#21) * m8s comands working in tye * fix styles --- samples/single-project/single-project.sln | 34 +++ .../single-project/test-project/Program.cs | 26 ++ .../Properties/launchSettings.json | 27 ++ .../single-project/test-project/Startup.cs | 40 +++ .../test-project/appsettings.Development.json | 9 + .../test-project/appsettings.json | 10 + .../test-project/test-project.csproj | 8 + .../Micronetes.Hosting.Runtime.csproj | 2 +- .../Micronetes.Hosting.csproj | 4 + .../Micronetes.Hosting/Model/Application.cs | 3 +- src/micronetes/m8s/Program.cs | 259 ------------------ .../m8s/Properties/launchSettings.json | 7 - src/micronetes/m8s/m8s.csproj | 20 -- src/tye/NameSanitizer.cs | 23 ++ src/tye/Program.InitCommand.cs | 153 +++++++++++ src/tye/Program.RunCommand.cs | 72 +++++ src/tye/Program.cs | 3 + src/tye/tye.csproj | 5 + tye.sln | 15 - 19 files changed, 417 insertions(+), 303 deletions(-) create mode 100644 samples/single-project/single-project.sln create mode 100644 samples/single-project/test-project/Program.cs create mode 100644 samples/single-project/test-project/Properties/launchSettings.json create mode 100644 samples/single-project/test-project/Startup.cs create mode 100644 samples/single-project/test-project/appsettings.Development.json create mode 100644 samples/single-project/test-project/appsettings.json create mode 100644 samples/single-project/test-project/test-project.csproj delete mode 100644 src/micronetes/m8s/Program.cs delete mode 100644 src/micronetes/m8s/Properties/launchSettings.json delete mode 100644 src/micronetes/m8s/m8s.csproj create mode 100644 src/tye/NameSanitizer.cs create mode 100644 src/tye/Program.InitCommand.cs create mode 100644 src/tye/Program.RunCommand.cs diff --git a/samples/single-project/single-project.sln b/samples/single-project/single-project.sln new file mode 100644 index 00000000..ca2cd174 --- /dev/null +++ b/samples/single-project/single-project.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test-project", "test-project\test-project.csproj", "{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|x64.ActiveCfg = Debug|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|x64.Build.0 = Debug|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|x86.ActiveCfg = Debug|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|x86.Build.0 = Debug|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|Any CPU.Build.0 = Release|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|x64.ActiveCfg = Release|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|x64.Build.0 = Release|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|x86.ActiveCfg = Release|Any CPU + {7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/samples/single-project/test-project/Program.cs b/samples/single-project/test-project/Program.cs new file mode 100644 index 00000000..4a68c9d5 --- /dev/null +++ b/samples/single-project/test-project/Program.cs @@ -0,0 +1,26 @@ +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; + +namespace test_project +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/samples/single-project/test-project/Properties/launchSettings.json b/samples/single-project/test-project/Properties/launchSettings.json new file mode 100644 index 00000000..94b22801 --- /dev/null +++ b/samples/single-project/test-project/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:18482", + "sslPort": 44344 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "test_project": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/single-project/test-project/Startup.cs b/samples/single-project/test-project/Startup.cs new file mode 100644 index 00000000..ad1ba81f --- /dev/null +++ b/samples/single-project/test-project/Startup.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace test_project +{ + public class Startup + { + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapGet("/", async context => + { + await context.Response.WriteAsync("Hello World!"); + }); + }); + } + } +} diff --git a/samples/single-project/test-project/appsettings.Development.json b/samples/single-project/test-project/appsettings.Development.json new file mode 100644 index 00000000..dba68eb1 --- /dev/null +++ b/samples/single-project/test-project/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/samples/single-project/test-project/appsettings.json b/samples/single-project/test-project/appsettings.json new file mode 100644 index 00000000..81ff8777 --- /dev/null +++ b/samples/single-project/test-project/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/samples/single-project/test-project/test-project.csproj b/samples/single-project/test-project/test-project.csproj new file mode 100644 index 00000000..2edaa9cb --- /dev/null +++ b/samples/single-project/test-project/test-project.csproj @@ -0,0 +1,8 @@ + + + + netcoreapp3.1 + test_project + + + diff --git a/src/micronetes/Micronetes.Hosting.Runtime/Micronetes.Hosting.Runtime.csproj b/src/micronetes/Micronetes.Hosting.Runtime/Micronetes.Hosting.Runtime.csproj index 201688ea..33f8a95d 100644 --- a/src/micronetes/Micronetes.Hosting.Runtime/Micronetes.Hosting.Runtime.csproj +++ b/src/micronetes/Micronetes.Hosting.Runtime/Micronetes.Hosting.Runtime.csproj @@ -2,7 +2,7 @@ netstandard2.0 - Runtime helpers for m8s host platform + Runtime helpers for tye host platform disable diff --git a/src/micronetes/Micronetes.Hosting/Micronetes.Hosting.csproj b/src/micronetes/Micronetes.Hosting/Micronetes.Hosting.csproj index b88f5bcc..93125759 100644 --- a/src/micronetes/Micronetes.Hosting/Micronetes.Hosting.csproj +++ b/src/micronetes/Micronetes.Hosting/Micronetes.Hosting.csproj @@ -13,6 +13,10 @@ + + + + diff --git a/src/micronetes/Micronetes.Hosting/Model/Application.cs b/src/micronetes/Micronetes.Hosting/Model/Application.cs index 2391191c..1f45195a 100644 --- a/src/micronetes/Micronetes.Hosting/Model/Application.cs +++ b/src/micronetes/Micronetes.Hosting/Model/Application.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Text.Json; using Microsoft.Build.Construction; +using Tye; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; @@ -250,7 +251,7 @@ namespace Micronetes.Hosting.Model // If there's a launchSettings.json, then use it to get addresses var root = JsonSerializer.Deserialize(File.ReadAllText(launchSettingsPath)); - var key = Path.GetFileNameWithoutExtension(projectFilePath); + var key = NameSanitizer.SanitizeToIdentifier(Path.GetFileNameWithoutExtension(projectFilePath)); var profiles = root.GetProperty("profiles"); return profiles.TryGetProperty(key, out projectSettings); } diff --git a/src/micronetes/m8s/Program.cs b/src/micronetes/m8s/Program.cs deleted file mode 100644 index 5b2c3d56..00000000 --- a/src/micronetes/m8s/Program.cs +++ /dev/null @@ -1,259 +0,0 @@ -using System; -using System.CommandLine; -using System.CommandLine.Builder; -using System.CommandLine.Invocation; -using System.CommandLine.IO; -using System.CommandLine.Parsing; -using System.CommandLine.Rendering; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using Micronetes.Hosting; -using Micronetes.Hosting.Model; -using YamlDotNet.Serialization; -using YamlDotNet.Serialization.NamingConventions; - -namespace Micronetes.Host -{ - class Program - { - static async Task Main(string[] args) - { - var command = new RootCommand(); - - command.Add(RunCommand(args)); - command.Add(NewCommand()); - - command.Description = "Process manager and orchestrator for microservices."; - - var builder = new CommandLineBuilder(command); - builder.UseHelp(); - builder.UseVersionOption(); - builder.UseDebugDirective(); - builder.UseParseErrorReporting(); - builder.ParseResponseFileAs(ResponseFileHandling.ParseArgsAsSpaceSeparated); - builder.UsePrefixes(new[] { "-", "--", }); // disable garbage windows conventions - - builder.CancelOnProcessTermination(); - builder.UseExceptionHandler(HandleException); - - // Allow fancy drawing. - builder.UseAnsiTerminalWhenAvailable(); - - var parser = builder.Build(); - return await parser.InvokeAsync(args); - } - - private static Command NewCommand() - { - var command = new Command("new", "create a yaml manifest") - { - }; - - var argument = new Argument("path") - { - Description = "A solution or project file to generate a yaml manifest from", - Arity = ArgumentArity.ZeroOrOne - }; - - command.AddArgument(argument); - - command.Handler = CommandHandler.Create((console, path) => - { - if (File.Exists("m8s.yaml")) - { - console.Out.WriteLine("\"m8s.yaml\" already exists."); - return; - } - - var template = @"- name: app - # project: app.csproj # msbuild project path (relative to this file) - # executable: app.exe # path to an executable (relative to this file) - # args: --arg1=3 # arguments to pass to the process - # replicas: 5 # number of times to launch the application - # env: # array of environment variables - # - name: key - # value: value - # bindings: # optional array of bindings (ports, connection strings) - # - port: 8080 # number port of the binding -"; - - try - { - if (!string.IsNullOrEmpty(path)) - { - var application = ResolveApplication(path); - var serializer = new SerializerBuilder() - .WithNamingConvention(CamelCaseNamingConvention.Instance) - .ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitDefaults) - .Build(); - - var extension = Path.GetExtension(application.Source).ToLowerInvariant(); - var directory = Path.GetDirectoryName(application.Source); - var descriptions = application.Services.Select(s => s.Value.Description).ToList(); - - // Clear all bindings if any for solutions and project files - if (extension == ".sln" || extension == ".csproj" || extension == ".fsproj") - { - foreach (var d in descriptions) - { - d.Bindings = null; - d.Replicas = null; - d.Build = null; - d.Configuration = null; - d.Project = d.Project.Substring(directory.Length).TrimStart(Path.DirectorySeparatorChar); - } - } - - template = serializer.Serialize(descriptions); - } - } - catch (FileNotFoundException) - { - // No file found, just generate a new one - } - - File.WriteAllText("m8s.yaml", template); - console.Out.WriteLine("Created \"m8s.yaml\""); - }); - - return command; - } - - private static Command RunCommand(string[] args) - { - var command = new Command("run", "run the application") - { - }; - - var argument = new Argument("path") - { - Description = "A file or directory to execute. Supports a project files, solution files or a yaml manifest.", - Arity = ArgumentArity.ZeroOrOne - }; - - // TODO: We'll need to support a --build-args - command.AddOption(new Option("--no-build") - { - Description = "Do not build project files before running.", - Required = false - }); - - command.AddOption(new Option("--port") - { - Description = "The port to run control plane on.", - Argument = new Argument("port"), - Required = false - }); - - command.AddOption(new Option("--logs") - { - Description = "Write structured application logs to the specified log providers. Supported providers are console, elastic (Elasticsearch), ai (ApplicationInsights), seq.", - Argument = new Argument("logs"), - Required = false - }); - - command.AddOption(new Option("--dtrace") - { - Description = "Write distributed traces to the specified providers. Supported providers are zipkin.", - Argument = new Argument("logs"), - Required = false - }); - - command.AddOption(new Option("--debug") - { - Description = "Wait for debugger attach in all services.", - Required = false - }); - - command.AddArgument(argument); - - command.Handler = CommandHandler.Create((console, path) => - { - Application app = ResolveApplication(path); - return MicronetesHost.RunAsync(app, args); - }); - - return command; - } - - private static Application ResolveApplication(string path) - { - if (string.IsNullOrEmpty(path)) - { - path = ResolveFileFromDirectory(Directory.GetCurrentDirectory()); - } - else if (Directory.Exists(path)) - { - path = ResolveFileFromDirectory(Path.GetFullPath(path)); - } - - if (!File.Exists(path)) - { - throw new FileNotFoundException($"{path} does not exist"); - } - - switch (Path.GetExtension(path).ToLower()) - { - case ".yaml": - case ".yml": - return Application.FromYaml(path); - case ".csproj": - case ".fsproj": - return Application.FromProject(path); - case ".sln": - return Application.FromSolution(path); - default: - throw new NotSupportedException($"{path} not supported"); - } - } - - private static string ResolveFileFromDirectory(string basePath) - { - var formats = new[] { "m8s.yaml", "m8s.yml", "*.csproj", "*.fsproj", "*.sln" }; - - foreach (var format in formats) - { - var files = Directory.GetFiles(basePath, format); - if (files.Length == 0) - { - continue; - } - - if (files.Length > 1) - { - throw new InvalidOperationException($"Ambiguous match found {string.Join(", ", files.Select(Path.GetFileName))}"); - } - - return files[0]; - } - - throw new InvalidOperationException($"None of the supported files were found (m8s.yaml, .csproj, .fsproj, .sln)"); - } - - private static void HandleException(Exception exception, InvocationContext context) - { - // context.Console.ResetTerminalForegroundColor(); - // context.Console.SetTerminalForegroundColor(ConsoleColor.Red); - - if (exception is OperationCanceledException) - { - context.Console.Error.WriteLine("operation canceled."); - } - else if (exception is TargetInvocationException tae) - { - context.Console.Error.WriteLine(tae.InnerException.Message); - } - else - { - context.Console.Error.WriteLine("unhandled exception: "); - context.Console.Error.WriteLine(exception.ToString()); - } - - // context.Console.ResetTerminalForegroundColor(); - - context.ResultCode = 1; - } - } -} diff --git a/src/micronetes/m8s/Properties/launchSettings.json b/src/micronetes/m8s/Properties/launchSettings.json deleted file mode 100644 index 479a4581..00000000 --- a/src/micronetes/m8s/Properties/launchSettings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "profiles": { - "dotnet-micronetes": { - "commandName": "Project" - } - } -} \ No newline at end of file diff --git a/src/micronetes/m8s/m8s.csproj b/src/micronetes/m8s/m8s.csproj deleted file mode 100644 index 74f739a6..00000000 --- a/src/micronetes/m8s/m8s.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - Exe - netcoreapp3.1 - true - Micronetes.Host - m8s - m8s - Local orchestrator for microservices. - disable - - - - - - - - - diff --git a/src/tye/NameSanitizer.cs b/src/tye/NameSanitizer.cs new file mode 100644 index 00000000..68fc52cc --- /dev/null +++ b/src/tye/NameSanitizer.cs @@ -0,0 +1,23 @@ +using System; + +namespace Tye +{ + internal static class NameSanitizer + { + // Converts an arbitrary string into something usable as a C# identifier. + // + // For instance the project file might be `test-project.csproj` but `test-project` is + // not what will appear in `launchSettings.json`. We need to convert to + // `test_project` + public static string SanitizeToIdentifier(string name) + { + if (name is null) + { + throw new ArgumentNullException(nameof(name)); + } + + // This is not perfect. For now it just handles cases we've encountered. + return name.Replace("-", "_"); + } + } +} diff --git a/src/tye/Program.InitCommand.cs b/src/tye/Program.InitCommand.cs new file mode 100644 index 00000000..7ca586f0 --- /dev/null +++ b/src/tye/Program.InitCommand.cs @@ -0,0 +1,153 @@ +using System; +using System.CommandLine; +using System.CommandLine.Invocation; +using System.CommandLine.IO; +using System.IO; +using System.Linq; +using Micronetes.Hosting.Model; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; + +namespace Tye +{ + static partial class Program + { + private static Command CreateInitCommand() + { + var command = new Command("init", "create a yaml manifest") + { + }; + + var argument = new Argument("path") + { + Description = "A solution or project file to generate a yaml manifest from", + Arity = ArgumentArity.ZeroOrOne + }; + + command.AddArgument(argument); + + command.Handler = CommandHandler.Create((console, path) => + { + if (File.Exists("tye.yaml")) + { + console.Out.WriteLine("\"tye.yaml\" already exists."); + return; + } + + var template = @"- name: app + # project: app.csproj # msbuild project path (relative to this file) + # executable: app.exe # path to an executable (relative to this file) + # args: --arg1=3 # arguments to pass to the process + # replicas: 5 # number of times to launch the application + # env: # array of environment variables + # - name: key + # value: value + # bindings: # optional array of bindings (ports, connection strings) + # - port: 8080 # number port of the binding +"; + + try + { + var application = ResolveApplication(path); + if (application is object) + { + var serializer = new SerializerBuilder() + .WithNamingConvention(CamelCaseNamingConvention.Instance) + .ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitDefaults) + .Build(); + + var extension = Path.GetExtension(application.Source).ToLowerInvariant(); + var directory = Path.GetDirectoryName(application.Source); + var descriptions = application.Services.Select(s => s.Value.Description).ToList(); + + // Clear all bindings if any for solutions and project files + if (extension == ".sln" || extension == ".csproj" || extension == ".fsproj") + { + foreach (var d in descriptions) + { + d.Bindings = null; + d.Replicas = null; + d.Build = null; + d.Configuration = null; + d.Project = d.Project.Substring(directory.Length).TrimStart(Path.DirectorySeparatorChar); + } + } + + template = serializer.Serialize(descriptions); + } + } + catch (FileNotFoundException) + { + // No file found, just generate a new one + } + + File.WriteAllText("tye.yaml", template); + console.Out.WriteLine("Created \"tye.yaml\""); + }); + + return command; + } + + private static Application? ResolveApplication(string? path) + { + if (string.IsNullOrEmpty(path)) + { + path = ResolveFileFromDirectory(Directory.GetCurrentDirectory()); + } + else if (Directory.Exists(path)) + { + path = ResolveFileFromDirectory(Path.GetFullPath(path)); + } + + if (path == null) + { + return null; + } + + if (!File.Exists(path)) + { + throw new FileNotFoundException($"{path} does not exist"); + } + + switch (Path.GetExtension(path).ToLower()) + { + case ".yaml": + case ".yml": + return Application.FromYaml(path); + + case ".csproj": + case ".fsproj": + return Application.FromProject(path); + + case ".sln": + return Application.FromSolution(path); + + default: + throw new NotSupportedException($"{path} not supported"); + } + } + + private static string? ResolveFileFromDirectory(string basePath) + { + var formats = new[] { "tye.yaml", "tye.yml", "*.csproj", "*.fsproj", "*.sln" }; + + foreach (var format in formats) + { + var files = Directory.GetFiles(basePath, format); + if (files.Length == 0) + { + continue; + } + + if (files.Length > 1) + { + throw new InvalidOperationException($"Ambiguous match found {string.Join(", ", files.Select(Path.GetFileName))}"); + } + + return files[0]; + } + + return null; + } + } +} diff --git a/src/tye/Program.RunCommand.cs b/src/tye/Program.RunCommand.cs new file mode 100644 index 00000000..b1ddd224 --- /dev/null +++ b/src/tye/Program.RunCommand.cs @@ -0,0 +1,72 @@ +using System; +using System.CommandLine; +using System.CommandLine.Invocation; +using Micronetes.Hosting; + +namespace Tye +{ + static partial class Program + { + private static Command CreateRunCommand(string[] args) + { + var command = new Command("run", "run the application") + { + }; + + var argument = new Argument("path") + { + Description = "A file or directory to execute. Supports a project files, solution files or a yaml manifest.", + Arity = ArgumentArity.ZeroOrOne + }; + + // TODO: We'll need to support a --build-args + command.AddOption(new Option("--no-build") + { + Description = "Do not build project files before running.", + Required = false + }); + + command.AddOption(new Option("--port") + { + Description = "The port to run control plane on.", + Argument = new Argument("port"), + Required = false + }); + + command.AddOption(new Option("--logs") + { + Description = "Write structured application logs to the specified log providers. Supported providers are console, elastic (Elasticsearch), ai (ApplicationInsights), seq.", + Argument = new Argument("logs"), + Required = false + }); + + command.AddOption(new Option("--dtrace") + { + Description = "Write distributed traces to the specified providers. Supported providers are zipkin.", + Argument = new Argument("logs"), + Required = false + }); + + command.AddOption(new Option("--debug") + { + Description = "Wait for debugger attach in all services.", + Required = false + }); + + command.AddArgument(argument); + + command.Handler = CommandHandler.Create((console, path) => + { + var application = ResolveApplication(path); + if (application is null) + { + throw new CommandException($"None of the supported files were found (tye.yaml, .csproj, .fsproj, .sln)"); + } + + return MicronetesHost.RunAsync(application, args); + }); + + return command; + } + } +} diff --git a/src/tye/Program.cs b/src/tye/Program.cs index 4bc473d9..35bfb53a 100644 --- a/src/tye/Program.cs +++ b/src/tye/Program.cs @@ -18,6 +18,9 @@ namespace Tye Description = "Developer tools and publishing for microservices.", }; + command.AddCommand(CreateInitCommand()); + command.AddCommand(CreateRunCommand(args)); + // Show commandline help unless a subcommand was used. command.Handler = CommandHandler.Create(help => { diff --git a/src/tye/tye.csproj b/src/tye/tye.csproj index 0182643a..e81b620b 100644 --- a/src/tye/tye.csproj +++ b/src/tye/tye.csproj @@ -9,8 +9,13 @@ true + + + + + diff --git a/tye.sln b/tye.sln index cab1d92a..59863630 100644 --- a/tye.sln +++ b/tye.sln @@ -25,8 +25,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Micronetes.Hosting.Diagnost EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Micronetes.Hosting.Runtime", "src\micronetes\Micronetes.Hosting.Runtime\Micronetes.Hosting.Runtime.csproj", "{34719884-1338-4965-BA2A-F98DB03733C2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "m8s", "src\micronetes\m8s\m8s.csproj", "{01C77687-2E5E-4DB3-B88C-218FC706DC7D}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -124,18 +122,6 @@ Global {34719884-1338-4965-BA2A-F98DB03733C2}.Release|x64.Build.0 = Release|Any CPU {34719884-1338-4965-BA2A-F98DB03733C2}.Release|x86.ActiveCfg = Release|Any CPU {34719884-1338-4965-BA2A-F98DB03733C2}.Release|x86.Build.0 = Release|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|x64.ActiveCfg = Debug|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|x64.Build.0 = Debug|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|x86.ActiveCfg = Debug|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|x86.Build.0 = Debug|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|Any CPU.Build.0 = Release|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|x64.ActiveCfg = Release|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|x64.Build.0 = Release|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|x86.ActiveCfg = Release|Any CPU - {01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {9BFE4070-D6D8-41F8-B92E-F85C3DCD7AB8} = {8C662D59-A3CB-466F-8E85-A8E6BA5E7601} @@ -147,6 +133,5 @@ Global {0F4F5A86-DD27-4AF9-BF97-221EAD5040E7} = {B2C364E4-969E-4770-BF5F-BE65D292F70A} {CEBFC149-8162-4A0A-9AD4-40498B9172CD} = {B2C364E4-969E-4770-BF5F-BE65D292F70A} {34719884-1338-4965-BA2A-F98DB03733C2} = {B2C364E4-969E-4770-BF5F-BE65D292F70A} - {01C77687-2E5E-4DB3-B88C-218FC706DC7D} = {B2C364E4-969E-4770-BF5F-BE65D292F70A} EndGlobalSection EndGlobal