private async Task PushToECR(DockerCLIWrapper dockerCli, string sourceDockerImageTag, string destinationDockerImageTag)
        {
            var sourceRepoInfo = SplitImageTag(sourceDockerImageTag);

            await InitiateDockerLogin(dockerCli);

            var        splitDestinationTag = SplitImageTag(destinationDockerImageTag);
            Repository repository          = await SetupECRRepository(splitDestinationTag.RepositoryName);

            var targetTag = repository.RepositoryUri + ":" + splitDestinationTag.Tag;

            this.Logger?.WriteLine($"Taging image {sourceRepoInfo.FullTagName} with {destinationDockerImageTag}");
            if (dockerCli.Tag(sourceRepoInfo.FullTagName, targetTag) != 0)
            {
                throw new ToolsException("Error executing \"docker tag\"", ToolsException.CommonErrorCode.DockerTagFail);
            }

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

            this.PushedImageUri = targetTag;
            this.Logger?.WriteLine($"Image {this.PushedImageUri} Push Complete. ");
        }
        private async Task InitiateDockerLogin(DockerCLIWrapper dockerCLI)
        {
            try
            {
                this.Logger?.WriteLine("Fetching ECR authorization token to use to login with the docker CLI");
                var response = await this.ECRClient.GetAuthorizationTokenAsync(new GetAuthorizationTokenRequest());

                var authTokenBytes = Convert.FromBase64String(response.AuthorizationData[0].AuthorizationToken);
                var authToken      = Encoding.UTF8.GetString(authTokenBytes);
                var decodedTokens  = authToken.Split(':');

                this.Logger?.WriteLine("Executing docker CLI login command");
                if (dockerCLI.Login(decodedTokens[0], decodedTokens[1], response.AuthorizationData[0].ProxyEndpoint) != 0)
                {
                    throw new ToolsException($"Error executing the docker login command", ToolsException.CommonErrorCode.DockerCLILoginFail);
                }
            }
            catch (ToolsException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new ToolsException($"Error logging on with the docker CLI: {e.Message}", ToolsException.CommonErrorCode.GetECRAuthTokens);
            }
        }
        protected override async Task <bool> PerformActionAsync()
        {
            var projectLocation = Utilities.DetermineProjectLocation(this.WorkingDirectory, this.ProjectLocation);
            var dockerCli       = new DockerCLIWrapper(this.Logger, projectLocation);

            string sourceDockerTag;
            string destinationDockerTag;

            var localDockerImage = this.GetStringValueOrDefault(this.PushDockerImageProperties.LocalDockerImage, CommonDefinedCommandOptions.ARGUMENT_LOCAL_DOCKER_IMAGE, false);

            // If there is no local tag then build the image
            if (string.IsNullOrEmpty(localDockerImage))
            {
                // In the case of building the image when we push the image the local image will have the same name as the ECR destionation tag.
                destinationDockerTag = DetermineDockerImageTag(true, projectLocation);
                sourceDockerTag      = destinationDockerTag;

                BuildDockerImage(dockerCli, projectLocation, destinationDockerTag);
            }
            else
            {
                destinationDockerTag = DetermineDockerImageTag(false, projectLocation);
                sourceDockerTag      = localDockerImage;

                // If an ECR destination tag was not given then use the same tag as the local. That way the user isn't required to specify the --image-tag switch.
                if (string.IsNullOrEmpty(destinationDockerTag))
                {
                    destinationDockerTag = sourceDockerTag;
                    if (!destinationDockerTag.Contains(":"))
                    {
                        destinationDockerTag += ":latest";
                    }
                }
            }

            if (!this.SkipPushToECR)
            {
                string ecrTag;
                if (string.IsNullOrEmpty(ImageTagUniqueSeed))
                {
                    ecrTag = destinationDockerTag;
                }
                else
                {
                    var imageId = dockerCli.GetImageId(sourceDockerTag);
                    ecrTag = GenerateUniqueEcrTag(this.ImageTagUniqueSeed, destinationDockerTag, imageId);
                }

                await PushToECR(dockerCli, sourceDockerTag, ecrTag);
            }
            else
            {
                this.PushedImageUri = destinationDockerTag;
            }

            return(true);
        }
        protected override int ExecuteDockerBuild(DockerCLIWrapper dockerCli, string dockerBuildWorkingDirectory, string fullDockerfilePath, string dockerImageTag, string dockerBuildOptions)
        {
            var architecture = this.GetStringValueOrDefault(this.Architecture, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_ARCHITECTURE, false);
            var arm64Build   = false;

            if (string.Equals(LambdaConstants.RUNTIME_LINUX_ARM64, LambdaUtilities.DetermineRuntimeParameter(null, architecture)))
            {
                arm64Build = true;
            }

            return(dockerCli.Build(dockerBuildWorkingDirectory, fullDockerfilePath, dockerImageTag, dockerBuildOptions, arm64Build));
        }
 protected virtual int ExecuteDockerBuild(DockerCLIWrapper dockerCli, string dockerBuildWorkingDirectory, string fullDockerfilePath, string dockerImageTag, string dockerBuildOptions)
 {
     return(dockerCli.Build(dockerBuildWorkingDirectory, fullDockerfilePath, dockerImageTag, dockerBuildOptions));
 }
        private void BuildDockerImage(DockerCLIWrapper dockerCli, string projectLocation, string dockerImageTag)
        {
            var dockerFile = this.GetStringValueOrDefault(this.PushDockerImageProperties.DockerFile, CommonDefinedCommandOptions.ARGUMENT_DOCKERFILE, false);

            if (string.IsNullOrEmpty(dockerFile))
            {
                dockerFile = Constants.DEFAULT_DOCKERFILE;
            }


            var hostBuildOutput = this.GetStringValueOrDefault(this.PushDockerImageProperties.HostBuildOutput, CommonDefinedCommandOptions.ARGUMENT_HOST_BUILD_OUTPUT, false);

            if (!string.IsNullOrEmpty(hostBuildOutput))
            {
                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);

                BuildProject(projectLocation, configuration, targetFramework, publishOptions, Path.Combine(projectLocation, hostBuildOutput));
            }

            var dockerDetails = InspectDockerFile(this.Logger, projectLocation, dockerFile);

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

            var dockerBuildWorkingDirectory = this.GetStringValueOrDefault(this.PushDockerImageProperties.DockerBuildWorkingDirectory, CommonDefinedCommandOptions.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, CommonDefinedCommandOptions.ARGUMENT_DOCKER_BUILD_OPTIONS, false);

            var fullDockerfilePath = Path.Combine(projectLocation, dockerFile);

            if (!Path.IsPathRooted(fullDockerfilePath))
            {
                fullDockerfilePath = Path.Combine(dockerBuildWorkingDirectory, fullDockerfilePath);
            }

            // The Docker CLI gives a poor error message if the Dockerfile does not exist. This does a preemptive check and gives a more
            // meaningful error message.
            if (!File.Exists(fullDockerfilePath))
            {
                throw new ToolsException($"Error failed to find file \"{fullDockerfilePath}\" to build the Docker image", ToolsException.CommonErrorCode.DockerBuildFailed);
            }

            if (ExecuteDockerBuild(dockerCli, dockerBuildWorkingDirectory, fullDockerfilePath, dockerImageTag, dockerBuildOptions) != 0)
            {
                throw new ToolsException("Error executing \"docker build\"", ToolsException.CommonErrorCode.DockerBuildFailed);
            }
        }
        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);
        }
Ejemplo n.º 8
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);
        }