コード例 #1
0
        public void Compose(String args, DockerOutput output = DockerOutput.Stderr)
        {
            var console = Console.Out;

            var command = $"docker-compose {args}";

            using var process =
                      new Process {
                      StartInfo = new() {
                          WorkingDirectory       = workingDirectory,
                          FileName               = composeBinFilePath,
                          Arguments              = args,
                          RedirectStandardOutput = output is DockerOutput.Stdout,
                          RedirectStandardError  = output is DockerOutput.Stderr
                      }
                  };
            if (process.Start())
            {
                console.WriteLine();
                console.WriteLine($"> {command}");
            }
            else
            {
                console.WriteLine();
                var failureMsg = $"> Failed to start process: {command}";
                console.WriteLine(failureMsg);
                throw new(failureMsg);
            }

            var dockerComposeOutput =
                output switch {
                DockerOutput.Stdout => process.StandardOutput,
                DockerOutput.Stderr => process.StandardError
            };
            var bufferPool = ArrayPool <Char> .Shared;
            var buffer     = bufferPool.Rent(4096);

            try {
                while (dockerComposeOutput.ReadBlock(buffer, 0, 4096) is > 0 and var charsRead)
                {
                    console.Write(buffer, 0, charsRead);
                }
            }
            finally {
                bufferPool.Return(buffer);
            }

            process.WaitForExit();

            var exitCode = process.ExitCode;
            var exitMsg  = $"> Process exited with code {exitCode}: {command}";

            console.WriteLine(exitMsg);
            console.WriteLine();
            if (exitCode is not 0)
            {
                throw new(exitMsg);
            }
        }
コード例 #2
0
ファイル: DockerViaBash.cs プロジェクト: unisave-cloud/ant
        /// <inheritdoc/>
        public async Task Rmi(string imageName)
        {
            DockerOutput output = await DockerCommandAsync(
                $"rmi {imageName}"
                );

            // TODO: guard no such image
            // TODO: guard image in use
            GuardOtherErrors(output);
        }
コード例 #3
0
ファイル: DockerViaBash.cs プロジェクト: unisave-cloud/ant
        /// <inheritdoc/>
        public async Task Stop(string containerId, int time = 10)
        {
            DockerOutput output = await DockerCommandAsync(
                $"stop -t {time} {containerId}"
                );

            // NOTE: stopping a stopped container causes no error

            GuardNoSuchContainer(output, containerId);
            GuardOtherErrors(output);
        }
コード例 #4
0
ファイル: DockerViaBash.cs プロジェクト: unisave-cloud/ant
 /// <summary>
 /// Throws docker exception on any other nonzero exit code
 /// </summary>
 /// <exception cref="DockerException"></exception>
 private static void GuardOtherErrors(DockerOutput output)
 {
     if (output.exitCode != 0)
     {
         throw new DockerException(
                   DockerError.Other,
                   "Exit code: " + output.exitCode +
                   " Stderr: " + output.stderr
                   );
     }
 }
コード例 #5
0
ファイル: DockerViaBash.cs プロジェクト: unisave-cloud/ant
        /// <inheritdoc/>
        public async Task <string> Logs(string containerId)
        {
            DockerOutput output = await DockerCommandAsync(
                $"logs {containerId}"
                );

            GuardNoSuchContainer(output, containerId);
            GuardOtherErrors(output);

            // IMPORTANT NOTE: docker logs stdout and stderr
            // into their respective streams
            return(output.completeOutput);
        }
コード例 #6
0
ファイル: DockerViaBash.cs プロジェクト: unisave-cloud/ant
        /// <summary>
        /// Executes the docker command and returns the docker output
        /// </summary>
        /// <param name="arguments">Argument string, e.g. "logs --tail 50"</param>
        /// <returns>Output from the docker process</returns>
        private static Task <DockerOutput> DockerCommandAsync(string arguments)
        {
            var process = new Process {
                EnableRaisingEvents = true,
                StartInfo           =
                {
                    UseShellExecute        = false,
                    FileName               = "docker",
                    Arguments              = arguments,
                    RedirectStandardInput  = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError  = true,
                    CreateNoWindow         = true
                }
            };

            var stdout      = new List <string>();
            var stderr      = new List <string>();
            var combinedOut = new List <string>();

            process.OutputDataReceived += (s, e) => {
                stdout.Add(e.Data + "\n");
                combinedOut.Add(e.Data + "\n");
            };
            process.ErrorDataReceived += (s, e) => {
                stderr.Add(e.Data + "\n");
                combinedOut.Add(e.Data + "\n");
            };

            var tcs = new TaskCompletionSource <DockerOutput>();

            process.Exited += (sender, args) => {
                var output = new DockerOutput {
                    // BUG: Collection was modified; enumeration operation may not execute.
                    stdout         = string.Concat(stdout), // <-- here
                    stderr         = string.Concat(stderr), // <-- or here
                    completeOutput = string.Concat(combinedOut),
                    exitCode       = process.ExitCode
                };

                process.Dispose();

                tcs.SetResult(output);
            };

            process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            return(tcs.Task);
        }
コード例 #7
0
ファイル: DockerViaBash.cs プロジェクト: unisave-cloud/ant
        /// <inheritdoc/>
        public async Task <string> Build(DockerBuildOptions options)
        {
            // TODO: also pass CPU usage limitations

            string flags =
                $"--file {options.DockerfilePath} " +
                $"--tag {options.Tag}";

            DockerOutput output = await DockerCommandAsync(
                $"build {flags} {options.ContextPath}"
                );

            return(output.completeOutput);
        }
コード例 #8
0
ファイル: DockerViaBash.cs プロジェクト: unisave-cloud/ant
        /// <inheritdoc/>
        public async Task Rm(string containerId)
        {
            DockerOutput output = await DockerCommandAsync(
                $"rm {containerId}"
                );

            if (output.exitCode == 1 &&
                output.stderr.Contains("You cannot remove a running container"))
            {
                throw new DockerException(
                          DockerError.RemovingRunningContainer,
                          containerId
                          );
            }

            GuardNoSuchContainer(output, containerId);
            GuardOtherErrors(output);
        }
コード例 #9
0
ファイル: DockerViaBash.cs プロジェクト: unisave-cloud/ant
        /// <inheritdoc/>
        public async Task <ContainerStatus> GetStatus(
            string containerId
            )
        {
            DockerOutput output = await DockerCommandAsync(
                "inspect --format='{{.State.Status}}' " + containerId
                );

            GuardNoSuchContainer(output, containerId);
            GuardOtherErrors(output);

            if (output.stdout.Contains("created"))
            {
                return(ContainerStatus.Created);
            }

            if (output.stdout.Contains("restarting"))
            {
                return(ContainerStatus.Restarting);
            }

            if (output.stdout.Contains("running"))
            {
                return(ContainerStatus.Running);
            }

            if (output.stdout.Contains("paused"))
            {
                return(ContainerStatus.Paused);
            }

            if (output.stdout.Contains("exited"))
            {
                return(ContainerStatus.Exited);
            }

            throw new DockerException(
                      DockerError.Other,
                      "Unknown container status: " + output.stdout
                      );
        }
コード例 #10
0
ファイル: DockerViaBash.cs プロジェクト: unisave-cloud/ant
        /// <inheritdoc/>
        public async Task <string> Run(DockerRunOptions options)
        {
            string arguments = string.Join(" ", options.GetArguments());

            DockerOutput output = await DockerCommandAsync(
                $"run {arguments}"
                );

            // TODO: extract to method
            if (output.exitCode == 125 &&
                output.stderr.Contains("Conflict. The container name"))
            {
                throw new DockerException(
                          DockerError.ContainerNameTaken,
                          arguments
                          );
            }

            GuardOtherErrors(output);

            return(output.completeOutput);
        }
コード例 #11
0
ファイル: DockerViaBash.cs プロジェクト: unisave-cloud/ant
        /// <summary>
        /// Throws docker exception if the output means, no such container exists
        /// </summary>
        /// <param name="output"></param>
        /// <param name="containerId"></param>
        /// <exception cref="DockerException"></exception>
        private static void GuardNoSuchContainer(
            DockerOutput output,
            string containerId
            )
        {
            if (output.exitCode != 1)
            {
                return;
            }

            if (
                !output.stderr.Contains("No such container") &&
                !output.stderr.Contains("No such object")    // 'inspect' cmd
                )
            {
                return;
            }

            throw new DockerException(
                      DockerError.NoSuchContainer,
                      containerId
                      );
        }