package daemon import ( "errors" "fmt" "os" "strconv" "github.com/subgraph/oz/ipc" ) func clientConnect() (*ipc.MsgConn, error) { return ipc.Connect(SocketName, messageFactory, nil) } func clientSend(msg interface{}) (*ipc.Message, error) { c, err := clientConnect() if err != nil { return nil, err } defer c.Close() rr, err := c.ExchangeMsg(msg) if err != nil { return nil, err } resp := <-rr.Chan() rr.Done() return resp, nil } func ListProfiles() ([]Profile, error) { resp, err := clientSend(new(ListProfilesMsg)) if err != nil { return nil, err } body, ok := resp.Body.(*ListProfilesResp) if !ok { return nil, errors.New("ListProfiles response was not expected type") } return body.Profiles, nil } func ListSandboxes() ([]SandboxInfo, error) { resp, err := clientSend(&ListSandboxesMsg{}) if err != nil { return nil, err } body, ok := resp.Body.(*ListSandboxesResp) if !ok { return nil, errors.New("ListSandboxes response was not expected type") } return body.Sandboxes, nil } func Launch(arg, cpath string, args []string, noexec bool) error { idx, name, err := parseProfileArg(arg) if err != nil { return err } pwd, _ := os.Getwd() groups, _ := os.Getgroups() gg := []uint32{} if len(groups) > 0 { gg = make([]uint32, len(groups)) for i, v := range groups { gg[i] = uint32(v) } } resp, err := clientSend(&LaunchMsg{ Index: idx, Name: name, Path: cpath, Pwd: pwd, Gids: gg, Args: args, Env: os.Environ(), Noexec: noexec, }) if err != nil { return err } switch body := resp.Body.(type) { case *ErrorMsg: fmt.Printf("error was %s\n", body.Msg) case *OkMsg: fmt.Println("ok received") default: fmt.Printf("Unexpected message received %+v", body) } return nil } func KillAllSandboxes() error { return KillSandbox(-1) } func KillSandbox(id int) error { resp, err := clientSend(&KillSandboxMsg{Id: id}) if err != nil { return err } switch body := resp.Body.(type) { case *ErrorMsg: return errors.New(body.Msg) case *OkMsg: return nil default: return fmt.Errorf("Unexpected message received %+v", body) } } func MountFiles(files []string) error { resp, err := clientSend(&MountFilesMsg{Files: files}) if err != nil { return err } switch body := resp.Body.(type) { case *ErrorMsg: return errors.New(body.Msg) case *OkMsg: return nil default: return fmt.Errorf("Unexpected message received %+v", body) } } func UnmountFile(file string) error { resp, err := clientSend(&UnmountFileMsg{File: file}) if err != nil { return err } switch body := resp.Body.(type) { case *ErrorMsg: return errors.New(body.Msg) case *OkMsg: return nil default: return fmt.Errorf("Unexpected message received %+v", body) } } func parseProfileArg(arg string) (int, string, error) { if len(arg) == 0 { return 0, "", errors.New("profile argument needed") } if n, err := strconv.Atoi(arg); err == nil { return n, "", nil } return 0, arg, nil } func Logs(count int, follow bool) (chan string, error) { c, err := clientConnect() if err != nil { return nil, err } rr, err := c.ExchangeMsg(&LogsMsg{Count: count, Follow: follow}) if err != nil { return nil, err } out := make(chan string) go dumpLogs(out, rr) return out, nil } func dumpLogs(out chan<- string, rr ipc.ResponseReader) { for resp := range rr.Chan() { switch body := resp.Body.(type) { case *OkMsg: rr.Done() close(out) return case *LogData: for _, ll := range body.Lines { out <- ll } default: out <- fmt.Sprintf("Unexpected response type (%T)", body) } } }