in src/AWS.Deploy.CLI/Commands/DeployCommand.cs [173:281]
public async Task<(Orchestrator, Recommendation, CloudApplication)> InitializeDeployment(string cloudApplicationName, DeploymentSettings? deploymentSettings, string deploymentProjectPath)
{
var orchestrator = new Orchestrator(
_session,
_orchestratorInteractiveService,
_cdkProjectHandler,
_cdkManager,
_cdkVersionDetector,
_awsResourceQueryer,
_deploymentBundleHandler,
_localUserSettingsEngine,
_dockerEngine,
_recipeHandler,
_fileManager,
_directoryManager,
_awsServiceHandler,
_optionSettingHandler,
_deployToolWorkspaceMetadata);
// Determine what recommendations are possible for the project.
var recommendations = await GenerateDeploymentRecommendations(orchestrator, deploymentProjectPath);
// Get all existing applications that were previously deployed using our deploy tool.
var allDeployedApplications = await _deployedApplicationQueryer.GetExistingDeployedApplications(recommendations.Select(x => x.Recipe.DeploymentType).ToList());
// Filter compatible applications that can be re-deployed using the current set of recommendations.
var compatibleApplications = await _deployedApplicationQueryer.GetCompatibleApplications(recommendations, allDeployedApplications, _session);
if (string.IsNullOrEmpty(cloudApplicationName))
// Try finding the CloudApplication name via the user provided config settings.
cloudApplicationName = deploymentSettings?.ApplicationName ?? string.Empty;
// Prompt the user with a choice to re-deploy to existing targets or deploy to a new cloud application.
// This prompt is NOT needed if the user is just pushing the docker image to ECR.
if (string.IsNullOrEmpty(cloudApplicationName) && !string.Equals(deploymentSettings?.RecipeId, Constants.RecipeIdentifier.PUSH_TO_ECR_RECIPE_ID))
cloudApplicationName = AskForCloudApplicationNameFromDeployedApplications(compatibleApplications);
// Find existing application with the same CloudApplication name.
CloudApplication? deployedApplication = null;
if (!string.IsNullOrEmpty(deploymentSettings?.RecipeId))
{
// if the recommendation is specified via a config file then find the deployed application by matching the deployment type along with the cloudApplicationName
var recommendation = recommendations.FirstOrDefault(x => string.Equals(x.Recipe.Id, deploymentSettings.RecipeId));
if (recommendation == null)
{
var errorMsg = "The recipe ID specified in the deployment settings file does not match any compatible deployment recipes.";
throw new InvalidDeploymentSettingsException(DeployToolErrorCode.DeploymentConfigurationNeedsAdjusting, errorMsg);
}
deployedApplication = allDeployedApplications.FirstOrDefault(x => string.Equals(x.Name, cloudApplicationName) && x.DeploymentType == recommendation.Recipe.DeploymentType);
}
else
{
deployedApplication = allDeployedApplications.FirstOrDefault(x => string.Equals(x.Name, cloudApplicationName));
}
Recommendation? selectedRecommendation = null;
if (deployedApplication != null)
{
// Verify that the target application can be deployed using the current set of recommendations
if (!compatibleApplications.Any(app => app.Name.Equals(deployedApplication.Name, StringComparison.Ordinal)))
{
var errorMessage = $"{deployedApplication.Name} already exists as a {deployedApplication.ResourceType} but a compatible recommendation to perform a redeployment was not found";
throw new FailedToFindCompatibleRecipeException(DeployToolErrorCode.CompatibleRecommendationForRedeploymentNotFound, errorMessage);
}
// preset settings for deployment based on last deployment.
selectedRecommendation = await GetSelectedRecommendationFromPreviousDeployment(orchestrator, recommendations, deployedApplication, deploymentSettings, deploymentProjectPath);
}
else
{
if (!string.IsNullOrEmpty(deploymentProjectPath))
{
selectedRecommendation = recommendations.First();
}
else
{
// Filter the recommendation list for a NEW deployment with recipes which have the DisableNewDeployments property set to false.
selectedRecommendation = GetSelectedRecommendation(deploymentSettings, recommendations.Where(x => !x.Recipe.DisableNewDeployments).ToList());
}
// Ask the user for a new Cloud Application name based on the deployment type of the recipe.
if (string.IsNullOrEmpty(cloudApplicationName))
{
// Don't prompt for a new name if a user just wants to push images to ECR
// The ECR repository name is already configurable as part of the recipe option settings.
if (selectedRecommendation.Recipe.DeploymentType == DeploymentTypes.ElasticContainerRegistryImage)
{
cloudApplicationName = _cloudApplicationNameGenerator.GenerateValidName(_session.ProjectDefinition, compatibleApplications, selectedRecommendation.Recipe.DeploymentType);
}
else
{
cloudApplicationName = AskForNewCloudApplicationName(selectedRecommendation.Recipe.DeploymentType, compatibleApplications);
}
}
// cloudApplication name was already provided via CLI args or the deployment config file
else
{
var validationResult = _cloudApplicationNameGenerator.IsValidName(cloudApplicationName, allDeployedApplications, selectedRecommendation.Recipe.DeploymentType);
if (!validationResult.IsValid)
throw new InvalidCloudApplicationNameException(DeployToolErrorCode.InvalidCloudApplicationName, validationResult.ErrorMessage);
}
}
await orchestrator.ApplyAllReplacementTokens(selectedRecommendation, cloudApplicationName);
var cloudApplication = new CloudApplication(cloudApplicationName, deployedApplication?.UniqueIdentifier ?? string.Empty, orchestrator.GetCloudApplicationResourceType(selectedRecommendation.Recipe.DeploymentType), selectedRecommendation.Recipe.Id);
return (orchestrator, selectedRecommendation, cloudApplication);
}