Esempio n. 1
0
    public static async Task PipeContainerOutput(IOutputObserver outputObserver, MultiplexedStream stream, CancellationToken cancellationToken)
    {
        byte[] buffer = new byte[1024];
        while (!cancellationToken.IsCancellationRequested)
        {
            var result = await stream.ReadOutputAsync(buffer, 0, buffer.Length, cancellationToken);

            if (result.EOF)
            {
                break;
            }

            switch (result.Target)
            {
            case MultiplexedStream.TargetStream.StandardOut:
                await outputObserver.StandardOutput(buffer, result.Count);

                break;

            case MultiplexedStream.TargetStream.StandardError:
                await outputObserver.StandardError(buffer, result.Count);

                break;
            }
        }
    }
Esempio n. 2
0
 internal void AddOutputObserver(IOutputObserver obs)
 {
     m_OutputMessage += new ModelHandler<GlobalStateModel>(obs.NewOutputMessage);
 }
Esempio n. 3
0
 public void usunObserwator(IOutputObserver o)
 {
     _listaObserwatorow.Remove(o);
 }
Esempio n. 4
0
 public void dodajObserwatora(IOutputObserver o)
 {
     _listaObserwatorow.Add(o);
 }
Esempio n. 5
0
        public async Task <int> RunBuild(Protocol.RunDockerBuild build, IOutputObserver outputObserver, CancellationToken cancellationToken)
        {
            await CleanupNetworks(cancellationToken);

            CreateContainerResponse?proxyContainer = null;

            try {
                proxyContainer = await docker.Containers.CreateContainerAsync(new CreateContainerParameters {
                    Image = build.ProxyImage,
                    Env   = build.EnableNetwork
                        ? null
                        : new List <string> {
                        "HELIUM_PROXY_REPLAY=true"
                    },
                    HostConfig = new HostConfig {
                        AutoRemove  = true,
                        NetworkMode = build.EnableNetwork ? null : "none",
                        Isolation   = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "process" : null,
                    },
                }, cancellationToken);

                NetworksCreateResponse?network = null;
                try {
                    var networkName = networkTag + "-" + proxyContainer.ID;
                    network = await docker.Networks.CreateNetworkAsync(
                        new NetworksCreateParameters {
                        Name     = networkName,
                        Internal = true,
                    },
                        cancellationToken
                        );

                    await docker.Networks.ConnectNetworkAsync(
                        network.ID,
                        new NetworkConnectParameters {
                        Container      = proxyContainer.ID,
                        EndpointConfig = new EndpointSettings {
                            Aliases = new List <string> {
                                buildProxyHostname,
                            },
                        },
                    },
                        cancellationToken
                        );


                    var    buildMapping = new Dictionary <string, string>();
                    string?imageId      = null;

                    foreach (var imageBuild in build.Dockerfile.Builds)
                    {
                        var id = await RunSingleImageBuild(imageBuild, network.ID, buildMapping, outputObserver, cancellationToken);

                        if (imageBuild.FromCommand.AsName != null)
                        {
                            buildMapping.Add(imageBuild.FromCommand.AsName, id);
                        }

                        imageId = id;
                    }

                    if (imageId == null)
                    {
                        throw new Exception("No images were built");
                    }

                    await using (var imageFile = File.Create(build.OutputFile)) {
                        await docker.Images.SaveImageAsync(imageId, cancellationToken);
                    }

                    return(0);
                }
                finally {
                    if (network != null)
                    {
                        await docker.Networks.DeleteNetworkAsync(network.ID, cancellationToken);
                    }
                }
            }
            catch (RunCommandFailedException ex) {
                await outputObserver.StandardOutput(ex.Message);

                return(ex.ExitCode);
            }
            catch (Exception ex) {
                await outputObserver.StandardOutput(ex.Message);

                return(1);
            }
            finally {
                if (proxyContainer != null)
                {
                    await docker.Containers.RemoveContainerAsync(
                        proxyContainer.ID,
                        new ContainerRemoveParameters { Force = true },
                        cancellationToken
                        );
                }
            }
        }
Esempio n. 6
0
        private async Task <string> HandleRunCommandCommon(BuildState state, string proxyNetworkId, ReadOnlyDictionary <string, string> buildArgs, IReadOnlyList <string> command, IOutputObserver outputObserver, CancellationToken cancellationToken)
        {
            var nonEnvArgs = buildArgs.Where(arg => !state.Environment.ContainsKey(arg.Key)).ToList();

            var response = await docker.Containers.CreateContainerAsync(
                new Docker.DotNet.Models.CreateContainerParameters {
                Image        = state.Id,
                Env          = nonEnvArgs.Select(env => $"{env.Key}={env.Value}").Concat(proxyEnv).ToList(),
                AttachStderr = true,
                AttachStdout = true,
                Cmd          = command.ToList(),

                HostConfig = new Docker.DotNet.Models.HostConfig {
                    NetworkMode = proxyNetworkId,
                    Isolation   = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "process" : null,
                },
            },
                cancellationToken
                );

            try {
                using var stream = await docker.Containers.AttachContainerAsync(
                          response.ID,
                          tty : false,
                          new Docker.DotNet.Models.ContainerAttachParameters {
                    Stream = true,
                    Stderr = true,
                    Stdout = true,
                },
                          cancellationToken
                          );

                await docker.Containers.StartContainerAsync(
                    response.ID,
                    new Docker.DotNet.Models.ContainerStartParameters {
                },
                    cancellationToken
                    );

                await DockerHelpers.PipeContainerOutput(outputObserver, stream, cancellationToken);

                var waitResponse = await docker.Containers.WaitContainerAsync(response.ID, cancellationToken);

                int exitCode = (int)waitResponse.StatusCode;
                if (exitCode != 0)
                {
                    throw new RunCommandFailedException($"Command failed with exit code {exitCode}.", exitCode);
                }

                var image = await docker.Images.CommitContainerChangesAsync(new CommitContainerChangesParameters {
                    ContainerID = response.ID,
                    Config      = new Config {
                        Env = nonEnvArgs.Select(env => env.Key).ToList(),
                    },
                }, cancellationToken);

                return(image.ID);
            }
            finally {
                await docker.Containers.RemoveContainerAsync(response.ID, new Docker.DotNet.Models.ContainerRemoveParameters(), cancellationToken);
            }
        }
Esempio n. 7
0
        private Task <string> HandleRunShellCommand(BuildState state, string proxyNetworkId, RunShellCommand runShell, IOutputObserver outputObserver, CancellationToken cancellationToken)
        {
            var cmd = state.Shell.ToList();

            cmd.Add(runShell.ShellCommand);
            return(HandleRunCommandCommon(state, proxyNetworkId, runShell.BuildArgs, cmd, outputObserver, cancellationToken));
        }
Esempio n. 8
0
 private Task <string> HandleRunExecCommand(BuildState state, string proxyNetworkId, RunExecCommand runExec, IOutputObserver outputObserver, CancellationToken cancellationToken) =>
 HandleRunCommandCommon(state, proxyNetworkId, runExec.BuildArgs, runExec.ExecCommand, outputObserver, cancellationToken);
Esempio n. 9
0
        private async Task <string> RunSingleImageBuild(DockerfileBuild imageBuild, string proxyNetworkId, IReadOnlyDictionary <string, string> buildMapping, IOutputObserver outputObserver, CancellationToken cancellationToken)
        {
            string id = imageBuild.FromCommand.Image;

            if (id == "scratch")
            {
                throw new Exception("FROM scratch is not supported");
            }

            var state = await InitialBuildState(id);

            foreach (var command in imageBuild.Commands)
            {
                var prevId = id;
                id = command switch {
                    RunExecCommand runExec => await HandleRunExecCommand(state, proxyNetworkId, runExec, outputObserver, cancellationToken),
                    RunShellCommand runShell => await HandleRunShellCommand(state, proxyNetworkId, runShell, outputObserver, cancellationToken),
                    _ => throw new Exception("Unexpected command"),
                };

                if (prevId != imageBuild.FromCommand.Image)
                {
                    await docker.Images.DeleteImageAsync(prevId, new ImageDeleteParameters(), cancellationToken);
                }

                state.Id = id;
            }

            return(id);
        }
Esempio n. 10
0
        private static async Task <int> RunDocker(IDockerClient client, RunDockerCommand command, string callingContainerId, IOutputObserver outputObserver, CancellationToken cancellationToken)
        {
            var allowedMounts = await GetMounts(client, callingContainerId, cancellationToken);

            if (!(ValidateDockerCommand(command) && ValidateMounts(command.BindMounts, allowedMounts) is {} mounts))
            {
                await Console.Error.WriteLineAsync("Could not validate docker command.");

                return(1);
            }



            var response = await client.Containers.CreateContainerAsync(
                new Docker.DotNet.Models.CreateContainerParameters {
                Image        = command.ImageName,
                Env          = command.Environment.Select(env => $"{env.Key}={env.Value}").ToList(),
                AttachStderr = true,
                AttachStdout = true,
                ArgsEscaped  = false,
                Cmd          = command.Command.ToList(),
                WorkingDir   = command.CurrentDirectory,

                HostConfig = new Docker.DotNet.Models.HostConfig {
                    AutoRemove  = true,
                    NetworkMode = "none",
                    Isolation   = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "process" : null,

                    Mounts = mounts,
                },
            },
                cancellationToken
                );

            using var stream = await client.Containers.AttachContainerAsync(
                      response.ID,
                      tty : false,
                      new Docker.DotNet.Models.ContainerAttachParameters {
                Stream = true,
                Stderr = true,
                Stdout = true,
            },
                      cancellationToken
                      );

            await client.Containers.StartContainerAsync(
                response.ID,
                new Docker.DotNet.Models.ContainerStartParameters {
            },
                cancellationToken
                );

            await DockerHelpers.PipeContainerOutput(outputObserver, stream, cancellationToken);

            var waitResponse = await client.Containers.WaitContainerAsync(response.ID, cancellationToken);

            return((int)waitResponse.StatusCode);
        }