public Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var settingValue = _consoleUtilities .AskUserForValue( string.Empty, recommendation.GetOptionSettingValue(optionSetting).ToString(), allowEmpty: true, resetValue: recommendation.GetOptionSettingDefaultValue <string>(optionSetting), // validators: publishArgs => (publishArgs.Contains("-o ") || publishArgs.Contains("--output ")) ? "You must not include -o/--output as an additional argument as it is used internally." : "", publishArgs => (publishArgs.Contains("-c ") || publishArgs.Contains("--configuration ") ? "You must not include -c/--configuration as an additional argument. You can set the build configuration in the advanced settings." : ""), publishArgs => (publishArgs.Contains("--self-contained") || publishArgs.Contains("--no-self-contained") ? "You must not include --self-contained/--no-self-contained as an additional argument. You can set the self-contained property in the advanced settings." : "")) .ToString() .Replace("\"", "\"\""); recommendation.DeploymentBundle.DotnetPublishAdditionalBuildArguments = settingValue; return(Task.FromResult <object>(settingValue)); }
public void CanBuildRehydratedOptionSettingsItem() { // ARRANGE var expectedValidator = new RequiredValidator { ValidationFailedMessage = "Custom Test Message" }; var optionSettingItem = new OptionSettingItem("id", "name", "description") { Name = "Test Item", Validators = new List <OptionSettingItemValidatorConfig> { new OptionSettingItemValidatorConfig { ValidatorType = OptionSettingItemValidatorList.Required, Configuration = expectedValidator } } }; var json = JsonConvert.SerializeObject(optionSettingItem, Formatting.Indented); var deserialized = JsonConvert.DeserializeObject <OptionSettingItem>(json); // ACT var validators = deserialized.BuildValidators(); // ASSERT validators.Length.ShouldEqual(1); validators.First().ShouldBeType(expectedValidator.GetType()); validators.OfType <RequiredValidator>().First().ValidationFailedMessage.ShouldEqual(expectedValidator.ValidationFailedMessage); }
[InlineData("arn:aws:ecs:us-east-1:012345678910:fluster/test", false)] //fluster instead of cluster public void ClusterArnValidationTests(string value, bool isValid) { var optionSettingItem = new OptionSettingItem("id", "name", "description"); optionSettingItem.Validators.Add(GetRegexValidatorConfig("arn:[^:]+:ecs:[^:]*:[0-9]{12}:cluster/.+")); Validate(optionSettingItem, value, isValid); }
public void DesiredCountValidationTests(int value, bool isValid) { var optionSettingItem = new OptionSettingItem("id", "name", "description"); optionSettingItem.Validators.Add(GetRangeValidatorConfig(1, 5000)); Validate(optionSettingItem, value, isValid); }
public void HasABindingForAllOptionSettingItemValidators() { // ARRANGE var allValidators = Enum.GetValues(typeof(OptionSettingItemValidatorList)); var optionSettingItem = new OptionSettingItem("id", "name", "description") { Validators = allValidators .Cast <OptionSettingItemValidatorList>() .Select(validatorType => new OptionSettingItemValidatorConfig { ValidatorType = validatorType } ) .ToList() }; // ACT var validators = optionSettingItem.BuildValidators(); // ASSERT validators.Length.ShouldEqual(allValidators.Length); }
[InlineData("arn:aws:iam::1234567890124354:role/S3Access", false)] //invalid account ID public void RoleArnValidationTests(string value, bool isValid) { var optionSettingItem = new OptionSettingItem("id", "name", "description"); optionSettingItem.Validators.Add(GetRegexValidatorConfig("arn:.+:iam::[0-9]{12}:.+")); Validate(optionSettingItem, value, isValid); }
[InlineData("arn:aws:elasticbeanstack:eu-west-1:123456789012:platform/MyPlatform", false)] //Typo elasticbeanstack instead of elasticbeanstalk public void ElasticBeanstalkPlatformArnValidationTest(string value, bool isValid) { var optionSettingItem = new OptionSettingItem("id", "name", "description"); optionSettingItem.Validators.Add(GetRegexValidatorConfig("arn:[^:]+:elasticbeanstalk:[^:]+:[^:]*:platform/.+")); Validate(optionSettingItem, value, isValid); }
private async Task ConfigureDeployment(Recommendation recommendation, OptionSettingItem setting) { _toolInteractiveService.WriteLine(string.Empty); _toolInteractiveService.WriteLine($"{setting.Name}:"); _toolInteractiveService.WriteLine($"{setting.Description}"); var currentValue = recommendation.GetOptionSettingValue(setting); object settingValue = null; if (setting.AllowedValues?.Count > 0) { var userInputConfig = new UserInputConfiguration <string> { DisplaySelector = x => setting.ValueMapping[x], DefaultSelector = x => x.Equals(currentValue), CreateNew = false }; var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(setting.AllowedValues, string.Empty, userInputConfig); settingValue = userResponse.SelectedOption; // If they didn't change the value then don't store so we can rely on using the default in the recipe. if (Equals(settingValue, currentValue)) { return; } } else { if (setting.TypeHint.HasValue && _typeHintCommandFactory.GetCommand(setting.TypeHint.Value) is var typeHintCommand && typeHintCommand != null) { settingValue = await typeHintCommand.Execute(recommendation, setting); }
[InlineData(" 123 abc-456 ", false)] //leading and trailing space public void EC2KeyPairValidationTest(string value, bool isValid) { var optionSettingItem = new OptionSettingItem("id", "name", "description"); // It allows all ASCII characters but without leading and trailing spaces optionSettingItem.Validators.Add(GetRegexValidatorConfig("^(?! ).+(?<! )$")); Validate(optionSettingItem, value, isValid); }
[InlineData("123*&$_abc_", false)] //invalid characters public void ECSServiceNameValidationTests(string value, bool isValid) { var optionSettingItem = new OptionSettingItem("id", "name", "description"); // Up to 255 letters (uppercase and lowercase), numbers, hyphens, and underscores are allowed. optionSettingItem.Validators.Add(GetRegexValidatorConfig("^([A-Za-z0-9_-]{1,255})$")); Validate(optionSettingItem, value, isValid); }
[InlineData("abc/123/#", false)] // invalid character forward slash(/) public void ApplicationNameValidationTest(string value, bool isValid) { var optionSettingItem = new OptionSettingItem("id", "name", "description"); //can contain up to 100 Unicode characters, not including forward slash (/). optionSettingItem.Validators.Add(GetRegexValidatorConfig("^[^/]{1,100}$")); Validate(optionSettingItem, value, isValid); }
[InlineData("-12-abc", false)] // invalid character leading hyphen (-) public void EnvironmentNameValidationTest(string value, bool isValid) { var optionSettingItem = new OptionSettingItem("id", "name", "description"); // Must be from 4 to 40 characters in length. The name can contain only letters, numbers, and hyphens. // It can't start or end with a hyphen. optionSettingItem.Validators.Add(GetRegexValidatorConfig("^[a-zA-Z0-9][a-zA-Z0-9-]{2,38}[a-zA-Z0-9]$")); Validate(optionSettingItem, value, isValid); }
public async Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var currentValue = recommendation.GetOptionSettingValue(optionSetting); var keyPairs = await _awsResourceQueryer.ListOfEC2KeyPairs(); var userInputConfiguration = new UserInputConfiguration <KeyPairInfo>( kp => kp.KeyName, kp => kp.KeyName.Equals(currentValue) ) { AskNewName = true, EmptyOption = true, CurrentValue = currentValue }; var settingValue = ""; while (true) { var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(keyPairs, "Select key pair to use:", userInputConfiguration); if (userResponse.IsEmpty) { settingValue = ""; break; } else { settingValue = userResponse.SelectedOption?.KeyName ?? userResponse.NewName ?? throw new UserPromptForNameReturnedNullException("The user prompt for a new EC2 Key Pair name was null or empty."); } if (userResponse.CreateNew && !string.IsNullOrEmpty(userResponse.NewName)) { _toolInteractiveService.WriteLine(string.Empty); _toolInteractiveService.WriteLine("You have chosen to create a new key pair."); _toolInteractiveService.WriteLine("You are required to specify a directory to save the key pair private key."); var answer = _consoleUtilities.AskYesNoQuestion("Do you want to continue?", "false"); if (answer == YesNo.No) { continue; } _toolInteractiveService.WriteLine(string.Empty); _toolInteractiveService.WriteLine($"A new key pair will be created with the name {settingValue}."); var keyPairDirectory = _consoleUtilities.AskForEC2KeyPairSaveDirectory(recommendation.ProjectPath); await _awsResourceQueryer.CreateEC2KeyPair(settingValue, keyPairDirectory); } break; } return(settingValue ?? ""); }
[InlineData("vpc-ffffffffaaaabbbb12", false)] //suffix length greater than 17 public void VpcIdValidationTests(string value, bool isValid) { var optionSettingItem = new OptionSettingItem("id", "name", "description"); //must start with the \"vpc-\" prefix, //followed by either 8 or 17 characters consisting of digits and letters(lower-case) from a to f. optionSettingItem.Validators.Add(GetRegexValidatorConfig("^vpc-([0-9a-f]{8}|[0-9a-f]{17})$")); Validate(optionSettingItem, value, isValid); }
public Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var answer = _consoleUtilities.AskYesNoQuestion(string.Empty, recommendation.GetOptionSettingValue <string>(optionSetting)); recommendation.DeploymentBundle.DotnetPublishSelfContainedBuild = answer == YesNo.Yes; var result = answer == YesNo.Yes ? "true" : "false"; return(Task.FromResult <object>(result)); }
public SetOptionSettingTests() { var projectPath = SystemIOUtilities.ResolvePath("WebAppNoDockerFile"); var engine = new RecommendationEngine(new[] { RecipeLocator.FindRecipeDefinitionsPath() }, new Orchestrator.OrchestratorSession()); var recommendations = engine.ComputeRecommendations(projectPath, new Dictionary <string, string>()).GetAwaiter().GetResult(); _recommendation = recommendations.First(r => r.Recipe.Id == Constants.ASPNET_CORE_BEANSTALK_RECIPE_ID); _optionSetting = _recommendation.Recipe.OptionSettings.First(x => x.Id.Equals("EnvironmentType")); }
public Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var settingValue = _consoleUtilities.AskUserForValue( string.Empty, recommendation.GetOptionSettingValue <string>(optionSetting), allowEmpty: false, resetValue: recommendation.GetOptionSettingDefaultValue <string>(optionSetting) ?? ""); recommendation.DeploymentBundle.DotnetPublishBuildConfiguration = settingValue; return(Task.FromResult <object>(settingValue)); }
public Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var settingValue = _consoleUtilities .AskUserForValue( string.Empty, recommendation.GetOptionSettingValue <string>(optionSetting), allowEmpty: true, resetValue: recommendation.GetOptionSettingDefaultValue <string>(optionSetting) ?? "", validators: executionDirectory => ValidateExecutionDirectory(executionDirectory)); recommendation.DeploymentBundle.DockerExecutionDirectory = settingValue; return(Task.FromResult <object>(settingValue)); }
public void WhenValidatorTypeAndConfigurationHaveAMismatchThenValidatorTypeWins() { // ARRANGE var optionSettingItem = new OptionSettingItem("id", "name", "description") { Name = "Test Item", Validators = new List <OptionSettingItemValidatorConfig> { new OptionSettingItemValidatorConfig { ValidatorType = OptionSettingItemValidatorList.Regex, // Required can only map to RequiredValidator, this setup doesn't make sense: Configuration = new RangeValidator { Min = 1 } } } }; var json = JsonConvert.SerializeObject(optionSettingItem, Formatting.Indented); var deserialized = JsonConvert.DeserializeObject <OptionSettingItem>(json); Exception exception = null; IOptionSettingItemValidator[] validators = null; // ACT try { validators = deserialized.BuildValidators(); } catch (Exception e) { exception = e; } // ASSERT exception.ShouldBeNull(); // we have our built validator validators.ShouldNotBeNull(); validators.Length.ShouldEqual(1); // things get a little odd, the type is correct, // but the output messages is going to be from the RangeValidator. validators.First().ShouldBeType <RegexValidator>(); validators.OfType <RegexValidator>().First().ValidationFailedMessage.ShouldEqual( new RangeValidator().ValidationFailedMessage); }
private void DisplayOptionSetting(Recommendation recommendation, OptionSettingItem optionSetting, int optionSettingNumber, int optionSettingsCount, DisplayOptionSettingsMode mode) { var value = recommendation.GetOptionSettingValue(optionSetting); Type typeHintResponseType = null; if (optionSetting.Type == OptionSettingValueType.Object) { var typeHintResponseTypeFullName = $"AWS.Deploy.CLI.TypeHintResponses.{optionSetting.TypeHint}TypeHintResponse"; typeHintResponseType = Assembly.GetExecutingAssembly().GetType(typeHintResponseTypeFullName); } DisplayValue(recommendation, optionSetting, optionSettingNumber, optionSettingsCount, typeHintResponseType, mode); }
public Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var settingValue = _consoleUtilities .AskUserForValue( string.Empty, recommendation.GetOptionSettingValue <string>(optionSetting), allowEmpty: true, resetValue: recommendation.GetOptionSettingDefaultValue <string>(optionSetting) ?? "", validators: buildArgs => ValidateBuildArgs(buildArgs)) .ToString() .Replace("\"", "\"\""); recommendation.DeploymentBundle.DockerBuildArgs = settingValue; return(Task.FromResult <object>(settingValue)); }
public async Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var currentValue = recommendation.GetOptionSettingValue(optionSetting); var applicationOptionSetting = recommendation.GetOptionSetting(optionSetting.ParentSettingId); var applicationName = recommendation.GetOptionSettingValue(applicationOptionSetting) as string; var environments = await _awsResourceQueryer.ListOfElasticBeanstalkEnvironments(_session, applicationName); 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); }
public async Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var currentValue = recommendation.GetOptionSettingValue(optionSetting); var platformArns = await _awsResourceQueryer.GetElasticBeanstalkPlatformArns(_session); var userInputConfiguration = new UserInputConfiguration <PlatformSummary> { DisplaySelector = platform => $"{platform.PlatformBranchName} v{platform.PlatformVersion}", DefaultSelector = platform => platform.PlatformArn.Equals(currentValue), CreateNew = false }; var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(platformArns, "Select the Platform to use:", userInputConfiguration); return(userResponse.SelectedOption?.PlatformArn); }
public async Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var loadBalancers = await _awsResourceQueryer.ListOfLoadBalancers(LoadBalancerTypeEnum.Application); var currentValue = recommendation.GetOptionSettingValue <string>(optionSetting); var userInputConfiguration = new UserInputConfiguration <LoadBalancer>( loadBalancer => loadBalancer.LoadBalancerName, loadBalancer => loadBalancer.LoadBalancerArn.Equals(currentValue)) { AskNewName = false }; var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(loadBalancers, "Select Load Balancer to deploy to:", userInputConfiguration); return(userResponse.SelectedOption?.LoadBalancerArn ?? string.Empty); }
public async Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var typeHintData = optionSetting.GetTypeHintData <IAMRoleTypeHintData>(); var existingRoles = await _awsResourceQueryer.ListOfIAMRoles(typeHintData?.ServicePrincipal); var currentTypeHintResponse = recommendation.GetOptionSettingValue <IAMRoleTypeHintResponse>(optionSetting); var userInputConfiguration = new UserInputConfiguration <Role>( role => role.RoleName, role => currentTypeHintResponse.RoleArn?.Equals(role.Arn) ?? false); var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(existingRoles, "Select an IAM role", userInputConfiguration); return(new IAMRoleTypeHintResponse { CreateNew = userResponse.CreateNew, RoleArn = userResponse.SelectedOption?.Arn }); }
public async Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var currentVpcTypeHintResponse = optionSetting.GetTypeHintData <VpcTypeHintResponse>(); var vpcs = await _awsResourceQueryer.GetListOfVpcs(_session); var userInputConfig = new UserInputConfiguration <Vpc> { 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 }; var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew( vpcs, "Select a VPC", userInputConfig); return(new VpcTypeHintResponse { IsDefault = userResponse.SelectedOption?.IsDefault == true, CreateNew = userResponse.CreateNew, VpcId = userResponse.SelectedOption?.VpcId ?? "" }); }
public async Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var clusters = await _awsResourceQueryer.ListOfECSClusters(); var currentTypeHintResponse = recommendation.GetOptionSettingValue <ECSClusterTypeHintResponse>(optionSetting); var userInputConfiguration = new UserInputConfiguration <Cluster>( cluster => cluster.ClusterName, cluster => cluster.ClusterArn.Equals(currentTypeHintResponse?.ClusterArn), currentTypeHintResponse.NewClusterName) { AskNewName = true }; var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(clusters, "Select ECS cluster to deploy to:", userInputConfiguration); return(new ECSClusterTypeHintResponse( userResponse.CreateNew, userResponse.SelectedOption?.ClusterArn ?? string.Empty, userResponse.NewName ?? string.Empty)); }
public async Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var applications = await _awsResourceQueryer.ListOfElasticBeanstalkApplications(); var currentTypeHintResponse = recommendation.GetOptionSettingValue <BeanstalkApplicationTypeHintResponse>(optionSetting); var userInputConfiguration = new UserInputConfiguration <ApplicationDescription>( app => app.ApplicationName, app => app.ApplicationName.Equals(currentTypeHintResponse?.ApplicationName), currentTypeHintResponse.ApplicationName) { AskNewName = true, }; var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(applications, "Select Elastic Beanstalk application to deploy to:", userInputConfiguration); return(new BeanstalkApplicationTypeHintResponse( userResponse.CreateNew, userResponse.SelectedOption?.ApplicationName ?? userResponse.NewName ?? throw new UserPromptForNameReturnedNullException("The user response for a new application name was null.") )); }
public async Task <object> Execute(Recommendation recommendation, OptionSettingItem optionSetting) { var applications = await _awsResourceQueryer.ListOfElasticBeanstalkApplications(_session); var currentTypeHintResponse = recommendation.GetOptionSettingValue <BeanstalkApplicationTypeHintResponse>(optionSetting); var userInputConfiguration = new UserInputConfiguration <ApplicationDescription> { DisplaySelector = app => app.ApplicationName, DefaultSelector = app => app.ApplicationName.Equals(currentTypeHintResponse?.ApplicationName), AskNewName = true, DefaultNewName = currentTypeHintResponse.ApplicationName }; var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(applications, "Select Elastic Beanstalk application to deploy to:", userInputConfiguration); return(new BeanstalkApplicationTypeHintResponse { CreateNew = userResponse.CreateNew, ApplicationName = userResponse.SelectedOption?.ApplicationName ?? userResponse.NewName }); }
public SetOptionSettingTests() { var projectPath = SystemIOUtilities.ResolvePath("WebAppNoDockerFile"); var parser = new ProjectDefinitionParser(new FileManager(), new DirectoryManager()); var awsCredentials = new Mock <AWSCredentials>(); var session = new OrchestratorSession( parser.Parse(projectPath).Result, awsCredentials.Object, "us-west-2", "123456789012") { AWSProfileName = "default" }; var engine = new RecommendationEngine(new[] { RecipeLocator.FindRecipeDefinitionsPath() }, session); var recommendations = engine.ComputeRecommendations().GetAwaiter().GetResult(); _recommendation = recommendations.First(r => r.Recipe.Id == Constants.ASPNET_CORE_BEANSTALK_RECIPE_ID); _optionSetting = _recommendation.Recipe.OptionSettings.First(x => x.Id.Equals("EnvironmentType")); }