|
1 | 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2 | 2 | // SPDX-License-Identifier: Apache-2.0
|
3 | 3 |
|
4 |
| -using System; |
5 |
| -using System.CommandLine; |
6 |
| -using System.Reflection; |
7 |
| -using System.Text; |
8 | 4 | using System.Threading.Tasks;
|
9 | 5 | using AWS.Deploy.CLI.Commands;
|
| 6 | +using AWS.Deploy.CLI.Utilities; |
| 7 | +using AWS.Deploy.Common; |
| 8 | +using Microsoft.Extensions.DependencyInjection; |
| 9 | +using Spectre.Console.Cli; |
10 | 10 |
|
11 |
| -namespace AWS.Deploy.CLI |
| 11 | +namespace AWS.Deploy.CLI; |
| 12 | + |
| 13 | +public class App |
12 | 14 | {
|
13 |
| - public class App |
| 15 | + public static CommandApp<RootCommand> ConfigureServices(TypeRegistrar registrar) |
14 | 16 | {
|
15 |
| - private readonly ICommandFactory _commandFactory; |
16 |
| - private readonly IToolInteractiveService _toolInteractiveService; |
17 |
| - |
18 |
| - public App(ICommandFactory commandFactory, IToolInteractiveService toolInteractiveService) |
19 |
| - { |
20 |
| - _commandFactory = commandFactory; |
21 |
| - _toolInteractiveService = toolInteractiveService; |
22 |
| - } |
| 17 | + var app = new CommandApp<RootCommand>(registrar); |
23 | 18 |
|
24 |
| - public async Task<int> Run(string[] args) |
| 19 | + app.Configure(config => |
25 | 20 | {
|
26 |
| - Console.OutputEncoding = Encoding.UTF8; |
27 |
| - |
28 |
| - SetExecutionEnvironment(args); |
29 |
| - |
30 |
| - _toolInteractiveService.WriteLine("AWS .NET deployment tool for deploying .NET Core applications to AWS."); |
31 |
| - _toolInteractiveService.WriteLine("Project Home: https://github.com/aws/aws-dotnet-deploy"); |
32 |
| - _toolInteractiveService.WriteLine(string.Empty); |
33 |
| - |
34 |
| - // if user didn't specify a command, default to help |
35 |
| - if (args.Length == 0) |
| 21 | + config.SetApplicationName(Constants.CLI.TOOL_NAME); |
| 22 | + config.AddCommand<DeployCommand>("deploy") |
| 23 | + .WithDescription("Inspect, build, and deploy the .NET project to AWS using the recommended AWS service."); |
| 24 | + config.AddCommand<ListDeploymentsCommand>("list-deployments") |
| 25 | + .WithDescription("List existing deployments."); |
| 26 | + config.AddCommand<DeleteDeploymentCommand>("delete-deployment") |
| 27 | + .WithDescription("Delete an existing deployment."); |
| 28 | + config.AddBranch("deployment-project", deploymentProject => |
36 | 29 | {
|
37 |
| - args = new[] { "-h" }; |
38 |
| - } |
39 |
| - |
40 |
| - return await _commandFactory.BuildRootCommand().InvokeAsync(args); |
41 |
| - } |
42 |
| - |
43 |
| - /// <summary> |
44 |
| - /// Set up the execution environment variable picked up by the AWS .NET SDK. This can be useful for identify calls |
45 |
| - /// made by this tool in AWS CloudTrail. |
46 |
| - /// </summary> |
47 |
| - private static void SetExecutionEnvironment(string[] args) |
48 |
| - { |
49 |
| - const string envName = "AWS_EXECUTION_ENV"; |
50 |
| - |
51 |
| - var toolVersion = GetToolVersion(); |
52 |
| - |
53 |
| - // The leading and trailing whitespaces are intentional |
54 |
| - var userAgent = $" lib/aws-dotnet-deploy-cli#{toolVersion} "; |
55 |
| - if (args?.Length > 0) |
| 30 | + deploymentProject.SetDescription("Save the deployment project inside a user provided directory path."); |
| 31 | + deploymentProject.AddCommand<GenerateDeploymentProjectCommand>("generate") |
| 32 | + .WithDescription("Save the deployment project inside a user provided directory path without proceeding with a deployment"); |
| 33 | + }); |
| 34 | + config.AddCommand<ServerModeCommand>("server-mode") |
| 35 | + .WithDescription("Launches the tool in a server mode for IDEs like Visual Studio to integrate with."); |
| 36 | + |
| 37 | + config.SetExceptionHandler((exception, _) => |
56 | 38 | {
|
57 |
| - // The trailing whitespace is intentional |
58 |
| - userAgent = $"{userAgent}md/cli-args#{args[0]} "; |
59 |
| - } |
60 |
| - |
61 |
| - |
62 |
| - var envValue = new StringBuilder(); |
63 |
| - var existingValue = Environment.GetEnvironmentVariable(envName); |
64 |
| - |
65 |
| - // If there is an existing execution environment variable add this tool as a suffix. |
66 |
| - if (!string.IsNullOrEmpty(existingValue)) |
67 |
| - { |
68 |
| - envValue.Append(existingValue); |
69 |
| - } |
| 39 | + var serviceProvider = registrar.GetServiceProvider();; |
| 40 | + var toolInteractiveService = serviceProvider.GetRequiredService<IToolInteractiveService>(); |
| 41 | + |
| 42 | + if (exception.IsAWSDeploymentExpectedException()) |
| 43 | + { |
| 44 | + if (toolInteractiveService.Diagnostics) |
| 45 | + toolInteractiveService.WriteErrorLine(exception.PrettyPrint()); |
| 46 | + else |
| 47 | + { |
| 48 | + toolInteractiveService.WriteErrorLine(string.Empty); |
| 49 | + toolInteractiveService.WriteErrorLine(exception.Message); |
| 50 | + } |
| 51 | + |
| 52 | + toolInteractiveService.WriteErrorLine(string.Empty); |
| 53 | + toolInteractiveService.WriteErrorLine("For more information, please visit our troubleshooting guide https://aws.github.io/aws-dotnet-deploy/troubleshooting-guide/."); |
| 54 | + toolInteractiveService.WriteErrorLine("If you are still unable to solve this issue and believe this is an issue with the tooling, please cut a ticket https://github.com/aws/aws-dotnet-deploy/issues/new/choose."); |
| 55 | + |
| 56 | + if (exception is TcpPortInUseException) |
| 57 | + { |
| 58 | + return CommandReturnCodes.TCP_PORT_ERROR; |
| 59 | + } |
| 60 | + |
| 61 | + // bail out with an non-zero return code. |
| 62 | + return CommandReturnCodes.USER_ERROR; |
| 63 | + } |
| 64 | + else |
| 65 | + { |
| 66 | + // This is a bug |
| 67 | + toolInteractiveService.WriteErrorLine( |
| 68 | + "Unhandled exception. This is a bug. Please copy the stack trace below and file a bug at https://github.com/aws/aws-dotnet-deploy. " + |
| 69 | + exception.PrettyPrint()); |
| 70 | + |
| 71 | + return CommandReturnCodes.UNHANDLED_EXCEPTION; |
| 72 | + } |
| 73 | + }); |
| 74 | + }); |
| 75 | + |
| 76 | + return app; |
| 77 | + } |
70 | 78 |
|
71 |
| - envValue.Append(userAgent); |
| 79 | + public static async Task<int> RunAsync(string[] args, CommandApp<RootCommand> app, TypeRegistrar registrar) |
| 80 | + { |
| 81 | + var serviceProvider = registrar.GetServiceProvider();; |
| 82 | + var toolInteractiveService = serviceProvider.GetRequiredService<IToolInteractiveService>(); |
72 | 83 |
|
73 |
| - Environment.SetEnvironmentVariable(envName, envValue.ToString()); |
74 |
| - } |
| 84 | + toolInteractiveService.WriteLine("AWS .NET deployment tool for deploying .NET Core applications to AWS."); |
| 85 | + toolInteractiveService.WriteLine("Project Home: https://github.com/aws/aws-dotnet-deploy"); |
| 86 | + toolInteractiveService.WriteLine(string.Empty); |
75 | 87 |
|
76 |
| - internal static string GetToolVersion() |
| 88 | + // if user didn't specify a command, default to help |
| 89 | + if (args.Length == 0) |
77 | 90 | {
|
78 |
| - var assembly = typeof(App).GetTypeInfo().Assembly; |
79 |
| - var version = assembly.GetCustomAttribute<AssemblyFileVersionAttribute>()?.Version; |
80 |
| - if (version is null) |
81 |
| - { |
82 |
| - return string.Empty; |
83 |
| - } |
84 |
| - |
85 |
| - var versionParts = version.Split('.'); |
86 |
| - if (versionParts.Length == 4) |
87 |
| - { |
88 |
| - // The revision part of the version number is intentionally set to 0 since package versioning on |
89 |
| - // NuGet follows semantic versioning consisting only of Major.Minor.Patch versions. |
90 |
| - versionParts[3] = "0"; |
91 |
| - } |
92 |
| - |
93 |
| - return string.Join(".", versionParts); |
| 91 | + args = ["-h"]; |
94 | 92 | }
|
| 93 | + |
| 94 | + return await app.RunAsync(args); |
95 | 95 | }
|
96 | 96 | }
|
0 commit comments