Skip to content

Commit

Permalink
test: log rethrown exceptions when diagnostics is enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
Ganesh Jangir authored and ganeshnj committed Sep 28, 2021
1 parent 58ce9d6 commit d9fa514
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 44 deletions.
61 changes: 33 additions & 28 deletions src/AWS.Deploy.CLI/AWSUtilities.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;
using Amazon.EC2.Model;
using System.IO;
using AWS.Deploy.CLI.Commands.CommandHandlerInput;
using AWS.Deploy.CLI.Utilities;
using AWS.Deploy.Common;
using AWS.Deploy.Common.IO;

namespace AWS.Deploy.CLI
Expand All @@ -25,7 +28,10 @@ public class AWSUtilities : IAWSUtilities
private readonly IConsoleUtilities _consoleUtilities;
private readonly IDirectoryManager _directoryManager;

public AWSUtilities(IToolInteractiveService toolInteractiveService, IConsoleUtilities consoleUtilities, IDirectoryManager directoryManager)
public AWSUtilities(
IToolInteractiveService toolInteractiveService,
IConsoleUtilities consoleUtilities,
IDirectoryManager directoryManager)
{
_toolInteractiveService = toolInteractiveService;
_consoleUtilities = consoleUtilities;
Expand All @@ -36,51 +42,52 @@ public async Task<AWSCredentials> ResolveAWSCredentials(string? profileName, str
{
async Task<AWSCredentials> Resolve()
{
var chain = new CredentialProfileStoreChain();
var chain = new CredentialProfileStoreChain();

if (!string.IsNullOrEmpty(profileName) && chain.TryGetAWSCredentials(profileName, out var profileCredentials) &&
// Skip checking CanLoadCredentials for AssumeRoleAWSCredentials because it might require an MFA token and the callback hasn't been setup yet.
(profileCredentials is AssumeRoleAWSCredentials || await CanLoadCredentials(profileCredentials)))
{
{
_toolInteractiveService.WriteLine($"Configuring AWS Credentials from Profile {profileName}.");
return profileCredentials;
}

if (!string.IsNullOrEmpty(lastUsedProfileName) &&
if (!string.IsNullOrEmpty(lastUsedProfileName) &&
chain.TryGetAWSCredentials(lastUsedProfileName, out var lastUsedCredentials) &&
await CanLoadCredentials(lastUsedCredentials))
{
_toolInteractiveService.WriteLine($"Configuring AWS Credentials with previous configured profile value {lastUsedProfileName}.");
{
_toolInteractiveService.WriteLine($"Configuring AWS Credentials with previous configured profile value {lastUsedProfileName}.");
return lastUsedCredentials;
}
}

try
{
try
{
var fallbackCredentials = FallbackCredentialsFactory.GetCredentials();

if (await CanLoadCredentials(fallbackCredentials))
{
_toolInteractiveService.WriteLine("Configuring AWS Credentials using AWS SDK credential search.");
{
_toolInteractiveService.WriteLine("Configuring AWS Credentials using AWS SDK credential search.");
return fallbackCredentials;
}
}
catch (AmazonServiceException ex)
{
// FallbackCredentialsFactory throws an exception if no credentials are found. Burying exception because if no credentials are found
// we want to continue and ask the user to select a profile.
_toolInteractiveService.WriteDebugLine(ex.PrettyPrint());
}
}
catch (AmazonServiceException)
{
// FallbackCredentialsFactory throws an exception if no credentials are found. Burying exception because if no credentials are found
// we want to continue and ask the user to select a profile.
}

var sharedCredentials = new SharedCredentialsFile();
if (sharedCredentials.ListProfileNames().Count == 0)
{
throw new NoAWSCredentialsFoundException("Unable to resolve AWS credentials to access AWS.");
}
var sharedCredentials = new SharedCredentialsFile();
if (sharedCredentials.ListProfileNames().Count == 0)
{
throw new NoAWSCredentialsFoundException("Unable to resolve AWS credentials to access AWS.");
}

var selectedProfileName = _consoleUtilities.AskUserToChoose(sharedCredentials.ListProfileNames(), "Select AWS Credentials Profile", null);
var selectedProfileName = _consoleUtilities.AskUserToChoose(sharedCredentials.ListProfileNames(), "Select AWS Credentials Profile", null);

if (chain.TryGetAWSCredentials(selectedProfileName, out var selectedProfileCredentials) &&
(await CanLoadCredentials(selectedProfileCredentials)))
{
{
return selectedProfileCredentials;
}

Expand All @@ -100,16 +107,14 @@ await CanLoadCredentials(lastUsedCredentials))

private async Task<bool> CanLoadCredentials(AWSCredentials credentials)
{
if (null == credentials)
return false;

try
{
await credentials.GetCredentialsAsync();
return true;
}
catch
catch (Exception ex)
{
_toolInteractiveService.WriteDebugLine(ex.PrettyPrint());
return false;
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/AWS.Deploy.CLI/CloudFormation/StackEventMonitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ internal class StackEventMonitor
private readonly IAmazonCloudFormation _cloudFormationClient;
private readonly HashSet<string> _processedEventIds = new HashSet<string>();
private readonly IConsoleUtilities _consoleUtilities;
private readonly IToolInteractiveService _interactiveService;

public StackEventMonitor(string stackName, IAWSClientFactory awsClientFactory, IConsoleUtilities consoleUtilities)
public StackEventMonitor(string stackName, IAWSClientFactory awsClientFactory, IConsoleUtilities consoleUtilities, IToolInteractiveService interactiveService)
{
_stackName = stackName;
_consoleUtilities = consoleUtilities;
_interactiveService = interactiveService;

_cloudFormationClient = awsClientFactory.GetAWSClient<IAmazonCloudFormation>();
}
Expand Down Expand Up @@ -112,10 +114,12 @@ private async Task ReadNewEventsAsync()
catch (AmazonCloudFormationException exception) when (exception.ErrorCode.Equals("ValidationError") && exception.Message.Equals($"Stack [{_stackName}] does not exist"))
{
// Stack is deleted, there could be some missed events between the last poll timestamp and DELETE_COMPLETE
_interactiveService.WriteDebugLine(exception.PrettyPrint());
}
catch (AmazonCloudFormationException)
catch (AmazonCloudFormationException exception)
{
// Other AmazonCloudFormationException
_interactiveService.WriteDebugLine(exception.PrettyPrint());
}

foreach (var stackEvent in stackEvents.OrderBy(e => e.Timestamp))
Expand Down
3 changes: 2 additions & 1 deletion src/AWS.Deploy.CLI/Commands/DeleteDeploymentCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public async Task ExecuteAsync(string stackName)
}

_interactiveService.WriteLine($"{stackName}: deleting...");
var monitor = new StackEventMonitor(stackName, _awsClientFactory, _consoleUtilities);
var monitor = new StackEventMonitor(stackName, _awsClientFactory, _consoleUtilities, _interactiveService);

try
{
Expand Down Expand Up @@ -171,6 +171,7 @@ private async Task WaitForStackDelete(string stackName)
}
catch (AmazonCloudFormationException exception) when (exception.ErrorCode.Equals("ValidationError") && exception.Message.Equals($"Stack with id {stackName} does not exist"))
{
_interactiveService.WriteDebugLine(exception.PrettyPrint());
shouldRetry = false;
}
catch (AmazonCloudFormationException exception) when (exception.ErrorCode.Equals("Throttling"))
Expand Down
10 changes: 7 additions & 3 deletions src/AWS.Deploy.CLI/Commands/DeployCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private void DisplayOutputResources(List<DisplayedResourceItem> displayedResourc

// Get Cloudformation stack name.
var cloudApplicationName = GetCloudApplicationName(stackName, userDeploymentSettings, compatibleApplications);

// Find existing application with the same CloudFormation stack name.
var deployedApplication = allDeployedApplications.FirstOrDefault(x => string.Equals(x.Name, cloudApplicationName));

Expand Down Expand Up @@ -354,8 +354,9 @@ private void ConfigureDeploymentFromConfigFile(Recommendation recommendation, Us
throw new InvalidOverrideValueException($"Invalid value {optionSettingValue} for option setting item {optionSettingJsonPath}");
}
}
catch (Exception)
catch (Exception exception)
{
_toolInteractiveService.WriteDebugLine(exception.PrettyPrint());
throw new InvalidOverrideValueException($"Invalid value {optionSettingValue} for option setting item {optionSettingJsonPath}");
}

Expand Down Expand Up @@ -483,7 +484,10 @@ private string AskUserForCloudApplicationName(ProjectDefinition project, List<Cl
{
defaultName = _cloudApplicationNameGenerator.GenerateValidName(project, existingApplications);
}
catch { }
catch (Exception exception)
{
_toolInteractiveService.WriteDebugLine(exception.PrettyPrint());
}

var cloudApplicationName = "";

Expand Down
4 changes: 3 additions & 1 deletion src/AWS.Deploy.CLI/Commands/ServerModeCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Threading.Tasks;
using AWS.Deploy.CLI.ServerMode;
using AWS.Deploy.CLI.ServerMode.Services;
using AWS.Deploy.Common;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;

Expand Down Expand Up @@ -65,8 +66,9 @@ public ServerModeCommand(IToolInteractiveService interactiveService, int port, i
process.EnableRaisingEvents = true;
process.Exited += async (sender, args) => { await ShutDownHost(host, cancellationToken); };
}
catch (Exception)
catch (Exception exception)
{
_interactiveService.WriteDebugLine(exception.PrettyPrint());
return;
}

Expand Down
8 changes: 5 additions & 3 deletions src/AWS.Deploy.Orchestration/CdkProjectHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public interface ICdkProjectHandler
Task<string> ConfigureCdkProject(OrchestratorSession session, CloudApplication cloudApplication, Recommendation recommendation);
string CreateCdkProject(Recommendation recommendation, OrchestratorSession session, string? saveDirectoryPath = null);
Task DeployCdkProject(OrchestratorSession session, string cdkProjectPath, Recommendation recommendation);
void DeleteTemporaryCdkProject(string cdkProjectPath);
void DeleteTemporaryCdkProject(OrchestratorSession session, string cdkProjectPath);
}

public class CdkProjectHandler : ICdkProjectHandler
Expand Down Expand Up @@ -83,6 +83,7 @@ await _commandLineWrapper.Run($"npx cdk bootstrap aws://{session.AWSAccountId}/{
workingDirectory: cdkProjectPath,
environmentVariables: environmentVariables,
needAwsCredentials: true,
redirectIO: true,
streamOutputToInteractiveService: true);

if (cdkDeploy.ExitCode != 0)
Expand Down Expand Up @@ -118,7 +119,7 @@ public string CreateCdkProject(Recommendation recommendation, OrchestratorSessio
return saveCdkDirectoryPath;
}

public void DeleteTemporaryCdkProject(string cdkProjectPath)
public void DeleteTemporaryCdkProject(OrchestratorSession session, string cdkProjectPath)
{
var parentPath = Path.GetFullPath(Constants.CDK.ProjectsDirectory);
cdkProjectPath = Path.GetFullPath(cdkProjectPath);
Expand All @@ -130,8 +131,9 @@ public void DeleteTemporaryCdkProject(string cdkProjectPath)
{
_directoryManager.Delete(cdkProjectPath, true);
}
catch (Exception)
catch (Exception exception)
{
_interactiveService.LogDebugLine(exception.PrettyPrint());
_interactiveService.LogErrorMessageLine($"We were unable to delete the temporary project that was created for this deployment. Please manually delete it at this location: {cdkProjectPath}");
}
}
Expand Down
10 changes: 6 additions & 4 deletions src/AWS.Deploy.Orchestration/Orchestrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public async Task DeployRecommendation(CloudApplication cloudApplication, Recomm
}
finally
{
_cdkProjectHandler.DeleteTemporaryCdkProject(cdkProject);
_cdkProjectHandler.DeleteTemporaryCdkProject(_session, cdkProject);
}
break;
default:
Expand Down Expand Up @@ -235,16 +235,18 @@ public async Task<bool> CreateDotnetPublishDeploymentBundle(Recommendation recom
{
await _deploymentBundleHandler.CreateDotnetPublishZip(recommendation);
}
catch (DotnetPublishFailedException ex)
catch (DotnetPublishFailedException exception)
{
_interactiveService.LogErrorMessageLine("We were unable to package the application using 'dotnet publish' due to the following error:");
_interactiveService.LogErrorMessageLine(ex.Message);
_interactiveService.LogErrorMessageLine(exception.Message);
_interactiveService.LogDebugLine(exception.PrettyPrint());
return false;
}
catch (FailedToCreateZipFileException)
catch (FailedToCreateZipFileException exception)
{
_interactiveService.LogErrorMessageLine("We were unable to create a zip archive of the packaged application.");
_interactiveService.LogErrorMessageLine("Normally this indicates a problem running the \"zip\" utility. Make sure that application is installed and available in your PATH.");
_interactiveService.LogDebugLine(exception.PrettyPrint());
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,18 @@ public async Task<List<CloudApplication>> GetCompatibleApplications(List<Recomme
catch (FailedToUpdateLocalUserSettingsFileException ex)
{
_orchestratorInteractiveService.LogErrorMessageLine(ex.Message);
_orchestratorInteractiveService.LogDebugLine(ex.PrettyPrint());
}
catch (InvalidLocalUserSettingsFileException ex)
{
_orchestratorInteractiveService.LogErrorMessageLine(ex.Message);
_orchestratorInteractiveService.LogDebugLine(ex.PrettyPrint());
}
}

return compatibleApplications
.OrderByDescending(x => x.LastUpdatedTime)
.ToList(); ;
.ToList();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ private async Task<Orchestrator> GetOrchestrator(string targetApplicationProject
var fileManager = new FileManager();
var deploymentManifestEngine = new DeploymentManifestEngine(directoryManager, fileManager);
var localUserSettingsEngine = new LocalUserSettingsEngine(fileManager, directoryManager);
var consoleInteractiveServiceImpl = new ConsoleInteractiveServiceImpl();
var commandLineWrapper = new CommandLineWrapper(_inMemoryInteractiveService);
var customRecipeLocator = new CustomRecipeLocator(deploymentManifestEngine, _inMemoryInteractiveService, commandLineWrapper, directoryManager);

Expand Down

0 comments on commit d9fa514

Please sign in to comment.