in src/Amazon.ElasticBeanstalk.Tools/Commands/DeployEnvironmentCommand.cs [92:284]
protected override async Task<bool> PerformActionAsync()
{
string package = this.GetStringValueOrDefault(this.Package, EBDefinedCommandOptions.ARGUMENT_INPUT_PACKAGE, false);
string application = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.Application, EBDefinedCommandOptions.ARGUMENT_EB_APPLICATION, true);
string versionLabel = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.VersionLabel, EBDefinedCommandOptions.ARGUMENT_EB_VERSION_LABEL, false) ?? DateTime.Now.Ticks.ToString();
string environment = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.Environment, EBDefinedCommandOptions.ARGUMENT_EB_ENVIRONMENT, true);
bool doesApplicationExist = await DoesApplicationExist(application);
var environmentDescription = doesApplicationExist ? await GetEnvironmentDescription(application, environment) : null;
bool isWindowsEnvironment;
List<ConfigurationOptionSetting> existingSettings = null;
if(environmentDescription != null)
{
isWindowsEnvironment = EBUtilities.IsSolutionStackWindows(environmentDescription.SolutionStackName);
var response = await this.EBClient.DescribeConfigurationSettingsAsync(new DescribeConfigurationSettingsRequest
{
ApplicationName = environmentDescription.ApplicationName,
EnvironmentName = environmentDescription.EnvironmentName
});
if(response.ConfigurationSettings.Count != 1)
{
throw new ElasticBeanstalkExceptions($"Unknown error to retrieving settings for existing Beanstalk environment.", ElasticBeanstalkExceptions.EBCode.FailedToDescribeEnvironmentSettings);
}
existingSettings = response.ConfigurationSettings[0].OptionSettings;
}
else
{
isWindowsEnvironment = EBUtilities.IsSolutionStackWindows(this.GetSolutionStackOrDefault(this.DeployEnvironmentOptions.SolutionStack, EBDefinedCommandOptions.ARGUMENT_SOLUTION_STACK, true));
}
await CreateEBApplicationIfNotExist(application, doesApplicationExist);
string zipArchivePath = null;
if (string.IsNullOrEmpty(package))
{
this.EnsureInProjectDirectory();
var projectLocation = Utilities.DetermineProjectLocation(this.WorkingDirectory,
this.GetStringValueOrDefault(this.ProjectLocation, CommonDefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false));
string configuration = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.Configuration, CommonDefinedCommandOptions.ARGUMENT_CONFIGURATION, false) ?? "Release";
string targetFramework = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, false);
if (string.IsNullOrEmpty(targetFramework))
{
targetFramework = Utilities.LookupTargetFrameworkFromProjectFile(projectLocation, null);
if (string.IsNullOrEmpty(targetFramework))
{
targetFramework = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
}
}
var dotnetCli = new DotNetCLIWrapper(this.Logger, projectLocation);
var publishLocation = Utilities.DeterminePublishLocation(null, projectLocation, configuration, targetFramework);
this.Logger?.WriteLine("Determine publish location: " + publishLocation);
var publishOptions = GetPublishOptions(isWindowsEnvironment);
this.Logger?.WriteLine("Executing publish command");
if (dotnetCli.Publish(projectLocation, publishLocation, targetFramework, configuration, publishOptions) != 0)
{
throw new ElasticBeanstalkExceptions("Error executing \"dotnet publish\"", ElasticBeanstalkExceptions.CommonErrorCode.DotnetPublishFailed);
}
if(isWindowsEnvironment)
{
this.Logger?.WriteLine("Configuring application bundle for a Windows deployment");
EBUtilities.SetupAWSDeploymentManifest(this.Logger, this, this.DeployEnvironmentOptions, publishLocation);
}
else
{
var proxyServer = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.ProxyServer, EBDefinedCommandOptions.ARGUMENT_PROXY_SERVER, false);
if(string.IsNullOrEmpty(proxyServer))
{
proxyServer = existingSettings.FindExistingValue(OPTIONS_NAMESPACE_ENVIRONMENT_PROXY, OPTIONS_NAMESPACE_APPLICATION_ENVIRONMENT);
}
var applicationPort = this.GetIntValueOrDefault(this.DeployEnvironmentOptions.ApplicationPort, EBDefinedCommandOptions.ARGUMENT_APPLICATION_PORT, false);
if(!applicationPort.HasValue)
{
var strPort = existingSettings.FindExistingValue(OPTIONS_NAMESPACE_APPLICATION_ENVIRONMENT, OPTIONS_NAME_APPLICATION_PORT);
int intPort;
if(int.TryParse(strPort, NumberStyles.Any, CultureInfo.InvariantCulture, out intPort))
{
applicationPort = intPort;
}
}
this.Logger?.WriteLine("Configuring application bundle for a Linux deployment");
EBUtilities.SetupPackageForLinux(this.Logger, this, this.DeployEnvironmentOptions, publishLocation, proxyServer, applicationPort);
}
zipArchivePath = Path.Combine(Directory.GetParent(publishLocation).FullName, new DirectoryInfo(projectLocation).Name + "-" + DateTime.Now.Ticks + ".zip");
this.Logger?.WriteLine("Zipping up publish folder");
Utilities.ZipDirectory(this.Logger, publishLocation, zipArchivePath);
this.Logger?.WriteLine("Zip archive created: " + zipArchivePath);
}
else
{
if (!File.Exists(package))
throw new ElasticBeanstalkExceptions($"Package {package} does not exist", ElasticBeanstalkExceptions.EBCode.InvalidPackage);
if (!string.Equals(Path.GetExtension(package), ".zip", StringComparison.OrdinalIgnoreCase))
throw new ElasticBeanstalkExceptions($"Package {package} must be a zip file", ElasticBeanstalkExceptions.EBCode.InvalidPackage);
this.Logger?.WriteLine($"Skipping compilation and using precompiled package {package}");
zipArchivePath = package;
}
S3Location s3Loc;
try
{
s3Loc = await this.UploadDeploymentPackageAsync(application, versionLabel, zipArchivePath).ConfigureAwait(false);
}
catch (Exception e)
{
throw new ElasticBeanstalkExceptions("Error uploading application bundle to S3: " + e.Message, ElasticBeanstalkExceptions.EBCode.FailedToUploadBundle);
}
try
{
this.Logger?.WriteLine("Creating new application version: " + versionLabel);
await this.EBClient.CreateApplicationVersionAsync(new CreateApplicationVersionRequest
{
ApplicationName = application,
VersionLabel = versionLabel,
SourceBundle = s3Loc
}).ConfigureAwait(false);
}
catch(Exception e)
{
throw new ElasticBeanstalkExceptions("Error creating Elastic Beanstalk application version: " + e.Message, ElasticBeanstalkExceptions.EBCode.FailedCreateApplicationVersion);
}
this.Logger?.WriteLine("Getting latest environment event date before update");
var startingEventDate = await GetLatestEventDateAsync(application, environment);
string environmentArn;
if(environmentDescription != null)
{
environmentArn = await UpdateEnvironment(environmentDescription, versionLabel);
}
else
{
environmentArn = await CreateEnvironment(application, environment, versionLabel, isWindowsEnvironment);
}
bool? waitForUpdate = this.GetBoolValueOrDefault(this.DeployEnvironmentOptions.WaitForUpdate, EBDefinedCommandOptions.ARGUMENT_WAIT_FOR_UPDATE, false);
if(!waitForUpdate.HasValue || waitForUpdate.Value)
{
this.Logger?.WriteLine("Waiting for environment update to complete");
var success = await this.WaitForDeploymentCompletionAsync(application, environment, startingEventDate);
if (success)
this.Logger?.WriteLine("Update Complete");
else
throw new ElasticBeanstalkExceptions("Environment update failed", ElasticBeanstalkExceptions.EBCode.FailedEnvironmentUpdate);
}
else
{
this.Logger?.WriteLine("Environment update initiated");
}
if (environmentDescription != null)
{
var tags = ConvertToTagsCollection();
if (tags != null && tags.Count > 0)
{
var updateTagsRequest = new UpdateTagsForResourceRequest
{
ResourceArn = environmentArn,
TagsToAdd = tags
};
this.Logger?.WriteLine("Updating Tags on environment");
try
{
await this.EBClient.UpdateTagsForResourceAsync(updateTagsRequest);
}
catch(Exception e)
{
throw new ElasticBeanstalkExceptions("Error updating tags for environment: " + e.Message, ElasticBeanstalkExceptions.EBCode.FailedToUpdateTags);
}
}
}
return true;
}