Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .autover/changes/d5f415cd-080b-41e1-8256-8743f7a423d3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"Projects": [
{
"Name": "AWS.Deploy.CLI",
"Type": "Patch",
"ChangelogMessages": [
"Fixed intermittent IAM permission failures in delete-deployment command by ensuring CloudFormation client is created after AWS credentials are configured"
]
}
]
}
22 changes: 5 additions & 17 deletions src/AWS.Deploy.CLI/Commands/DeleteDeploymentCommand.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Amazon;
using Amazon.CloudFormation;
using Amazon.CloudFormation.Model;
Expand All @@ -28,7 +24,6 @@

private readonly IAWSClientFactory _awsClientFactory;
private readonly IToolInteractiveService _interactiveService;
private readonly IAmazonCloudFormation _cloudFormationClient;
private readonly IConsoleUtilities _consoleUtilities;
private readonly ILocalUserSettingsEngine _localUserSettingsEngine;
private readonly IAWSUtilities _awsUtilities;
Expand All @@ -51,7 +46,6 @@
_awsClientFactory = awsClientFactory;
_interactiveService = interactiveService;
_consoleUtilities = consoleUtilities;
_cloudFormationClient = _awsClientFactory.GetAWSClient<IAmazonCloudFormation>();
_localUserSettingsEngine = localUserSettingsEngine;
_awsUtilities = awsUtilities;
_projectParserUtility = projectParserUtility;
Expand Down Expand Up @@ -123,10 +117,7 @@

try
{
await _cloudFormationClient.DeleteStackAsync(new DeleteStackRequest
{
StackName = settings.DeploymentName
});
await _awsResourceQueryer.DeleteStack(settings.DeploymentName);

// Fire and forget the monitor
// Monitor updates the stdout with current status of the CloudFormation stack
Expand Down Expand Up @@ -218,20 +209,17 @@
{
await Task.Delay(waitTime);

var response = await _cloudFormationClient.DescribeStacksAsync(new DescribeStacksRequest
{
StackName = stackName
});
var response = await _awsResourceQueryer.DescribeStacks(stackName);

stack = response.Stacks == null || response.Stacks.Count == 0 ? null : response.Stacks[0];
stack = response.Count == 0 ? null : response[0];
shouldRetry = false;
}
catch (AmazonCloudFormationException exception) when (exception.ErrorCode.Equals("ValidationError") && exception.Message.Equals($"Stack with id {stackName} does not exist"))
catch (ResourceQueryException exception) when (exception.InnerException is AmazonCloudFormationException amazonCloudFormationException && amazonCloudFormationException.ErrorCode.Equals("ValidationError") && amazonCloudFormationException.Message.Equals($"Stack with id {stackName} does not exist"))
{
_interactiveService.WriteDebugLine(exception.PrettyPrint());
shouldRetry = false;
}
catch (AmazonCloudFormationException exception) when (exception.ErrorCode.Equals("Throttling"))
catch (ResourceQueryException exception) when (exception.InnerException is AmazonCloudFormationException amazonCloudFormationException && amazonCloudFormationException.ErrorCode.Equals("Throttling"))

Check warning on line 222 in src/AWS.Deploy.CLI/Commands/DeleteDeploymentCommand.cs

View check run for this annotation

Codecov / codecov/patch

src/AWS.Deploy.CLI/Commands/DeleteDeploymentCommand.cs#L222

Added line #L222 was not covered by tests
{
_interactiveService.WriteDebugLine(exception.PrettyPrint());
shouldRetry = true;
Expand Down
10 changes: 10 additions & 0 deletions src/AWS.Deploy.CLI/ServerMode/Services/SessionAWSResourceQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,16 @@
return (await GetAndCache(async () => await _awsResourceQueryer.GetCloudFrontDistribution(distributionId), new object[] { distributionId }))!;
}

public async Task<List<Stack>> DescribeStacks(string stackName)
{
return (await GetAndCache(async () => await _awsResourceQueryer.DescribeStacks(stackName), new object[] { stackName }))!;
}

Check warning on line 249 in src/AWS.Deploy.CLI/ServerMode/Services/SessionAWSResourceQuery.cs

View check run for this annotation

Codecov / codecov/patch

src/AWS.Deploy.CLI/ServerMode/Services/SessionAWSResourceQuery.cs#L248-L249

Added lines #L248 - L249 were not covered by tests

public async Task<DeleteStackResponse> DeleteStack(string stackName)
{
return (await GetAndCache(async () => await _awsResourceQueryer.DeleteStack(stackName), new object[] { stackName }))!;
}

Check warning on line 254 in src/AWS.Deploy.CLI/ServerMode/Services/SessionAWSResourceQuery.cs

View check run for this annotation

Codecov / codecov/patch

src/AWS.Deploy.CLI/ServerMode/Services/SessionAWSResourceQuery.cs#L253-L254

Added lines #L253 - L254 were not covered by tests

/// <inheritdoc/>
public async Task<Vpc?> GetDefaultVpc()
{
Expand Down
2 changes: 2 additions & 0 deletions src/AWS.Deploy.Common/Data/IAWSResourceQueryer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public enum BeanstalkPlatformType { Linux, Windows }
/// </remarks>
public interface IAWSResourceQueryer
{
Task<List<Stack>> DescribeStacks(string stackName);
Task<DeleteStackResponse> DeleteStack(string stackName);
Task<Vpc?> GetDefaultVpc();
Task<ResourceDescription> GetCloudControlApiResource(string type, string identifier);
Task<List<StackEvent>> GetCloudFormationStackEvents(string stackName);
Expand Down
28 changes: 28 additions & 0 deletions src/AWS.Deploy.Orchestration/Data/AWSResourceQueryer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,34 @@ namespace AWS.Deploy.Orchestration.Data
{
public class AWSResourceQueryer(IAWSClientFactory awsClientFactory) : IAWSResourceQueryer
{
public async Task<List<Stack>> DescribeStacks(string stackName)
{
var cfClient = awsClientFactory.GetAWSClient<IAmazonCloudFormation>();
var request = new DescribeStacksRequest
{
StackName = stackName
};

return await HandleException(async () => await cfClient.Paginators
.DescribeStacks(request)
.Stacks
.ToListAsync(),
$"Error attempting to describe available CloudFormation stacks using stack name '{stackName}'");
}

public async Task<DeleteStackResponse> DeleteStack(string stackName)
{
var cfClient = awsClientFactory.GetAWSClient<IAmazonCloudFormation>();
var request = new DeleteStackRequest
{
StackName = stackName
};

return await HandleException(async () => await cfClient
.DeleteStackAsync(request),
$"Error attempting to delete the CloudFormation stack '{stackName}'.");
}

public async Task<ResourceDescription> GetCloudControlApiResource(string type, string identifier)
{
var cloudControlApiClient = awsClientFactory.GetAWSClient<IAmazonCloudControlApi>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ public Task<PlatformSummary> GetLatestElasticBeanstalkPlatformArn(string? target
public Task<List<SecurityGroup>> DescribeSecurityGroups(string? vpcID = null) => throw new NotImplementedException();
public Task<string?> GetParameterStoreTextValue(string parameterName) => throw new NotImplementedException();
public Task<ResourceDescription> GetCloudControlApiResource(string type, string identifier) => throw new NotImplementedException();
public Task<List<Stack>> DescribeStacks(string stackName) => throw new NotImplementedException();

public Task<DeleteStackResponse> DeleteStack(string stackName) => throw new NotImplementedException();

public Task<Vpc?> GetDefaultVpc() => throw new NotImplementedException();
public Task<List<ConfigurationSettingsDescription>> DescribeElasticBeanstalkConfigurationSettings(string applicationName, string environmentName) => throw new NotImplementedException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ public Task<PlatformSummary> GetLatestElasticBeanstalkPlatformArn(string? target
public Task<List<SecurityGroup>> DescribeSecurityGroups(string? vpcID = null) => throw new NotImplementedException();
public Task<string?> GetParameterStoreTextValue(string parameterName) => throw new NotImplementedException();
public Task<ResourceDescription> GetCloudControlApiResource(string type, string identifier) => throw new NotImplementedException();
public Task<List<Stack>> DescribeStacks(string stackName) => throw new NotImplementedException();

public Task<DeleteStackResponse> DeleteStack(string stackName) => throw new NotImplementedException();

public Task<Vpc?> GetDefaultVpc() => throw new NotImplementedException();
public Task<List<ConfigurationSettingsDescription>> DescribeElasticBeanstalkConfigurationSettings(string applicationName, string environmentName) => throw new NotImplementedException();
}
Expand Down
Loading