// GetContainerLogs returns logs of a specific container. By // default, it returns a snapshot of the container log. Set 'follow' to true to // stream the log. Set 'follow' to false and specify the number of lines (e.g. // "100" or "all") to tail the log. func (r *runtime) GetContainerLogs(pod *api.Pod, containerID kubecontainer.ContainerID, logOptions *api.PodLogOptions, stdout, stderr io.Writer) error { glog.V(4).Infof("Hyper: running logs on container %s", containerID.ID) args := append([]string{}, "logs") if logOptions.Follow { args = append(args, "--follow") } if logOptions.SinceSeconds != nil && *logOptions.SinceSeconds != 0 { args = append(args, fmt.Sprintf("--since=%d", *logOptions.SinceSeconds)) } if logOptions.TailLines != nil && *logOptions.TailLines != 0 { args = append(args, fmt.Sprintf("--tail=%d", *logOptions.TailLines)) } if logOptions.Timestamps { args = append(args, "--timestamps") } args = append(args, containerID.ID) command := r.buildCommand(args...) p, err := kubecontainer.StartPty(command) if err != nil { return err } defer p.Close() if stdout != nil { go io.Copy(stdout, p) } return command.Wait() }
// Runs the command in the container of the specified pod. // Attaches the processes stdin, stdout, and stderr. Optionally uses a // tty. func (r *runtime) ExecInContainer(containerID kubecontainer.ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error { glog.V(4).Infof("Hyper: execing %s in container %s.", cmd, containerID.ID) args := append([]string{}, "exec", "-a", containerID.ID) args = append(args, cmd...) command := r.buildCommand(args...) p, err := kubecontainer.StartPty(command) if err != nil { return err } defer p.Close() // make sure to close the stdout stream defer stdout.Close() if stdin != nil { go io.Copy(p, stdin) } if stdout != nil { go io.Copy(stdout, p) } return command.Wait() }
// TODO should we support nsenter in a container, running with elevated privs and --pid=host? func (*NsenterExecHandler) ExecInContainer(client DockerInterface, container *dockertypes.ContainerJSON, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error { nsenter, err := exec.LookPath("nsenter") if err != nil { return fmt.Errorf("exec unavailable - unable to locate nsenter") } containerPid := container.State.Pid // TODO what if the container doesn't have `env`??? args := []string{"-t", fmt.Sprintf("%d", containerPid), "-m", "-i", "-u", "-n", "-p", "--", "env", "-i"} args = append(args, fmt.Sprintf("HOSTNAME=%s", container.Config.Hostname)) args = append(args, container.Config.Env...) args = append(args, cmd...) command := exec.Command(nsenter, args...) if tty { p, err := kubecontainer.StartPty(command) if err != nil { return err } defer p.Close() // make sure to close the stdout stream defer stdout.Close() if stdin != nil { go io.Copy(p, stdin) } if stdout != nil { go io.Copy(stdout, p) } return command.Wait() } else { if stdin != nil { // Use an os.Pipe here as it returns true *os.File objects. // This way, if you run 'kubectl exec <pod> -i bash' (no tty) and type 'exit', // the call below to command.Run() can unblock because its Stdin is the read half // of the pipe. r, w, err := os.Pipe() if err != nil { return err } go io.Copy(w, stdin) command.Stdin = r } if stdout != nil { command.Stdout = stdout } if stderr != nil { command.Stderr = stderr } return command.Run() } }
// Note: In rkt, the container ID is in the form of "UUID:appName:ImageID", where // appName is the container name. func (r *runtime) ExecInContainer(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error { glog.V(4).Infof("Rkt execing in container.") id, err := parseContainerID(containerID) if err != nil { return err } // TODO(yifan): Use appName instead of imageID. // see https://github.com/coreos/rkt/pull/640 args := append([]string{}, "enter", "--imageid", id.imageID, id.uuid) args = append(args, cmd...) command := r.buildCommand(args...) if tty { p, err := kubecontainer.StartPty(command) if err != nil { return err } defer p.Close() // make sure to close the stdout stream defer stdout.Close() if stdin != nil { go io.Copy(p, stdin) } if stdout != nil { go io.Copy(stdout, p) } return command.Wait() } if stdin != nil { // Use an os.Pipe here as it returns true *os.File objects. // This way, if you run 'kubectl exec <pod> -i bash' (no tty) and type 'exit', // the call below to command.Run() can unblock because its Stdin is the read half // of the pipe. r, w, err := os.Pipe() if err != nil { return err } go io.Copy(w, stdin) command.Stdin = r } if stdout != nil { command.Stdout = stdout } if stderr != nil { command.Stderr = stderr } return command.Run() }