예제 #1
0
        protected override Task <bool> PerformActionAsync()
        {
            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);
            string publishOptions  = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.PublishOptions, CommonDefinedCommandOptions.ARGUMENT_PUBLISH_OPTIONS, false);

            if (string.IsNullOrEmpty(targetFramework))
            {
                targetFramework = Utilities.LookupTargetFrameworkFromProjectFile(projectLocation);
                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);


            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);
            }

            EBUtilities.SetupAWSDeploymentManifest(this.Logger, this, this.DeployEnvironmentOptions, publishLocation);

            string package        = this.GetStringValueOrDefault(this.OutputPackageFileName, EBDefinedCommandOptions.ARGUMENT_OUTPUT_PACKAGE, false);
            string zipArchivePath = null;

            if (!string.IsNullOrWhiteSpace(package))
            {
                zipArchivePath = package;
            }
            else
            {
                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);

            return(Task.FromResult(true));
        }
        private void DetermineEnvironment(out string environmentType, out string loadBalancerType)
        {
            environmentType  = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.EnvironmentType, EBDefinedCommandOptions.ARGUMENT_ENVIRONMENT_TYPE, false);
            loadBalancerType = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.LoadBalancerType, EBDefinedCommandOptions.ARGUMENT_LOADBALANCER_TYPE, false);

            if (string.IsNullOrWhiteSpace(environmentType))
            {
                environmentType = string.IsNullOrWhiteSpace(loadBalancerType) ? EBConstants.ENVIRONMENT_TYPE_SINGLEINSTANCE : EBConstants.ENVIRONMENT_TYPE_LOADBALANCED;
            }

            if (string.IsNullOrWhiteSpace(loadBalancerType) && EBUtilities.IsLoadBalancedEnvironmentType(environmentType))
            {
                loadBalancerType = EBConstants.LOADBALANCER_TYPE_APPLICATION;
            }
        }
        public async Task <IList <string> > FindSolutionStacksAsync()
        {
            var solutionStacks = new List <string>();

            var allSolutionStacks = (await this.EBClient.ListAvailableSolutionStacksAsync()).SolutionStacks;

            foreach (var stack in allSolutionStacks.OrderByDescending(x => x))
            {
                if (EBUtilities.IsSolutionStackWindows(stack) || EBUtilities.IsSolutionStackLinuxNETCore(stack))
                {
                    solutionStacks.Add(stack);
                }
            }

            return(FilterSolutionStackToLatestVersion(solutionStacks));
        }
        private async Task <string> UpdateEnvironment(EnvironmentDescription environmentDescription, string versionLabel)
        {
            this.Logger?.WriteLine("Updating environment {0} to new application version", environmentDescription.EnvironmentName);
            var updateRequest = new UpdateEnvironmentRequest
            {
                ApplicationName = environmentDescription.ApplicationName,
                EnvironmentName = environmentDescription.EnvironmentName,
                VersionLabel    = versionLabel
            };

            AddAdditionalOptions(updateRequest.OptionSettings, false, EBUtilities.IsSolutionStackWindows(environmentDescription.SolutionStackName));

            try
            {
                var updateEnvironmentResponse = await this.EBClient.UpdateEnvironmentAsync(updateRequest);

                return(updateEnvironmentResponse.EnvironmentArn);
            }
            catch (Exception e)
            {
                throw new ElasticBeanstalkExceptions("Error updating environment: " + e.Message, ElasticBeanstalkExceptions.EBCode.FailedToUpdateEnvironment);
            }
        }
예제 #5
0
 public void IsSelfContainedPublishTest(string filename, bool isSelfContained)
 {
     Assert.Equal(EBUtilities.IsSelfContainedPublish(filename), isSelfContained);
 }
        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);
                string publishOptions  = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.PublishOptions, CommonDefinedCommandOptions.ARGUMENT_PUBLISH_OPTIONS, false);

                if (string.IsNullOrEmpty(targetFramework))
                {
                    targetFramework = Utilities.LookupTargetFrameworkFromProjectFile(projectLocation);
                    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);

                if (!isWindowsEnvironment)
                {
                    if (publishOptions == null || !publishOptions.Contains("-r ") && !publishOptions.Contains("--runtime "))
                    {
                        publishOptions += " --runtime linux-x64";
                    }
                    if (publishOptions == null || !publishOptions.Contains("--self-contained"))
                    {
                        var selfContained = this.GetBoolValueOrDefault(this.DeployEnvironmentOptions.SelfContained, CommonDefinedCommandOptions.ARGUMENT_SELF_CONTAINED, false);
                        publishOptions += $" --self-contained {selfContained.GetValueOrDefault().ToString(CultureInfo.InvariantCulture).ToLowerInvariant()}";
                    }
                }

                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);
        }
        private void AddAdditionalOptions(IList <ConfigurationOptionSetting> settings, bool createEnvironmentMode, bool isWindowsEnvironment)
        {
            var additionalOptions = this.GetKeyValuePairOrDefault(this.DeployEnvironmentOptions.AdditionalOptions, EBDefinedCommandOptions.ARGUMENT_EB_ADDITIONAL_OPTIONS, false);

            if (additionalOptions != null && additionalOptions.Count > 0)
            {
                foreach (var kvp in additionalOptions)
                {
                    var tokens = kvp.Key.Split(',');
                    if (tokens.Length != 2)
                    {
                        throw new ToolsException("Additional option \"" + kvp.Key + "=" + kvp.Value + "\" in incorrect format. Format should be <option-namespace>,<option-name>=<option-value>.", ToolsException.CommonErrorCode.DefaultsParseFail);
                    }

                    settings.Add(new ConfigurationOptionSetting
                    {
                        Namespace  = tokens[0],
                        OptionName = tokens[1],
                        Value      = kvp.Value
                    });
                }
            }

            var enableXRay = this.GetBoolValueOrDefault(this.DeployEnvironmentOptions.EnableXRay, EBDefinedCommandOptions.ARGUMENT_ENABLE_XRAY, false);

            if (enableXRay.HasValue)
            {
                settings.Add(new ConfigurationOptionSetting()
                {
                    Namespace  = "aws:elasticbeanstalk:xray",
                    OptionName = "XRayEnabled",
                    Value      = enableXRay.Value.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()
                });

                this.Logger?.WriteLine($"Enable AWS X-Ray: {enableXRay.Value}");
            }

            var enhancedHealthType = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.EnhancedHealthType, EBDefinedCommandOptions.ARGUMENT_ENHANCED_HEALTH_TYPE, false);

            if (!string.IsNullOrWhiteSpace(enhancedHealthType))
            {
                if (!EBConstants.ValidEnhanceHealthType.Contains(enhancedHealthType))
                {
                    throw new ElasticBeanstalkExceptions($"The enhanced value type {enhancedHealthType} is invalid. Valid values are: {string.Join(", ", EBConstants.ValidEnhanceHealthType)}", ElasticBeanstalkExceptions.EBCode.InvalidEnhancedHealthType);
                }

                settings.Add(new ConfigurationOptionSetting()
                {
                    Namespace  = "aws:elasticbeanstalk:healthreporting:system",
                    OptionName = "SystemType",
                    Value      = enhancedHealthType
                });
            }

            string environmentType, loadBalancerType;

            DetermineEnvironment(out environmentType, out loadBalancerType);
            var healthCheckURL = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.HealthCheckUrl, EBDefinedCommandOptions.ARGUMENT_HEALTH_CHECK_URL, false);

            // If creating a new load balanced environment then a heath check url must be set.
            if (createEnvironmentMode && string.IsNullOrEmpty(healthCheckURL) && EBUtilities.IsLoadBalancedEnvironmentType(environmentType))
            {
                healthCheckURL = "/";
            }

            if (!string.IsNullOrEmpty(healthCheckURL))
            {
                settings.Add(new ConfigurationOptionSetting()
                {
                    Namespace  = "aws:elasticbeanstalk:application",
                    OptionName = "Application Healthcheck URL",
                    Value      = healthCheckURL
                });

                if (EBUtilities.IsLoadBalancedEnvironmentType(environmentType) && string.Equals(loadBalancerType, EBConstants.LOADBALANCER_TYPE_APPLICATION))
                {
                    settings.Add(new ConfigurationOptionSetting()
                    {
                        Namespace  = "aws:elasticbeanstalk:environment:process:default",
                        OptionName = "HealthCheckPath",
                        Value      = healthCheckURL
                    });
                }
            }

            if (!isWindowsEnvironment)
            {
                var proxyServer = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.ProxyServer, EBDefinedCommandOptions.ARGUMENT_PROXY_SERVER, false);
                if (!string.IsNullOrEmpty(proxyServer))
                {
                    if (!EBConstants.ValidProxyServer.Contains(proxyServer))
                    {
                        throw new ElasticBeanstalkExceptions($"The proxy server {proxyServer} is invalid. Valid values are: {string.Join(", ", EBConstants.ValidProxyServer)}", ElasticBeanstalkExceptions.EBCode.InvalidProxyServer);
                    }

                    Logger?.WriteLine($"Configuring reverse proxy to {proxyServer}");
                    settings.Add(new ConfigurationOptionSetting()
                    {
                        Namespace  = OPTIONS_NAMESPACE_ENVIRONMENT_PROXY,
                        OptionName = OPTIONS_NAME_PROXY_SERVER,
                        Value      = proxyServer
                    });
                }

                var applicationPort = this.GetIntValueOrDefault(this.DeployEnvironmentOptions.ApplicationPort, EBDefinedCommandOptions.ARGUMENT_APPLICATION_PORT, false);
                if (applicationPort.HasValue)
                {
                    Logger?.WriteLine($"Application port to {applicationPort}");
                    settings.Add(new ConfigurationOptionSetting()
                    {
                        Namespace  = OPTIONS_NAMESPACE_APPLICATION_ENVIRONMENT,
                        OptionName = OPTIONS_NAME_APPLICATION_PORT,
                        Value      = applicationPort.Value.ToString(CultureInfo.InvariantCulture)
                    });
                }
            }

            var enableStickySessions = this.GetBoolValueOrDefault(this.DeployEnvironmentOptions.EnableStickySessions, EBDefinedCommandOptions.ARGUMENT_ENABLE_STICKY_SESSIONS, false);

            if (enableStickySessions.HasValue)
            {
                if (enableStickySessions.Value)
                {
                    Logger?.WriteLine($"Enabling sticky sessions");
                }

                settings.Add(new ConfigurationOptionSetting()
                {
                    Namespace  = "aws:elasticbeanstalk:environment:process:default",
                    OptionName = "StickinessEnabled",
                    Value      = enableStickySessions.Value.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()
                });
            }
        }
        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);

            bool doesEnvironmentExist = doesApplicationExist ? await DoesEnvironmentExist(application, environment) : false;

            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);
                string publishOptions  = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.PublishOptions, CommonDefinedCommandOptions.ARGUMENT_PUBLISH_OPTIONS, false);

                if (string.IsNullOrEmpty(targetFramework))
                {
                    targetFramework = Utilities.LookupTargetFrameworkFromProjectFile(projectLocation);
                    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);


                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);
                }

                EBUtilities.SetupAWSDeploymentManifest(this.Logger, this, this.DeployEnvironmentOptions, publishLocation);

                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 (doesEnvironmentExist)
            {
                environmentArn = await UpdateEnvironment(application, environment, versionLabel);
            }
            else
            {
                environmentArn = await CreateEnvironment(application, environment, versionLabel);
            }

            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 (doesEnvironmentExist)
            {
                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);
        }