Skip to content

Commit

Permalink
Merge pull request #428 from aws/dev
Browse files Browse the repository at this point in the history
chore: release 0.32
  • Loading branch information
philasmar authored Jan 18, 2022
2 parents 49dde02 + e2a1c6d commit 5eb08cc
Show file tree
Hide file tree
Showing 30 changed files with 774 additions and 103 deletions.
4 changes: 2 additions & 2 deletions src/AWS.Deploy.CLI/Commands/DeployCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ private void ConfigureDeploymentFromConfigFile(Recommendation recommendation, Us
var validatorFailedResults =
recommendation.Recipe
.BuildValidators()
.Select(validator => validator.Validate(recommendation.Recipe, _session))
.Select(validator => validator.Validate(recommendation, _session))
.Where(x => !x.IsValid)
.ToList();

Expand Down Expand Up @@ -692,7 +692,7 @@ private async Task ConfigureDeploymentFromCli(Recommendation recommendation, IEn
var validatorFailedResults =
recommendation.Recipe
.BuildValidators()
.Select(validator => validator.Validate(recommendation.Recipe, _session))
.Select(validator => validator.Validate(recommendation, _session))
.Where(x => !x.IsValid)
.ToList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using System.Threading.Tasks;
using Amazon.ElasticBeanstalk.Model;
using AWS.Deploy.CLI.TypeHintResponses;
using AWS.Deploy.Common;
using AWS.Deploy.Common.Recipes;
using AWS.Deploy.Common.TypeHintData;
Expand Down Expand Up @@ -39,16 +40,24 @@ private async Task<List<EnvironmentDescription>> GetData(Recommendation recommen

public async Task<object> Execute(Recommendation recommendation, OptionSettingItem optionSetting)
{
var currentValue = recommendation.GetOptionSettingValue(optionSetting);
var environments = await GetData(recommendation, optionSetting);
var currentTypeHintResponse = recommendation.GetOptionSettingValue<BeanstalkEnvironmentTypeHintResponse>(optionSetting);

var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(
options: environments.Select(env => env.EnvironmentName),
title: "Select Elastic Beanstalk environment to deploy to:",
askNewName: true,
defaultNewName: currentValue.ToString() ?? "");
return userResponse.SelectedOption ?? userResponse.NewName
?? throw new UserPromptForNameReturnedNullException(DeployToolErrorCode.BeanstalkEnvPromptForNameReturnedNull, "The user response for a new environment name was null.");
var userInputConfiguration = new UserInputConfiguration<EnvironmentDescription>(
env => env.EnvironmentName,
app => app.EnvironmentName.Equals(currentTypeHintResponse?.EnvironmentName),
currentTypeHintResponse.EnvironmentName)
{
AskNewName = true,
};

var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(environments, "Select Elastic Beanstalk environment to deploy to:", userInputConfiguration);

return new BeanstalkEnvironmentTypeHintResponse(
userResponse.CreateNew,
userResponse.SelectedOption?.EnvironmentName ?? userResponse.NewName
?? throw new UserPromptForNameReturnedNullException(DeployToolErrorCode.BeanstalkAppPromptForNameReturnedNull, "The user response for a new environment name was null.")
);
}
}
}
10 changes: 5 additions & 5 deletions src/AWS.Deploy.CLI/Commands/TypeHints/InstanceTypeCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,24 @@ public InstanceTypeCommand(IAWSResourceQueryer awsResourceQueryer, IConsoleUtili
_consoleUtilities = consoleUtilities;
}

private async Task<List<InstanceTypeInfo>?> GetData(Recommendation recommendation, OptionSettingItem optionSetting)
private async Task<List<InstanceTypeInfo>?> GetData()
{
return await _awsResourceQueryer.ListOfAvailableInstanceTypes();
}

public async Task<List<TypeHintResource>?> GetResources(Recommendation recommendation, OptionSettingItem optionSetting)
{
var instanceType = await GetData(recommendation, optionSetting);
var instanceType = await GetData();

return instanceType?
.OrderBy(x => x.InstanceType.Value)
.Select(x => new TypeHintResource(x.InstanceType.Value, x.InstanceType.Value))
.Distinct()
.OrderBy(x => x)
.ToList();
}

public async Task<object> Execute(Recommendation recommendation, OptionSettingItem optionSetting)
{
var instanceTypes = await GetData(recommendation, optionSetting);
var instanceTypes = await GetData();
var instanceTypeDefaultValue = recommendation.GetOptionSettingDefaultValue<string>(optionSetting);
if (instanceTypes == null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using AWS.Deploy.Common.Recipes;

namespace AWS.Deploy.CLI.TypeHintResponses
{
/// <summary>
/// The <see cref="BeanstalkApplicationTypeHintResponse"/> class encapsulates
/// <see cref="OptionSettingTypeHint.BeanstalkEnvironment"/> type hint response
/// </summary>
public class BeanstalkEnvironmentTypeHintResponse : IDisplayable
{
public bool CreateNew { get; set; }
public string EnvironmentName { get; set; }

public BeanstalkEnvironmentTypeHintResponse(
bool createNew,
string environmentName)
{
CreateNew = createNew;
EnvironmentName = environmentName;
}

public string ToDisplayString() => EnvironmentName;
}
}
2 changes: 1 addition & 1 deletion src/AWS.Deploy.Common/AWS.Deploy.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AWSSDK.Core" Version="3.7.1.1" />
<PackageReference Include="AWSSDK.Core" Version="3.7.5.10" />
<PackageReference Include="AWSSDK.Extensions.NETCore.Setup" Version="3.7.1" />
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.1.35" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ namespace AWS.Deploy.Common.Recipes.Validation
/// </summary>
public interface IRecipeValidator
{
ValidationResult Validate(RecipeDefinition recipe, IDeployToolValidationContext deployValidationContext);
ValidationResult Validate(Recommendation recommendation, IDeployToolValidationContext deployValidationContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ public enum RecipeValidatorList
/// <summary>
/// Must be paired with <see cref="FargateTaskCpuMemorySizeValidator"/>
/// </summary>
FargateTaskSizeCpuMemoryLimits
FargateTaskSizeCpuMemoryLimits,

/// <summary>
/// Must be paired with <see cref="MinMaxConstraintValidator"/>
/// </summary>
MinMaxConstraint
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,37 +37,36 @@ private static IEnumerable<string> BuildMemoryArray(int start, int end, int incr
start += increment;
}
}

public string CpuOptionSettingsId { get; set; } = "TaskCpu";

private static readonly string defaultCpuOptionSettingsId = "TaskCpu";
private static readonly string defaultMemoryOptionSettingsId = "TaskMemory";
private static readonly string defaultValidationFailedMessage =
"Cpu value {{cpu}} is not compatible with memory value {{memory}}. Allowed values are {{memoryList}}";
public string MemoryOptionSettingsId { get; set; } = "TaskMemory";

/// <summary>
/// Supports replacement tokens {{cpu}}, {{memory}}, and {{memoryList}}
/// </summary>
public string ValidationFailedMessage { get; set; } = defaultValidationFailedMessage;

public string? InvalidCpuValueValidationFailedMessage {get;set;}
public string ValidationFailedMessage { get; set; } =
"Cpu value {{cpu}} is not compatible with memory value {{memory}}. Allowed values are {{memoryList}}";

public string CpuOptionSettingsId { get; set; } = defaultCpuOptionSettingsId;
public string MemoryOptionSettingsId { get; set; } = defaultMemoryOptionSettingsId;
public string? InvalidCpuValueValidationFailedMessage { get; set; }

/// <inheritdoc cref="FargateTaskCpuMemorySizeValidator"/>
public ValidationResult Validate(RecipeDefinition recipe, IDeployToolValidationContext deployValidationContext)
public ValidationResult Validate(Recommendation recommendation, IDeployToolValidationContext deployValidationContext)
{
var cpuItem = recipe.OptionSettings.FirstOrDefault(x => x.Id == CpuOptionSettingsId);
var memoryItem = recipe.OptionSettings.FirstOrDefault(x => x.Id == MemoryOptionSettingsId);
string cpu;
string memory;

if (null == cpuItem || null == memoryItem)
try
{
cpu = recommendation.GetOptionSettingValue<string>(recommendation.GetOptionSetting(CpuOptionSettingsId));
memory = recommendation.GetOptionSettingValue<string>(recommendation.GetOptionSetting(MemoryOptionSettingsId));
}
catch (OptionSettingItemDoesNotExistException)
{
return ValidationResult.Failed("Could not find a valid value for Task CPU or Task Memory " +
"as part of of the ECS Fargate deployment configuration. Please provide a valid value and try again.");
}

var cpu = cpuItem.GetValue<string>(new Dictionary<string, string>());
var memory = memoryItem.GetValue<string>(new Dictionary<string, string>());

if (!_cpuMemoryMap.ContainsKey(cpu))
{
// this could happen, but shouldn't.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

namespace AWS.Deploy.Common.Recipes.Validation
{
/// <summary>
/// This validator enforces a constraint that the value for one option setting item is less than another option setting item.
/// The setting that holds the minimum value is identified by the 'MinValueOptionSettingsId'.
/// The setting that holds the maximum value is identified by the 'MaxValueOptionSettingsId'.
/// </summary>
public class MinMaxConstraintValidator : IRecipeValidator
{
public string MinValueOptionSettingsId { get; set; } = string.Empty;
public string MaxValueOptionSettingsId { get; set; } = string.Empty;
public string ValidationFailedMessage { get; set; } = "The value specified for {{MinValueOptionSettingsId}} must be less than or equal to the value specified for {{MaxValueOptionSettingsId}}";

public ValidationResult Validate(Recommendation recommendation, IDeployToolValidationContext deployValidationContext)
{
double minVal;
double maxValue;

try
{
minVal = recommendation.GetOptionSettingValue<double>(recommendation.GetOptionSetting(MinValueOptionSettingsId));
maxValue = recommendation.GetOptionSettingValue<double>(recommendation.GetOptionSetting(MaxValueOptionSettingsId));
}
catch (OptionSettingItemDoesNotExistException)
{
return ValidationResult.Failed($"Could not find a valid value for {MinValueOptionSettingsId} or {MaxValueOptionSettingsId}. Please provide a valid value and try again.");
}

if (minVal <= maxValue)
return ValidationResult.Valid();

var failureMessage =
ValidationFailedMessage
.Replace("{{MinValueOptionSettingsId}}", MinValueOptionSettingsId)
.Replace("{{MaxValueOptionSettingsId}}", MaxValueOptionSettingsId);

return ValidationResult.Failed(failureMessage);
}
}
}
3 changes: 2 additions & 1 deletion src/AWS.Deploy.Common/Recipes/Validation/ValidatorFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public static class ValidatorFactory

private static readonly Dictionary<RecipeValidatorList, Type> _recipeValidatorTypeMapping = new()
{
{ RecipeValidatorList.FargateTaskSizeCpuMemoryLimits, typeof(FargateTaskCpuMemorySizeValidator) }
{ RecipeValidatorList.FargateTaskSizeCpuMemoryLimits, typeof(FargateTaskCpuMemorySizeValidator) },
{ RecipeValidatorList.MinMaxConstraint, typeof(MinMaxConstraintValidator) }
};

public static IOptionSettingItemValidator[] BuildValidators(this OptionSettingItem optionSettingItem)
Expand Down
2 changes: 1 addition & 1 deletion src/AWS.Deploy.Common/Recommendation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class Recommendation : IUserInputOption

public DeploymentBundle DeploymentBundle { get; }

private readonly List<OptionSettingItem> DeploymentBundleSettings = new ();
public readonly List<OptionSettingItem> DeploymentBundleSettings = new ();

private readonly Dictionary<string, string> _replacementTokens = new();

Expand Down
2 changes: 1 addition & 1 deletion src/AWS.Deploy.Orchestration/SystemCapabilityEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public async Task<List<SystemCapability>> EvaluateSystemCapabilities(Recommendat
capabilities.Add(new SystemCapability("Docker", false, false)
{
InstallationUrl = "https://docs.docker.com/engine/install/",
Message = "The selected deployment option requires Docker, which was not detected. Please install and start the appropriate version of Docker for you OS: https://docs.docker.com/engine/install/"
Message = "The selected deployment option requires Docker, which was not detected. Please install and start the appropriate version of Docker for your OS: https://docs.docker.com/engine/install/"
});
}
else if (!systemCapabilities.DockerInfo.DockerContainerType.Equals("linux", StringComparison.OrdinalIgnoreCase))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

// This is a generated file from the original deployment recipe. It contains properties for
// all of the settings defined in the recipe file. It is recommended to not modify this file in order
// to allow easy updates to the file when the original recipe that this project was created from has updates.
// This class is marked as a partial class. If you add new settings to the recipe file, those settings should be
// added to partial versions of this class outside of the Generated folder for example in the Configuration folder.

namespace AspNetAppElasticBeanstalkLinux.Configurations
{
public partial class BeanstalkEnvironmentConfiguration
{
public bool CreateNew { get; set; }
public string EnvironmentName { get; set; }

/// A parameterless constructor is needed for <see cref="Microsoft.Extensions.Configuration.ConfigurationBuilder"/>
/// or the classes will fail to initialize.
/// The warnings are disabled since a parameterless constructor will allow non-nullable properties to be initialized with null values.
#nullable disable warnings
public BeanstalkEnvironmentConfiguration()
{

}
#nullable restore warnings

public BeanstalkEnvironmentConfiguration(
bool createNew,
string environmentName)
{
CreateNew = createNew;
EnvironmentName = environmentName;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ public partial class Configuration
public string InstanceType { get; set; }

/// <summary>
/// The Elastic Beanstalk environment name.
/// The Elastic Beanstalk environment.
/// </summary>
public string EnvironmentName { get; set; }
public BeanstalkEnvironmentConfiguration BeanstalkEnvironment { get; set; }

/// <summary>
/// The Elastic Beanstalk application.
Expand Down Expand Up @@ -106,7 +106,7 @@ public Configuration()
public Configuration(
IAMRoleConfiguration applicationIAMRole,
string instanceType,
string environmentName,
BeanstalkEnvironmentConfiguration beanstalkEnvironment,
BeanstalkApplicationConfiguration beanstalkApplication,
string elasticBeanstalkPlatformArn,
string ec2KeyPair,
Expand All @@ -123,7 +123,7 @@ public Configuration(
{
ApplicationIAMRole = applicationIAMRole;
InstanceType = instanceType;
EnvironmentName = environmentName;
BeanstalkEnvironment = beanstalkEnvironment;
BeanstalkApplication = beanstalkApplication;
ElasticBeanstalkPlatformArn = elasticBeanstalkPlatformArn;
EC2KeyPair = ec2KeyPair;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,12 @@ private void ConfigureBeanstalkEnvironment(Configuration settings)
}
}

if (!settings.BeanstalkEnvironment.CreateNew)
throw new InvalidOrMissingConfigurationException("The ability to deploy an Elastic Beanstalk application to an existing environment via a new CloudFormation stack is not supported yet.");

BeanstalkEnvironment = new CfnEnvironment(this, nameof(BeanstalkEnvironment), InvokeCustomizeCDKPropsEvent(nameof(BeanstalkEnvironment), this, new CfnEnvironmentProps
{
EnvironmentName = settings.EnvironmentName,
EnvironmentName = settings.BeanstalkEnvironment.EnvironmentName,
ApplicationName = settings.BeanstalkApplication.ApplicationName,
PlatformArn = settings.ElasticBeanstalkPlatformArn,
OptionSettings = optionSettingProperties.ToArray(),
Expand Down
Loading

0 comments on commit 5eb08cc

Please sign in to comment.