예제 #1
0
        public async Task ResetOptionSettingValue_String()
        {
            var interactiveServices = new TestToolInteractiveServiceImpl(new List <string>
            {
                "<reset>"
            });
            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);

            var engine = await BuildRecommendationEngine("WebAppNoDockerFile");

            var recommendations = await engine.ComputeRecommendations();

            var fargateRecommendation = recommendations.First(r => r.Recipe.Id == Constants.ASPNET_CORE_ASPNET_CORE_FARGATE_RECIPE_ID);

            fargateRecommendation.AddReplacementToken("{StackName}", "MyAppStack");

            var ecsServiceNameOptionSetting = fargateRecommendation.Recipe.OptionSettings.First(optionSetting => optionSetting.Id.Equals("ECSServiceName"));

            var originalDefaultValue = fargateRecommendation.GetOptionSettingDefaultValue <string>(ecsServiceNameOptionSetting);

            ecsServiceNameOptionSetting.SetValueOverride("TestService");

            Assert.Equal("TestService", fargateRecommendation.GetOptionSettingValue <string>(ecsServiceNameOptionSetting));

            ecsServiceNameOptionSetting.SetValueOverride(consoleUtilities.AskUserForValue("Title", "TestService", true, originalDefaultValue));

            Assert.Equal(originalDefaultValue, fargateRecommendation.GetOptionSettingValue <string>(ecsServiceNameOptionSetting));
        }
예제 #2
0
        public async Task ResetOptionSettingValue_Int()
        {
            var interactiveServices = new TestToolInteractiveServiceImpl(new List <string>
            {
                "<reset>"
            });

            var consoleUtilities = new ConsoleUtilities(interactiveServices, _directoryManager);

            var engine = await BuildRecommendationEngine("WebAppNoDockerFile");

            var recommendations = await engine.ComputeRecommendations();

            var fargateRecommendation     = recommendations.First(r => r.Recipe.Id == Constants.ASPNET_CORE_ASPNET_CORE_FARGATE_RECIPE_ID);
            var desiredCountOptionSetting = fargateRecommendation.Recipe.OptionSettings.First(optionSetting => optionSetting.Id.Equals("DesiredCount"));

            var originalDefaultValue = fargateRecommendation.GetOptionSettingDefaultValue <int>(desiredCountOptionSetting);

            desiredCountOptionSetting.SetValueOverride(2);

            Assert.Equal(2, fargateRecommendation.GetOptionSettingValue <int>(desiredCountOptionSetting));

            desiredCountOptionSetting.SetValueOverride(consoleUtilities.AskUserForValue("Title", "2", true, originalDefaultValue.ToString()));

            Assert.Equal(originalDefaultValue, fargateRecommendation.GetOptionSettingValue <int>(desiredCountOptionSetting));
        }
예제 #3
0
        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 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 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 ClearOptionSettingValue_String()
        {
            var interactiveServices = new TestToolInteractiveServiceImpl(new List <string>
            {
                "<reset>"
            });
            var consoleUtilities = new ConsoleUtilities(interactiveServices);
            var projectPath      = SystemIOUtilities.ResolvePath("WebAppNoDockerFile");
            var engine           = new RecommendationEngine(new[] { RecipeLocator.FindRecipeDefinitionsPath() }, new Orchestrator.OrchestratorSession());
            var recommendations  = await engine.ComputeRecommendations(projectPath, new Dictionary <string, string>());

            var fargateRecommendation       = recommendations.First(r => r.Recipe.Id == Constants.ASPNET_CORE_ASPNET_CORE_FARGATE_RECIPE_ID);
            var ecsServiceNameOptionSetting = fargateRecommendation.Recipe.OptionSettings.First(optionSetting => optionSetting.Id.Equals("ECSServiceName"));

            var originalDefaultValue = fargateRecommendation.GetOptionSettingDefaultValue <string>(ecsServiceNameOptionSetting);

            ecsServiceNameOptionSetting.SetValueOverride("TestService");

            Assert.Equal("TestService", fargateRecommendation.GetOptionSettingValue <string>(ecsServiceNameOptionSetting));

            ecsServiceNameOptionSetting.SetValueOverride(consoleUtilities.AskUserForValue("Title", "TestService", true, originalDefaultValue));

            Assert.Equal(originalDefaultValue, fargateRecommendation.GetOptionSettingValue <string>(ecsServiceNameOptionSetting));
        }
        public async Task ExecuteAsync(bool saveCdkProject)
        {
            // Ensure a .NET project can be found.
            ProjectDefinition project = null;

            try
            {
                project = new ProjectDefinition(_session.ProjectPath);
            }
            catch (ProjectFileNotFoundException ex)
            {
                var files = Directory.GetFiles(_session.ProjectPath, "*.sln");
                if (files.Any())
                {
                    _toolInteractiveService.WriteErrorLine($"This directory contains a solution file, but the tool requires a project file. Please run the tool from the directory that contains a .csproj/.fsproj or provide a path to the .csproj/.fsproj via --project-path flag.");
                }
                else
                {
                    _toolInteractiveService.WriteErrorLine($"A project was not found at the path {_session.ProjectPath}");
                }

                throw new FailedToFindDeployableTargetException(ex);
            }

            var orchestrator =
                new Orchestrator.Orchestrator(
                    _session,
                    _orchestratorInteractiveService,
                    _cdkProjectHandler,
                    _awsResourceQueryer,
                    _deploymentBundleHandler,
                    new[] { RecipeLocator.FindRecipeDefinitionsPath() });

            // Determine what recommendations are possible for the project.
            var recommendations = await orchestrator.GenerateDeploymentRecommendations();

            if (recommendations.Count == 0)
            {
                _toolInteractiveService.WriteLine(string.Empty);
                _toolInteractiveService.WriteErrorLine($"The project you are trying to deploy is currently not supported.");
                throw new FailedToGenerateAnyRecommendations();
            }

            // Look to see if there are any existing deployed applications using any of the compatible recommendations.
            var existingApplications = await orchestrator.GetExistingDeployedApplications(recommendations);

            _toolInteractiveService.WriteLine(string.Empty);

            string cloudApplicationName;

            if (existingApplications.Count == 0)
            {
                var title = "Name the AWS stack to deploy your application to" + Environment.NewLine +
                            "(A stack is a collection of AWS resources that you can manage as a single unit.)" + Environment.NewLine +
                            "--------------------------------------------------------------------------------";
                cloudApplicationName =
                    _consoleUtilities.AskUserForValue(
                        title,
                        GetDefaultApplicationName(project.ProjectPath),
                        allowEmpty: false);
            }
            else
            {
                var title = "Select the AWS stack to deploy your application to" + Environment.NewLine +
                            "(A stack is a collection of AWS resources that you can manage as a single unit.)";

                var userResponse = _consoleUtilities.AskUserToChooseOrCreateNew(existingApplications.Select(x => x.Name).ToList(), title, askNewName: true, defaultNewName: GetDefaultApplicationName(project.ProjectPath));
                cloudApplicationName = userResponse.SelectedOption ?? userResponse.NewName;
            }

            var existingCloudApplication = existingApplications.FirstOrDefault(x => string.Equals(x.Name, cloudApplicationName));

            Recommendation selectedRecommendation = null;

            _toolInteractiveService.WriteLine(string.Empty);
            // If using a previous deployment preset settings for deployment based on last deployment.
            if (existingCloudApplication != null)
            {
                var existingCloudApplicationMetadata = await orchestrator.LoadCloudApplicationMetadata(existingCloudApplication.Name);

                selectedRecommendation = recommendations.FirstOrDefault(x => string.Equals(x.Recipe.Id, existingCloudApplication.RecipeId, StringComparison.InvariantCultureIgnoreCase));
                selectedRecommendation.ApplyPreviousSettings(existingCloudApplicationMetadata.Settings);

                var header = $"Loading {existingCloudApplication.Name} settings:";

                _toolInteractiveService.WriteLine(header);
                _toolInteractiveService.WriteLine(new string('-', header.Length));
                var optionSettings =
                    selectedRecommendation
                    .Recipe
                    .OptionSettings
                    .Where(x =>
                {
                    if (!selectedRecommendation.IsOptionSettingDisplayable(x))
                    {
                        return(false);
                    }

                    var value = selectedRecommendation.GetOptionSettingValue(x);
                    if (value == null || value.ToString() == string.Empty || object.Equals(value, x.DefaultValue))
                    {
                        return(false);
                    }

                    return(true);
                })
                    .ToArray();

                foreach (var setting in optionSettings)
                {
                    DisplayOptionSetting(selectedRecommendation, setting, -1, optionSettings.Length, DisplayOptionSettingsMode.Readonly);
                }
            }
            else
            {
                selectedRecommendation = _consoleUtilities.AskToChooseRecommendation(recommendations);
            }

            // Apply the user enter project name to the recommendation so that any default settings based on project name are applied.
            selectedRecommendation.OverrideProjectName(cloudApplicationName);

            var systemCapabilities = await _session.SystemCapabilities;

            if (selectedRecommendation.Recipe.DeploymentType == DeploymentTypes.CdkProject &&
                !systemCapabilities.NodeJsMinVersionInstalled)
            {
                _toolInteractiveService.WriteErrorLine("The selected deployment option requires Node.js 10.3 or later, which was not detected.  Please install Node.js: https://nodejs.org/en/download/");
                throw new MissingNodeJsException();
            }

            if (selectedRecommendation.Recipe.DeploymentBundle == DeploymentBundleTypes.Container)
            {
                if (!systemCapabilities.DockerInfo.DockerInstalled)
                {
                    _toolInteractiveService.WriteErrorLine("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/");
                    throw new MissingDockerException();
                }

                if (!systemCapabilities.DockerInfo.DockerContainerType.Equals("linux", StringComparison.OrdinalIgnoreCase))
                {
                    _toolInteractiveService.WriteErrorLine("The deployment tool requires Docker to be running in linux mode. Please switch Docker to linux mode to continue.");
                    throw new DockerContainerTypeException();
                }
            }

            var deploymentBundleDefinition = orchestrator.GetDeploymentBundleDefinition(selectedRecommendation);

            var configurableOptionSettings = selectedRecommendation.Recipe.OptionSettings.Union(deploymentBundleDefinition.Parameters);

            await ConfigureDeployment(selectedRecommendation, configurableOptionSettings, false);

            var cloudApplication = new CloudApplication
            {
                Name = cloudApplicationName
            };

            if (!ConfirmDeployment(selectedRecommendation))
            {
                return;
            }

            await CreateDeploymentBundle(orchestrator, selectedRecommendation, cloudApplication);

            await orchestrator.DeployRecommendation(cloudApplication, selectedRecommendation);
        }