-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: deployment workflow fails if there is no default vpc
- Loading branch information
Showing
34 changed files
with
610 additions
and
74 deletions.
There are no files selected for viewing
192 changes: 192 additions & 0 deletions
192
src/AWS.Deploy.CLI/Commands/TypeHints/ElasticBeanstalkVpcCommand.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Amazon.EC2.Model; | ||
using Amazon.ECS.Model; | ||
using AWS.Deploy.CLI.TypeHintResponses; | ||
using AWS.Deploy.Common; | ||
using AWS.Deploy.Common.Data; | ||
using AWS.Deploy.Common.Recipes; | ||
using AWS.Deploy.Common.TypeHintData; | ||
using AWS.Deploy.Orchestration; | ||
using AWS.Deploy.Orchestration.Data; | ||
using Newtonsoft.Json; | ||
|
||
namespace AWS.Deploy.CLI.Commands.TypeHints | ||
{ | ||
public class ElasticBeanstalkVpcCommand : ITypeHintCommand | ||
{ | ||
private readonly IAWSResourceQueryer _awsResourceQueryer; | ||
private readonly IConsoleUtilities _consoleUtilities; | ||
private readonly IToolInteractiveService _toolInteractiveService; | ||
private readonly IOptionSettingHandler _optionSettingHandler; | ||
|
||
public ElasticBeanstalkVpcCommand(IAWSResourceQueryer awsResourceQueryer, IConsoleUtilities consoleUtilities, IToolInteractiveService toolInteractiveService, IOptionSettingHandler optionSettingHandler) | ||
{ | ||
_awsResourceQueryer = awsResourceQueryer; | ||
_consoleUtilities = consoleUtilities; | ||
_toolInteractiveService = toolInteractiveService; | ||
_optionSettingHandler = optionSettingHandler; | ||
} | ||
|
||
private async Task<List<Vpc>> GetData() | ||
{ | ||
return await _awsResourceQueryer.GetListOfVpcs(); | ||
} | ||
|
||
public async Task<TypeHintResourceTable> GetResources(Recommendation recommendation, OptionSettingItem optionSetting) | ||
{ | ||
var vpcs = await GetData(); | ||
var resourceTable = new TypeHintResourceTable(); | ||
|
||
resourceTable.Rows = vpcs.ToDictionary(x => x.VpcId, x => { | ||
var name = x.Tags?.FirstOrDefault(x => x.Key == "Name")?.Value ?? string.Empty; | ||
var namePart = | ||
string.IsNullOrEmpty(name) | ||
? "" | ||
: $" ({name}) "; | ||
var isDefaultPart = | ||
x.IsDefault | ||
? " *** Account Default VPC ***" | ||
: ""; | ||
return $"{x.VpcId}{namePart}{isDefaultPart}"; | ||
}).Select(x => new TypeHintResource(x.Key, x.Value)).ToList(); | ||
|
||
return resourceTable; | ||
} | ||
|
||
public async Task<object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) | ||
{ | ||
_toolInteractiveService.WriteLine(); | ||
var useVpcOptionSetting = optionSetting.ChildOptionSettings.First(x => x.Id.Equals("UseVPC")); | ||
var useVpcValue = _optionSettingHandler.GetOptionSettingValue<string>(recommendation, useVpcOptionSetting) ?? "false"; | ||
var useVpcAnswer = _consoleUtilities.AskYesNoQuestion(useVpcOptionSetting.Description, useVpcValue); | ||
var useVpc = useVpcAnswer == YesNo.Yes; | ||
|
||
if (!useVpc) | ||
return new ElasticBeanstalkVpcTypeHintResponse() | ||
{ | ||
UseVPC = false | ||
}; | ||
|
||
var currentVpcTypeHintResponse = optionSetting.GetTypeHintData<ElasticBeanstalkVpcTypeHintResponse>(); | ||
|
||
var vpcs = await GetData(); | ||
|
||
if (!vpcs.Any()) | ||
{ | ||
_toolInteractiveService.WriteLine(); | ||
_toolInteractiveService.WriteLine("There are no VPCs in the selected account. The only option is to create a new one."); | ||
return new ElasticBeanstalkVpcTypeHintResponse | ||
{ | ||
UseVPC = true, | ||
CreateNew = true | ||
}; | ||
} | ||
|
||
_toolInteractiveService.WriteLine(); | ||
var vpcOptionSetting = optionSetting.ChildOptionSettings.First(x => x.Id.Equals("VpcId")); | ||
var currentVpcValue = _optionSettingHandler.GetOptionSettingValue(recommendation, vpcOptionSetting).ToString(); | ||
var userInputConfigurationVPCs = new UserInputConfiguration<Vpc>( | ||
idSelector: vpc => vpc.VpcId, | ||
displaySelector: vpc => | ||
{ | ||
var name = vpc.Tags?.FirstOrDefault(x => x.Key == "Name")?.Value ?? string.Empty; | ||
var namePart = | ||
string.IsNullOrEmpty(name) | ||
? "" | ||
: $" ({name}) "; | ||
var isDefaultPart = | ||
vpc.IsDefault | ||
? " *** Account Default VPC ***" | ||
: ""; | ||
return $"{vpc.VpcId}{namePart}{isDefaultPart}"; | ||
}, | ||
defaultSelector: vpc => | ||
!string.IsNullOrEmpty(currentVpcTypeHintResponse?.VpcId) | ||
? vpc.VpcId == currentVpcTypeHintResponse.VpcId | ||
: vpc.IsDefault) | ||
{ | ||
CanBeEmpty = false, | ||
CreateNew = true | ||
}; | ||
var vpc = _consoleUtilities.AskUserToChooseOrCreateNew<Vpc>(vpcs, "Select a VPC:", userInputConfigurationVPCs); | ||
if (vpc.CreateNew) | ||
return new ElasticBeanstalkVpcTypeHintResponse | ||
{ | ||
UseVPC = true, | ||
CreateNew = true | ||
}; | ||
if (vpc.SelectedOption == null) | ||
return new ElasticBeanstalkVpcTypeHintResponse | ||
{ | ||
UseVPC = false | ||
}; | ||
|
||
var availableSubnets = (await _awsResourceQueryer.DescribeSubnets(vpc.SelectedOption.VpcId)).OrderBy(x => x.SubnetId).ToList(); | ||
if (!availableSubnets.Any()) | ||
return new ElasticBeanstalkVpcTypeHintResponse | ||
{ | ||
UseVPC = true, | ||
CreateNew = false, | ||
VpcId = vpc.SelectedOption.VpcId | ||
}; | ||
var userInputConfigurationSubnets = new UserInputConfiguration<Subnet>( | ||
idSelector: subnet => subnet.SubnetId, | ||
displaySelector: subnet => $"{subnet.SubnetId.PadRight(24)} | {subnet.VpcId.PadRight(21)} | {subnet.AvailabilityZone}", | ||
defaultSelector: subnet => false) | ||
{ | ||
CanBeEmpty = false, | ||
CreateNew = false | ||
}; | ||
var subnetsOptionSetting = optionSetting.ChildOptionSettings.First(x => x.Id.Equals("Subnets")); | ||
_toolInteractiveService.WriteLine($"{subnetsOptionSetting.Id}:"); | ||
_toolInteractiveService.WriteLine(subnetsOptionSetting.Description); | ||
var subnets = _consoleUtilities.AskUserForList<Subnet>(userInputConfigurationSubnets, availableSubnets, subnetsOptionSetting, recommendation); | ||
|
||
var availableSecurityGroups = (await _awsResourceQueryer.DescribeSecurityGroups(vpc.SelectedOption.VpcId)).OrderBy(x => x.VpcId).ToList(); | ||
if (!availableSecurityGroups.Any()) | ||
return new ElasticBeanstalkVpcTypeHintResponse | ||
{ | ||
UseVPC = true, | ||
CreateNew = false, | ||
VpcId = vpc.SelectedOption.VpcId, | ||
Subnets = subnets | ||
}; | ||
var groupNamePadding = 0; | ||
availableSecurityGroups.ForEach(x => | ||
{ | ||
if (x.GroupName.Length > groupNamePadding) | ||
groupNamePadding = x.GroupName.Length; | ||
}); | ||
var userInputConfigurationSecurityGroups = new UserInputConfiguration<SecurityGroup>( | ||
idSelector: securityGroup => securityGroup.GroupId, | ||
displaySelector: securityGroup => $"{securityGroup.GroupName.PadRight(groupNamePadding)} | {securityGroup.GroupId.PadRight(20)} | {securityGroup.VpcId}", | ||
defaultSelector: securityGroup => false) | ||
{ | ||
CanBeEmpty = false, | ||
CreateNew = false | ||
}; | ||
var securityGroupsOptionSetting = optionSetting.ChildOptionSettings.First(x => x.Id.Equals("SecurityGroups")); | ||
_toolInteractiveService.WriteLine($"{securityGroupsOptionSetting.Id}:"); | ||
_toolInteractiveService.WriteLine(securityGroupsOptionSetting.Description); | ||
var securityGroups = _consoleUtilities.AskUserForList<SecurityGroup>(userInputConfigurationSecurityGroups, availableSecurityGroups, securityGroupsOptionSetting, recommendation); | ||
|
||
return new ElasticBeanstalkVpcTypeHintResponse | ||
{ | ||
UseVPC = true, | ||
CreateNew = false, | ||
VpcId = vpc.SelectedOption.VpcId, | ||
Subnets = subnets, | ||
SecurityGroups = securityGroups | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
src/AWS.Deploy.CLI/TypeHintResponses/ElasticBeanstalkVpcTypeHintResponse.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\r | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
using System.Collections.Generic; | ||
using AWS.Deploy.Common.Recipes; | ||
|
||
namespace AWS.Deploy.CLI.TypeHintResponses | ||
{ | ||
/// <summary> | ||
/// <see cref="OptionSettingTypeHint.Vpc"/> type hint response | ||
/// </summary> | ||
public class ElasticBeanstalkVpcTypeHintResponse : IDisplayable | ||
{ | ||
public bool UseVPC { get; set; } | ||
public bool CreateNew { get; set; } | ||
public string? VpcId { get; set; } | ||
public SortedSet<string> Subnets { get; set; } = new SortedSet<string>(); | ||
public SortedSet<string> SecurityGroups { get; set; } = new SortedSet<string>(); | ||
|
||
public string? ToDisplayString() => null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.