Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: install qemu
run: |
sudo apt-get update
sudo apt-get -y install qemu-system-x86

- name: Set up Go
uses: actions/setup-go@v3
with:
Expand Down
39 changes: 37 additions & 2 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ type Cmd struct {
SessionOut io.Reader
SessionErr io.Reader
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
Stdout io.WriteCloser
Stderr io.WriteCloser
Row int
Col int
hasTTY bool // Set if we have a TTY
Expand Down Expand Up @@ -102,6 +102,13 @@ func (c *Cmd) Listen(n, addr string) (net.Listener, error) {
return c.client.Listen(n, addr)
}

func sameFD(w io.WriteCloser, std *os.File) bool {
if file, ok := w.(*os.File); ok {
return file.Fd() == std.Fd()
}
return false
}

// Command implements exec.Command. The required parameter is a host.
// The args arg args to $SHELL. If there are no args, then starting $SHELL
// is assumed.
Expand Down Expand Up @@ -512,6 +519,7 @@ func (c *Cmd) Start() error {
}
go c.TTYIn(c.session, c.SessionIn, c.Stdin)
} else {
verbose("Setup batch input")
go func() {
if _, err := io.Copy(c.SessionIn, c.Stdin); err != nil && !errors.Is(err, io.EOF) {
log.Printf("copying stdin: %v", err)
Expand All @@ -522,14 +530,26 @@ func (c *Cmd) Start() error {
}()
}
go func() {
verbose("set up copying to c.Stdout")
if _, err := io.Copy(c.Stdout, c.SessionOut); err != nil && !errors.Is(err, io.EOF) {
log.Printf("copying stdout: %v", err)
}

// If the file is NOT stdout, close it.
// This is needed when programmers have
// set c.Stdout to be some other WriteCloser, e.g. a pipe.
if !sameFD(c.Stdout, os.Stdout) {
c.Stdout.Close()
}
}()
go func() {
verbose("set up copying to c.Stderr")
if _, err := io.Copy(c.Stderr, c.SessionErr); err != nil && !errors.Is(err, io.EOF) {
log.Printf("copying stderr: %v", err)
}
if !sameFD(c.Stdout, os.Stderr) {
c.Stderr.Close()
}
}()

return nil
Expand All @@ -549,6 +569,21 @@ func (c *Cmd) Run() error {
return c.Wait()
}

func (c *Cmd) CombinedOutput() ([]byte, error) {
r, w, err := os.Pipe()
if err != nil {
return nil, err
}

c.Stdout, c.Stderr = w, w

cpuerr := c.Run()

b, err := io.ReadAll(r)

return b, errors.Join(cpuerr, err)
}

// TTYIn manages tty input for a cpu session.
// It exists mainly to deal with ~.
func (c *Cmd) TTYIn(s *ssh.Session, w io.WriteCloser, r io.Reader) {
Expand Down
8 changes: 4 additions & 4 deletions client/fns.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,15 @@ func (c *Cmd) Signal(s ssh.Signal) error {
// and an error if either had trouble being read.
func (c *Cmd) Outputs() ([]bytes.Buffer, error) {
var r [2]bytes.Buffer
var errs []error
var errs error
if _, err := io.Copy(&r[0], c.SessionOut); err != nil && err != io.EOF {
errs = append(errs, fmt.Errorf("Stdout: %w", err))
errs = err
}
if _, err := io.Copy(&r[1], c.SessionErr); err != nil && err != io.EOF {
errs = append(errs, fmt.Errorf("Stderr: %w", err))
errs = errors.Join(errs, err)
}
if errs != nil {
return r[:], fmt.Errorf(fmt.Sprintf("%v", errs))
return r[:], errs
}
return r[:], nil
}
Expand Down
8 changes: 7 additions & 1 deletion cmds/cpud/serve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,13 @@ func TestListen(t *testing.T) {
// e.g. no ipv4 or vsock
continue
}
t.Errorf("Listen(%v, %v): err != nil", tt.network, tt.port)
// If it is in use, not a lot to do.
if errors.As(err, &sysErr) && sysErr.Err == syscall.EADDRINUSE {
t.Logf("%s:%s is in use, so can not test; continuing", tt.network, tt.port)
// e.g. no ipv4 or vsock
continue
}
t.Errorf("Listen(%v, %v): got %v, want nil", tt.network, tt.port, err)
continue
}
if ln == nil {
Expand Down
34 changes: 25 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,54 +1,70 @@
module github.com/u-root/cpu

go 1.23.0
go 1.24

toolchain go1.24.1

require (
github.com/gliderlabs/ssh v0.3.5
github.com/kevinburke/ssh_config v1.2.0
github.com/u-root/u-root v0.11.1-0.20230913033713-004977728a9d
golang.org/x/crypto v0.36.0
golang.org/x/sys v0.31.0
golang.org/x/crypto v0.39.0
golang.org/x/sys v0.33.0
)

require (
github.com/apptainer/container-library-client v1.4.12
github.com/brutella/dnssd v1.2.9
github.com/creack/pty v1.1.18
github.com/go-git/go-billy/v5 v5.5.1-0.20240514075308-8f1b719cb6a2
github.com/google/go-containerregistry v0.20.6
github.com/google/uuid v1.6.0
github.com/hugelgupf/p9 v0.3.0
github.com/mdlayher/vsock v1.2.1
github.com/moby/sys/mountinfo v0.7.1
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/willscott/go-nfs v0.0.0-20240424173852-04b947a7e58a
golang.org/x/exp v0.0.0-20230810033253-352e893a4cad
golang.org/x/term v0.30.0
golang.org/x/term v0.32.0
)

require (
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
github.com/apptainer/sif/v2 v2.21.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
github.com/docker/cli v28.2.2+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.3 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/go-log/log v0.2.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/mdlayher/socket v0.4.1 // indirect
github.com/miekg/dns v1.1.55 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pierrec/lz4/v4 v4.1.18 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rasky/go-xdr v0.0.0-20170124162913-1a41d1a06c93 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sylabs/json-resp v0.9.4 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/vbatts/tar-split v0.12.1 // indirect
github.com/vishvananda/netlink v1.2.1-beta.2 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
github.com/willscott/go-nfs-client v0.0.0-20240104095149-b44639837b00 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/tools v0.12.0 // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/tools v0.34.0 // indirect
google.golang.org/grpc v1.56.3 // indirect
)
Loading
Loading