|
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