Exemplo n.º 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));
        }
        protected virtual void BuildProject(string projectLocation, string configuration, string targetFramework, string publishOptions, string publishLocation)
        {
            this.EnsureInProjectDirectory();

            var dotnetCli = new DotNetCLIWrapper(this.Logger, projectLocation);

            this.Logger?.WriteLine("Executing publish command");
            if (dotnetCli.Publish(projectLocation, publishLocation, targetFramework, configuration, publishOptions) != 0)
            {
                throw new ToolsException("Error executing \"dotnet publish\"", ToolsException.CommonErrorCode.DotnetPublishFailed);
            }
        }
Exemplo n.º 3
0
        public override async Task <bool> ExecuteAsync()
        {
            try
            {
                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);
                    if (string.IsNullOrEmpty(targetFramework))
                    {
                        targetFramework = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
                    }
                }

                string application  = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.Application, EBDefinedCommandOptions.ARGUMENT_EB_APPLICATION, true);
                string environment  = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.Environment, EBDefinedCommandOptions.ARGUMENT_EB_ENVIRONMENT, true);
                string versionLabel = this.GetStringValueOrDefault(this.DeployEnvironmentOptions.VersionLabel, EBDefinedCommandOptions.ARGUMENT_EB_VERSION_LABEL, false) ?? DateTime.Now.Ticks.ToString();

                bool doesApplicationExist = await DoesApplicationExist(application);

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

                if (!doesApplicationExist)
                {
                    try
                    {
                        this.Logger?.WriteLine("Creating new Elastic Beanstalk Application");
                        await this.EBClient.CreateApplicationAsync(new CreateApplicationRequest
                        {
                            ApplicationName = application
                        });
                    }
                    catch (Exception e)
                    {
                        throw new ElasticBeanstalkExceptions("Error creating Elastic Beanstalk application: " + e.Message, ElasticBeanstalkExceptions.EBCode.FailedCreateApplication);
                    }
                }



                var dotnetCli = new DotNetCLIWrapper(this.Logger, projectLocation);

                var publishLocation = Utilities.DeterminePublishLocation(projectLocation, configuration, targetFramework);
                this.Logger?.WriteLine("Determine publish location: " + publishLocation);


                this.Logger?.WriteLine("Executing publish command");
                if (dotnetCli.Publish(projectLocation, publishLocation, targetFramework, configuration) != 0)
                {
                    throw new ElasticBeanstalkExceptions("Error executing \"dotnet publish\"", ElasticBeanstalkExceptions.CommonErrorCode.DotnetPublishFailed);
                }

                SetupAWSDeploymentManifest(publishLocation);

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

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

                if (this.GetBoolValueOrDefault(this.PersistConfigFile, CommonDefinedCommandOptions.ARGUMENT_PERSIST_CONFIG_FILE, false).GetValueOrDefault())
                {
                    this.SaveConfigFile();
                }
            }
            catch (ToolsException e)
            {
                this.Logger?.WriteLine(e.Message);
                this.LastToolsException = e;
                return(false);
            }
            catch (Exception e)
            {
                this.Logger?.WriteLine($"Unknown error deploying application to Elastic Beanstalk: {e.Message}");
                this.Logger?.WriteLine(e.StackTrace);
                return(false);
            }
            return(true);
        }
        private async Task <CreateLayerZipFileResult> CreateRuntimePackageStoreLayerZipFile(string layerName, string s3Prefix)
        {
            var targetFramework    = this.GetStringValueOrDefault(this.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
            var projectLocation    = this.GetStringValueOrDefault(this.ProjectLocation, CommonDefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);
            var enableOptimization = this.GetBoolValueOrDefault(this.EnablePackageOptimization, LambdaDefinedCommandOptions.ARGUMENT_ENABLE_PACKAGE_OPTIMIZATION, false).GetValueOrDefault();

            if (string.Equals(targetFramework, "netcoreapp3.1"))
            {
                var version = DotNetCLIWrapper.GetSdkVersion();

                // .NET SDK 3.1 versions less then 3.1.400 have an issue throwing NullReferenceExceptions when pruning packages out with the manifest.
                // https://github.com/dotnet/sdk/issues/10973
                if (version < Version.Parse("3.1.400"))
                {
                    var message = $"Publishing runtime package store layers targeting .NET Core 3.1 requires at least version 3.1.400 of the .NET SDK. Current version installed is {version}.";
                    throw new LambdaToolsException(message, LambdaToolsException.LambdaErrorCode.DisabledSupportForNET31Layers);
                }
            }

#if NETCORE
            if (enableOptimization)
            {
                if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    throw new LambdaToolsException($"Package optimization is only possible on Amazon Linux. To use this feature execute the command in an Amazon Linux environment.", LambdaToolsException.LambdaErrorCode.UnsupportedOptimizationPlatform);
                }
                else
                {
                    this.Logger.WriteLine("Warning: Package optimization has been enabled. Be sure to run this on an Amazon Linux environment or the optimization might not be compatbile with the Lambda runtime.");
                }
            }
#else
            // This is the case the code is run in the AWS Toolkit for Visual Studio which will never run on Amazon Linux.
            enableOptimization = false;
#endif

            // This is the manifest that list the NuGet packages via <PackageReference> elements in the msbuild project file.
            var packageManifest = this.GetStringValueOrDefault(this.PackageManifest, LambdaDefinedCommandOptions.ARGUMENT_PACKAGE_MANIFEST, false);
            // If this is null attempt to use the current directory. This is likely if the intent is to make a
            // layer from the current Lambda project.
            if (string.IsNullOrEmpty(packageManifest))
            {
                packageManifest = Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation);
            }

            // If this is a directory look to see if there is a single csproj of fsproj in the directory in use that.
            // This is to make it easy to make a layer in the current directory of a Lambda function.
            if (Directory.Exists(packageManifest))
            {
                var files = Directory.GetFiles(packageManifest, "*.csproj");
                if (files.Length == 1)
                {
                    packageManifest = Path.Combine(packageManifest, files[0]);
                }
                else if (files.Length == 0)
                {
                    files = Directory.GetFiles(packageManifest, "*.fsproj");
                    if (files.Length == 1)
                    {
                        packageManifest = Path.Combine(packageManifest, files[0]);
                    }
                }
            }

            if (!File.Exists(packageManifest))
            {
                throw new LambdaToolsException($"Can not find package manifest {packageManifest}. Make sure to point to a file not a directory.", LambdaToolsException.LambdaErrorCode.LayerPackageManifestNotFound);
            }

            // Create second subdirectory so that when the directory is zipped the sub directory is retained in the zip file.
            // The sub directory will be created in the /opt directory in the Lambda environment.
            var tempDirectoryName = $"{layerName}-{DateTime.UtcNow.Ticks}".ToLower();
            var optDirectory      = this.GetStringValueOrDefault(this.OptDirectory, LambdaDefinedCommandOptions.ARGUMENT_OPT_DIRECTORY, false);
            if (string.IsNullOrEmpty(optDirectory))
            {
                optDirectory = LambdaConstants.DEFAULT_LAYER_OPT_DIRECTORY;
            }
            var tempRootPath         = Path.Combine(Path.GetTempPath(), tempDirectoryName);
            var storeOutputDirectory = Path.Combine(tempRootPath, optDirectory);

            {
                var convertResult = LambdaUtilities.ConvertManifestToSdkManifest(targetFramework, packageManifest);
                if (convertResult.ShouldDelete)
                {
                    this.Logger?.WriteLine("Converted ASP.NET Core project file to temporary package manifest file.");
                }
                var architecture = this.GetStringValueOrDefault(this.Architecture, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_ARCHITECTURE, false);
                var cliWrapper   = new LambdaDotNetCLIWrapper(this.Logger, this.WorkingDirectory);
                if (cliWrapper.Store(defaults: this.DefaultConfig,
                                     projectLocation: projectLocation,
                                     outputLocation: storeOutputDirectory,
                                     targetFramework: targetFramework,
                                     packageManifest: convertResult.PackageManifest,
                                     architecture: architecture,
                                     enableOptimization: enableOptimization) != 0)
                {
                    throw new LambdaToolsException($"Error executing the 'dotnet store' command", LambdaToolsException.LambdaErrorCode.StoreCommandError);
                }

                if (convertResult.ShouldDelete)
                {
                    File.Delete(convertResult.PackageManifest);
                }
            }

            // The artifact.xml file is generated by the "dotnet store" command that lists the packages that were added to the store.
            // It is required during a "dotnet publish" so the NuGet packages in the store will be filtered out.
            var artifactXmlPath = Path.Combine(storeOutputDirectory, "x64", targetFramework, "artifact.xml");
            if (!File.Exists(artifactXmlPath))
            {
                throw new LambdaToolsException($"Failed to find artifact.xml file in created local store.", LambdaToolsException.LambdaErrorCode.FailedToFindArtifactZip);
            }
            this.Logger.WriteLine($"Uploading runtime package store manifest to S3");
            var s3Key = await UploadFile(artifactXmlPath, $"{s3Prefix}artifact.xml");

            this.Logger.WriteLine($"Create zip file of runtime package store directory");
            var zipPath = Path.Combine(Path.GetTempPath(), $"{layerName}-{DateTime.UtcNow.Ticks}.zip");
            if (File.Exists(zipPath))
            {
                File.Delete(zipPath);
            }
            LambdaPackager.BundleDirectory(zipPath, tempRootPath, false, this.Logger);

            var result = new CreateLayerZipFileResult
            {
                ZipFile        = zipPath,
                LayerDirectory = optDirectory
            };

            var s3Bucket = this.GetStringValueOrDefault(this.S3Bucket, LambdaDefinedCommandOptions.ARGUMENT_S3_BUCKET, true);

            // Set the description field to the our JSON layer manifest file so when the tooling is used
            // to create a package of a Lambda function in the future the artifact.xml file can be used during "dotnet publish".
            result.Description = GeneratorRuntimePackageManifestLayerDescription(optDirectory, s3Bucket, s3Key, enableOptimization);

            var compatibleRuntime = LambdaUtilities.DetermineLambdaRuntimeFromTargetFramework(targetFramework);
            if (!string.IsNullOrEmpty(compatibleRuntime))
            {
                result.CompatibleRuntimes = new List <string>()
                {
                    compatibleRuntime
                };
            }

            return(result);
        }
        public override async Task <bool> ExecuteAsync()
        {
            try
            {
                string configuration   = this.GetStringValueOrDefault(this.PushDockerImageProperties.Configuration, CommonDefinedCommandOptions.ARGUMENT_CONFIGURATION, false) ?? "Release";
                string targetFramework = this.GetStringValueOrDefault(this.PushDockerImageProperties.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, false);
                this.PushDockerImageProperties.DockerImageTag = this.GetStringValueOrDefault(this.PushDockerImageProperties.DockerImageTag, ECSDefinedCommandOptions.ARGUMENT_DOCKER_TAG, true).ToLower();

                if (!this.PushDockerImageProperties.DockerImageTag.Contains(":"))
                {
                    this.PushDockerImageProperties.DockerImageTag += ":latest";
                }

                var projectLocation = Utilities.DetermineProjectLocation(this.WorkingDirectory, this.ProjectLocation);
                var dockerDetails   = InspectDockerFile(projectLocation);


                if (!dockerDetails.SkipDotnetBuild)
                {
                    var dotnetCli = new DotNetCLIWrapper(this.Logger, projectLocation);
                    this.Logger?.WriteLine("Executing publish command");
                    if (dotnetCli.Publish(projectLocation, dockerDetails.ExpectedPublishLocation, targetFramework, configuration) != 0)
                    {
                        throw new DockerToolsException("Error executing \"dotnet publish\"", DockerToolsException.CommonErrorCode.DotnetPublishFailed);
                    }
                }

                var dockerCli = new DockerCLIWrapper(this.Logger, projectLocation);
                this.Logger?.WriteLine("Executing docker build");

                string dockerBuildWorkingDirectory = dockerDetails.BuildFromSolutionDirectory ? DetermineSolutionDirectory(projectLocation) : projectLocation;

                if (dockerCli.Build(this.DefaultConfig, dockerBuildWorkingDirectory, Path.Combine(projectLocation, "Dockerfile"), this.PushDockerImageProperties.DockerImageTag) != 0)
                {
                    throw new DockerToolsException("Error executing \"docker build\"", DockerToolsException.ECSErrorCode.DockerBuildFailed);
                }

                await InitiateDockerLogin(dockerCli);

                Repository repository = await SetupECRRepository(this.PushDockerImageProperties.DockerImageTag.Substring(0, this.PushDockerImageProperties.DockerImageTag.IndexOf(':')));

                var targetTag = repository.RepositoryUri + this.PushDockerImageProperties.DockerImageTag.Substring(this.PushDockerImageProperties.DockerImageTag.IndexOf(':'));
                this.Logger?.WriteLine($"Taging image {this.PushDockerImageProperties.DockerImageTag} with {targetTag}");
                if (dockerCli.Tag(this.PushDockerImageProperties.DockerImageTag, targetTag) != 0)
                {
                    throw new DockerToolsException("Error executing \"docker tag\"", DockerToolsException.ECSErrorCode.DockerTagFail);
                }

                this.Logger?.WriteLine("Pushing image to ECR repository");
                if (dockerCli.Push(targetTag) != 0)
                {
                    throw new DockerToolsException("Error executing \"docker push\"", DockerToolsException.ECSErrorCode.DockerPushFail);
                }

                this.PushedImageUri = targetTag;
                this.Logger?.WriteLine($"Image {this.PushedImageUri} Push Complete. ");

                if (this.GetBoolValueOrDefault(this.PersistConfigFile, CommonDefinedCommandOptions.ARGUMENT_PERSIST_CONFIG_FILE, false).GetValueOrDefault())
                {
                    this.SaveConfigFile();
                }
            }
            catch (DockerToolsException e)
            {
                this.Logger?.WriteLine(e.Message);
                this.LastToolsException = e;
                return(false);
            }
            catch (Exception e)
            {
                this.Logger?.WriteLine($"Unknown error executing docker push to Amazon Elastic Container Registry: {e.Message}");
                this.Logger?.WriteLine(e.StackTrace);
                return(false);
            }
            return(true);
        }
        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);
        }
Exemplo n.º 7
0
        protected override async Task <bool> PerformActionAsync()
        {
            var    configuration   = this.GetStringValueOrDefault(this.PushDockerImageProperties.Configuration, CommonDefinedCommandOptions.ARGUMENT_CONFIGURATION, false) ?? "Release";
            var    targetFramework = this.GetStringValueOrDefault(this.PushDockerImageProperties.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, false);
            string publishOptions  = this.GetStringValueOrDefault(this.PushDockerImageProperties.PublishOptions, CommonDefinedCommandOptions.ARGUMENT_PUBLISH_OPTIONS, false);

            this.PushDockerImageProperties.DockerImageTag = this.GetStringValueOrDefault(this.PushDockerImageProperties.DockerImageTag, ECSDefinedCommandOptions.ARGUMENT_DOCKER_TAG, true).ToLower();

            if (!this.PushDockerImageProperties.DockerImageTag.Contains(":"))
            {
                this.PushDockerImageProperties.DockerImageTag += ":latest";
            }

            var projectLocation = Utilities.DetermineProjectLocation(this.WorkingDirectory, this.ProjectLocation);
            var dockerDetails   = InspectDockerFile(this.Logger, projectLocation);


            if (!dockerDetails.SkipDotnetBuild)
            {
                this.EnsureInProjectDirectory();

                var dotnetCli = new DotNetCLIWrapper(this.Logger, projectLocation);
                this.Logger?.WriteLine("Executing publish command");
                if (dotnetCli.Publish(projectLocation, dockerDetails.ExpectedPublishLocation, targetFramework, configuration, publishOptions) != 0)
                {
                    throw new DockerToolsException("Error executing \"dotnet publish\"", DockerToolsException.CommonErrorCode.DotnetPublishFailed);
                }
            }

            var dockerCli = new DockerCLIWrapper(this.Logger, projectLocation);

            this.Logger?.WriteLine("Executing docker build");

            var dockerBuildWorkingDirectory = this.GetStringValueOrDefault(this.PushDockerImageProperties.DockerBuildWorkingDirectory, ECSDefinedCommandOptions.ARGUMENT_DOCKER_BUILD_WORKING_DIRECTORY, false);

            if (string.IsNullOrEmpty(dockerBuildWorkingDirectory))
            {
                dockerBuildWorkingDirectory = dockerDetails.BuildFromSolutionDirectory ? DetermineSolutionDirectory(projectLocation) : projectLocation;
            }
            else
            {
                if (!Path.IsPathRooted(dockerBuildWorkingDirectory))
                {
                    dockerBuildWorkingDirectory = Path.GetFullPath(Path.Combine(projectLocation, dockerBuildWorkingDirectory));
                }

                this.PushDockerImageProperties.DockerBuildWorkingDirectory = Utilities.RelativePathTo(projectLocation, dockerBuildWorkingDirectory);
            }

            var dockerBuildOptions = this.GetStringValueOrDefault(this.PushDockerImageProperties.DockerBuildOptions, ECSDefinedCommandOptions.ARGUMENT_DOCKER_BUILD_OPTIONS, false);

            if (dockerCli.Build(this.DefaultConfig, dockerBuildWorkingDirectory, Path.Combine(projectLocation, "Dockerfile"), this.PushDockerImageProperties.DockerImageTag, dockerBuildOptions) != 0)
            {
                throw new DockerToolsException("Error executing \"docker build\"", DockerToolsException.ECSErrorCode.DockerBuildFailed);
            }

            await InitiateDockerLogin(dockerCli);

            Repository repository = await SetupECRRepository(this.PushDockerImageProperties.DockerImageTag.Substring(0, this.PushDockerImageProperties.DockerImageTag.IndexOf(':')));

            var targetTag = repository.RepositoryUri + this.PushDockerImageProperties.DockerImageTag.Substring(this.PushDockerImageProperties.DockerImageTag.IndexOf(':'));

            this.Logger?.WriteLine($"Taging image {this.PushDockerImageProperties.DockerImageTag} with {targetTag}");
            if (dockerCli.Tag(this.PushDockerImageProperties.DockerImageTag, targetTag) != 0)
            {
                throw new DockerToolsException("Error executing \"docker tag\"", DockerToolsException.ECSErrorCode.DockerTagFail);
            }

            this.Logger?.WriteLine("Pushing image to ECR repository");
            if (dockerCli.Push(targetTag) != 0)
            {
                throw new DockerToolsException("Error executing \"docker push\"", DockerToolsException.ECSErrorCode.DockerPushFail);
            }

            this.PushedImageUri = targetTag;
            this.Logger?.WriteLine($"Image {this.PushedImageUri} Push Complete. ");

            return(true);
        }
        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);
        }