From fdf67d3a89c6b4b096c3a4d7ae1321ed274a9de4 Mon Sep 17 00:00:00 2001 From: Phil Asmar Date: Mon, 1 Jul 2024 11:29:24 -0400 Subject: [PATCH] feat: Remove disabled fields from showing on redeployment in server mode --- .../Controllers/DeploymentController.cs | 4 +- .../Recipes/OptionSettingItem.cs | 5 ++ .../ASP.NETAppAppRunner.recipe | 1 + .../ASP.NETAppECSFargate.recipe | 7 +- .../ASP.NETAppElasticBeanstalkLinux.recipe | 5 ++ .../ASP.NETAppElasticBeanstalkWindows.recipe | 4 + .../ConsoleAppECSFargateScheduleTask.recipe | 3 + .../ConsoleAppECSFargateService.recipe | 4 + .../aws-deploy-recipe-schema.json | 6 ++ .../ServerModeTests.cs | 82 +++++++++++++++++++ 10 files changed, 119 insertions(+), 2 deletions(-) diff --git a/src/AWS.Deploy.CLI/ServerMode/Controllers/DeploymentController.cs b/src/AWS.Deploy.CLI/ServerMode/Controllers/DeploymentController.cs index 4ceb91d23..206a6c7c0 100644 --- a/src/AWS.Deploy.CLI/ServerMode/Controllers/DeploymentController.cs +++ b/src/AWS.Deploy.CLI/ServerMode/Controllers/DeploymentController.cs @@ -208,7 +208,9 @@ private List ListOptionSettingSummary(IOptionSettingHa Value = optionSettingHandler.GetOptionSettingValue(recommendation, setting), Advanced = setting.AdvancedSetting, ReadOnly = recommendation.IsExistingCloudApplication && !setting.Updatable, - Visible = optionSettingHandler.IsOptionSettingDisplayable(recommendation, setting), + Visible = + optionSettingHandler.IsOptionSettingDisplayable(recommendation, setting) && + !(recommendation.IsExistingCloudApplication && !setting.Updatable && !setting.VisibleOnRedeployment), SummaryDisplayable = optionSettingHandler.IsSummaryDisplayable(recommendation, setting), AllowedValues = setting.AllowedValues, ValueMapping = setting.ValueMapping, diff --git a/src/AWS.Deploy.Common/Recipes/OptionSettingItem.cs b/src/AWS.Deploy.Common/Recipes/OptionSettingItem.cs index 14f3ab010..a0f78a960 100644 --- a/src/AWS.Deploy.Common/Recipes/OptionSettingItem.cs +++ b/src/AWS.Deploy.Common/Recipes/OptionSettingItem.cs @@ -124,6 +124,11 @@ public partial class OptionSettingItem : IOptionSettingItem /// public bool Updatable { get; set; } + /// + /// If the value is true, the setting will be displayed during a redeployment. This only applies to server-mode clients. + /// + public bool VisibleOnRedeployment { get; set; } + /// /// List of all validators that should be run when configuring this OptionSettingItem. /// diff --git a/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppAppRunner.recipe b/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppAppRunner.recipe index 6b993c4d3..54ff3d951 100644 --- a/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppAppRunner.recipe +++ b/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppAppRunner.recipe @@ -100,6 +100,7 @@ "TypeHint": "AppRunnerService", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "DefaultValue": "{StackName}-service", "Validators": [ { diff --git a/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppECSFargate.recipe b/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppECSFargate.recipe index 5c23ccc8a..00d00f8d0 100644 --- a/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppECSFargate.recipe +++ b/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppECSFargate.recipe @@ -118,6 +118,7 @@ "TypeHint": "ECSCluster", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "ChildOptionSettings": [ { "Id": "CreateNew", @@ -136,6 +137,7 @@ "TypeHint": "ExistingECSCluster", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "Validators": [ { "ValidatorType": "Regex", @@ -160,6 +162,7 @@ "DefaultValue": "{StackName}", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "Validators": [ { "ValidatorType": "Regex", @@ -195,6 +198,7 @@ "DefaultValue": "{StackName}-service", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "Validators": [ { "ValidatorType": "Regex", @@ -738,7 +742,8 @@ "Type": "Bool", "DefaultValue": true, "AdvancedSetting": false, - "Updatable": false + "Updatable": false, + "VisibleOnRedeployment": true } ] }, diff --git a/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppElasticBeanstalkLinux.recipe b/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppElasticBeanstalkLinux.recipe index ab48fa97e..4143c9b84 100644 --- a/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppElasticBeanstalkLinux.recipe +++ b/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppElasticBeanstalkLinux.recipe @@ -137,6 +137,7 @@ "TypeHint": "BeanstalkApplication", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "ChildOptionSettings": [ { "Id": "CreateNew", @@ -155,6 +156,7 @@ "DefaultValue": "{StackName}", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "DependsOn": [ { "Id": "BeanstalkApplication.CreateNew", @@ -187,6 +189,7 @@ "DefaultValue": "{StackName}", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "DependsOn": [ { "Id": "BeanstalkApplication.CreateNew", @@ -215,6 +218,7 @@ "Type": "Object", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "ChildOptionSettings": [ { "Id": "EnvironmentName", @@ -225,6 +229,7 @@ "DefaultValue": "{StackName}-dev", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "Validators": [ { "ValidatorType": "Regex", diff --git a/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppElasticBeanstalkWindows.recipe b/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppElasticBeanstalkWindows.recipe index 0fe4fdfda..c1ef92c35 100644 --- a/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppElasticBeanstalkWindows.recipe +++ b/src/AWS.Deploy.Recipes/RecipeDefinitions/ASP.NETAppElasticBeanstalkWindows.recipe @@ -137,6 +137,7 @@ "TypeHint": "BeanstalkApplication", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "ChildOptionSettings": [ { "Id": "CreateNew", @@ -155,6 +156,7 @@ "DefaultValue": "{StackName}", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "DependsOn": [ { "Id": "BeanstalkApplication.CreateNew", @@ -187,6 +189,7 @@ "DefaultValue": "{StackName}", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "DependsOn": [ { "Id": "BeanstalkApplication.CreateNew", @@ -216,6 +219,7 @@ "DefaultValue": "{StackName}-dev", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "Validators": [ { "ValidatorType": "Regex", diff --git a/src/AWS.Deploy.Recipes/RecipeDefinitions/ConsoleAppECSFargateScheduleTask.recipe b/src/AWS.Deploy.Recipes/RecipeDefinitions/ConsoleAppECSFargateScheduleTask.recipe index 33a51c247..2fd93de41 100644 --- a/src/AWS.Deploy.Recipes/RecipeDefinitions/ConsoleAppECSFargateScheduleTask.recipe +++ b/src/AWS.Deploy.Recipes/RecipeDefinitions/ConsoleAppECSFargateScheduleTask.recipe @@ -136,6 +136,7 @@ "TypeHint": "ECSCluster", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "ChildOptionSettings": [ { "Id": "CreateNew", @@ -154,6 +155,7 @@ "TypeHint": "ExistingECSCluster", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "Validators": [ { "ValidatorType": "Regex", @@ -178,6 +180,7 @@ "DefaultValue": "{StackName}", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "Validators": [ { "ValidatorType": "Regex", diff --git a/src/AWS.Deploy.Recipes/RecipeDefinitions/ConsoleAppECSFargateService.recipe b/src/AWS.Deploy.Recipes/RecipeDefinitions/ConsoleAppECSFargateService.recipe index e31c4cb62..c897b7304 100644 --- a/src/AWS.Deploy.Recipes/RecipeDefinitions/ConsoleAppECSFargateService.recipe +++ b/src/AWS.Deploy.Recipes/RecipeDefinitions/ConsoleAppECSFargateService.recipe @@ -176,6 +176,7 @@ "TypeHint": "ECSCluster", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "ChildOptionSettings": [ { "Id": "CreateNew", @@ -194,6 +195,7 @@ "TypeHint": "ExistingECSCluster", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "Validators": [ { "ValidatorType": "Regex", @@ -218,6 +220,7 @@ "DefaultValue": "{StackName}", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "Validators": [ { "ValidatorType": "Regex", @@ -247,6 +250,7 @@ "DefaultValue": "{StackName}-service", "AdvancedSetting": false, "Updatable": false, + "VisibleOnRedeployment": true, "Validators": [ { "ValidatorType": "Regex", diff --git a/src/AWS.Deploy.Recipes/RecipeDefinitions/aws-deploy-recipe-schema.json b/src/AWS.Deploy.Recipes/RecipeDefinitions/aws-deploy-recipe-schema.json index 071a8c6f5..99f053e26 100644 --- a/src/AWS.Deploy.Recipes/RecipeDefinitions/aws-deploy-recipe-schema.json +++ b/src/AWS.Deploy.Recipes/RecipeDefinitions/aws-deploy-recipe-schema.json @@ -587,6 +587,12 @@ "description": "If the setting is false the setting can not be changed during redeployment.", "minLength": 1 }, + "VisibleOnRedeployment": { + "type": "boolean", + "title": "VisibleOnRedeployment", + "description": "If the value is true, the setting will be displayed during a redeployment. This only applies to server-mode clients.", + "minLength": 1 + }, "DependsOn": { "type": "array", "title": "", diff --git a/test/AWS.Deploy.CLI.IntegrationTests/ServerModeTests.cs b/test/AWS.Deploy.CLI.IntegrationTests/ServerModeTests.cs index d65eca697..4db05372b 100644 --- a/test/AWS.Deploy.CLI.IntegrationTests/ServerModeTests.cs +++ b/test/AWS.Deploy.CLI.IntegrationTests/ServerModeTests.cs @@ -190,6 +190,88 @@ public async Task GetRecommendationsWithEncryptedCredentials() } } + [Fact] + public async Task AppRunnerRedeployment_VisibleOnRedeploymentSettings() + { + _stackName = $"ServerModeAppRunner{Guid.NewGuid().ToString().Split('-').Last()}"; + + var projectPath = _testAppManager.GetProjectPath(Path.Combine("testapps", "WebAppWithDockerFile", "WebAppWithDockerFile.csproj")); + var portNumber = 4950; + using var httpClient = ServerModeHttpClientFactory.ConstructHttpClient(ServerModeUtilities.ResolveDefaultCredentials); + + var serverCommand = new ServerModeCommand(_serviceProvider.GetRequiredService(), portNumber, null, true); + var cancelSource = new CancellationTokenSource(); + + var serverTask = serverCommand.ExecuteAsync(cancelSource.Token); + try + { + var baseUrl = $"http://localhost:{portNumber}/"; + var restClient = new RestAPIClient(baseUrl, httpClient); + + await restClient.WaitUntilServerModeReady(); + + var startSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput + { + AwsRegion = _awsRegion, + ProjectPath = projectPath + }); + + var sessionId = startSessionOutput.SessionId; + Assert.NotNull(sessionId); + + var signalRClient = new DeploymentCommunicationClient(baseUrl); + await signalRClient.JoinSession(sessionId); + + var logOutput = new StringBuilder(); + RegisterSignalRMessageCallbacks(signalRClient, logOutput); + + var getRecommendationOutput = await restClient.GetRecommendationsAsync(sessionId); + Assert.NotEmpty(getRecommendationOutput.Recommendations); + + var appRunnerRecommendation = getRecommendationOutput.Recommendations.FirstOrDefault(x => string.Equals(x.RecipeId, "AspNetAppAppRunner")); + Assert.NotNull(appRunnerRecommendation); + + await restClient.SetDeploymentTargetAsync(sessionId, new SetDeploymentTargetInput + { + NewDeploymentName = _stackName, + NewDeploymentRecipeId = appRunnerRecommendation.RecipeId + }); + + await restClient.StartDeploymentAsync(sessionId); + + await restClient.WaitForDeployment(sessionId); + + var stackStatus = await _cloudFormationHelper.GetStackStatus(_stackName); + Assert.Equal(StackStatus.CREATE_COMPLETE, stackStatus); + + Assert.True(logOutput.Length > 0); + + var redeploymentSessionOutput = await restClient.StartDeploymentSessionAsync(new StartDeploymentSessionInput + { + AwsRegion = _awsRegion, + ProjectPath = projectPath + }); + + var redeploymentSessionId = redeploymentSessionOutput.SessionId; + + await restClient.SetDeploymentTargetAsync(redeploymentSessionId, new SetDeploymentTargetInput + { + ExistingDeploymentId = await _cloudFormationHelper.GetStackArn(_stackName) + }); + + var settings = await restClient.GetConfigSettingsAsync(redeploymentSessionId); + + Assert.True(settings.OptionSettings.First(x => x.Id.Equals("ServiceName")).Visible); + Assert.False(settings.OptionSettings.First(x => x.Id.Equals("EncryptionKmsKey")).Visible); + } + finally + { + cancelSource.Cancel(); + await _cloudFormationHelper.DeleteStack(_stackName); + _stackName = null; + } + } + [Fact] public async Task WebFargateDeploymentNoConfigChanges() {