public Orchestrator(
     OrchestratorSession session,
     IOrchestratorInteractiveService interactiveService,
     ICdkProjectHandler cdkProjectHandler,
     ICDKManager cdkManager,
     ICDKVersionDetector cdkVersionDetector,
     IAWSResourceQueryer awsResourceQueryer,
     IDeploymentBundleHandler deploymentBundleHandler,
     ILocalUserSettingsEngine localUserSettingsEngine,
     IDockerEngine dockerEngine,
     ICustomRecipeLocator customRecipeLocator,
     IList <string> recipeDefinitionPaths,
     IDirectoryManager directoryManager)
 {
     _session                 = session;
     _interactiveService      = interactiveService;
     _cdkProjectHandler       = cdkProjectHandler;
     _cdkManager              = cdkManager;
     _cdkVersionDetector      = cdkVersionDetector;
     _awsResourceQueryer      = awsResourceQueryer;
     _deploymentBundleHandler = deploymentBundleHandler;
     _dockerEngine            = dockerEngine;
     _customRecipeLocator     = customRecipeLocator;
     _recipeDefinitionPaths   = recipeDefinitionPaths;
     _localUserSettingsEngine = localUserSettingsEngine;
     _directoryManager        = directoryManager;
 }
        public string CreateCdkProject(Recommendation recommendation, OrchestratorSession session, string?saveCdkDirectoryPath = null)
        {
            string?assemblyName;

            if (string.IsNullOrEmpty(saveCdkDirectoryPath))
            {
                saveCdkDirectoryPath =
                    Path.Combine(
                        Constants.CDK.ProjectsDirectory,
                        Path.GetFileNameWithoutExtension(Path.GetRandomFileName()));

                assemblyName = recommendation.ProjectDefinition.AssemblyName;
            }
            else
            {
                assemblyName = _directoryManager.GetDirectoryInfo(saveCdkDirectoryPath).Name;
            }

            if (string.IsNullOrEmpty(assemblyName))
            {
                throw new ArgumentNullException("The assembly name for the CDK deployment project cannot be null");
            }

            _directoryManager.CreateDirectory(saveCdkDirectoryPath);

            var templateEngine = new TemplateEngine();

            templateEngine.GenerateCDKProjectFromTemplate(recommendation, session, saveCdkDirectoryPath, assemblyName);

            _interactiveService.LogDebugLine($"The CDK Project is saved at: {saveCdkDirectoryPath}");
            return(saveCdkDirectoryPath);
        }
        public async Task DeployCdkProject(OrchestratorSession session, string cdkProjectPath, Recommendation recommendation)
        {
            var recipeInfo           = $"{recommendation.Recipe.Id}_{recommendation.Recipe.Version}";
            var environmentVariables = new Dictionary <string, string>
            {
                { EnvironmentVariableKeys.AWS_EXECUTION_ENV, recipeInfo }
            };

            _interactiveService.LogMessageLine("Starting deployment of CDK Project");

            // Ensure region is bootstrapped
            await _commandLineWrapper.Run($"npx cdk bootstrap aws://{session.AWSAccountId}/{session.AWSRegion}",
                                          needAwsCredentials : true);

            var appSettingsFilePath = Path.Combine(cdkProjectPath, "appsettings.json");

            // Handover to CDK command line tool
            // Use a CDK Context parameter to specify the settings file that has been serialized.
            var cdkDeploy = await _commandLineWrapper.TryRunWithResult($"npx cdk deploy --require-approval never -c {Constants.CloudFormationIdentifier.SETTINGS_PATH_CDK_CONTEXT_PARAMETER}=\"{appSettingsFilePath}\"",
                                                                       workingDirectory : cdkProjectPath,
                                                                       environmentVariables : environmentVariables,
                                                                       needAwsCredentials : true,
                                                                       streamOutputToInteractiveService : true);

            if (cdkDeploy.ExitCode != 0)
            {
                throw new FailedToDeployCDKAppException("We had an issue deploying your application to AWS. Check the deployment output for more details.");
            }
        }
        public async Task <string> ConfigureCdkProject(OrchestratorSession session, CloudApplication cloudApplication, Recommendation recommendation)
        {
            string?cdkProjectPath;

            if (recommendation.Recipe.PersistedDeploymentProject)
            {
                if (string.IsNullOrEmpty(recommendation.Recipe.RecipePath))
                {
                    throw new InvalidOperationException($"{nameof(recommendation.Recipe.RecipePath)} cannot be null");
                }

                // The CDK deployment project is already saved in the same directory.
                cdkProjectPath = _directoryManager.GetDirectoryInfo(recommendation.Recipe.RecipePath).Parent.FullName;
            }
            else
            {
                // Create a new temporary CDK project for a new deployment
                _interactiveService.LogMessageLine($"Generating a {recommendation.Recipe.Name} CDK Project");
                cdkProjectPath = CreateCdkProject(recommendation, session);
            }

            // Write required configuration in appsettings.json
            var appSettingsBody     = _appSettingsBuilder.Build(cloudApplication, recommendation, session);
            var appSettingsFilePath = Path.Combine(cdkProjectPath, "appsettings.json");

            await using var appSettingsFile = new StreamWriter(appSettingsFilePath);
            await appSettingsFile.WriteAsync(appSettingsBody);

            return(cdkProjectPath);
        }
        public string Build(CloudApplication cloudApplication, Recommendation recommendation, OrchestratorSession session)
        {
            var projectPath = new FileInfo(recommendation.ProjectPath).Directory?.FullName;

            if (string.IsNullOrEmpty(projectPath))
            {
                throw new InvalidProjectPathException("The project path provided is invalid.");
            }

            // General Settings
            var appSettingsContainer = new RecipeProps <Dictionary <string, object> >(
                cloudApplication.StackName,
                projectPath,
                recommendation.Recipe.Id,
                recommendation.Recipe.Version,
                session.AWSAccountId,
                session.AWSRegion,
                new ()
                )
            {
                ECRRepositoryName            = recommendation.DeploymentBundle.ECRRepositoryName ?? "",
                ECRImageTag                  = recommendation.DeploymentBundle.ECRImageTag ?? "",
                DotnetPublishZipPath         = recommendation.DeploymentBundle.DotnetPublishZipPath ?? "",
                DotnetPublishOutputDirectory = recommendation.DeploymentBundle.DotnetPublishOutputDirectory ?? ""
            };

            // Option Settings
            foreach (var optionSetting in recommendation.Recipe.OptionSettings)
            {
                var optionSettingValue = recommendation.GetOptionSettingValue(optionSetting);

                if (optionSettingValue != null)
                {
                    appSettingsContainer.Settings[optionSetting.Id] = optionSettingValue;
                }
            }

            return(JsonConvert.SerializeObject(appSettingsContainer, Formatting.Indented));
        }
    }
 public Orchestrator(OrchestratorSession session, IList <string> recipeDefinitionPaths)
 {
     _session = session;
     _recipeDefinitionPaths = recipeDefinitionPaths;
 }