func CmdRender(args []string, stdout, stderr io.Writer, in beam.Receiver, out beam.Sender) { if len(args) != 2 { fmt.Fprintf(stderr, "Usage: %s FORMAT\n", args[0]) out.Send(data.Empty().Set("status", "1").Bytes(), nil) return } txt := args[1] if !strings.HasSuffix(txt, "\n") { txt += "\n" } t := template.Must(template.New("render").Parse(txt)) for { payload, attachment, err := in.Receive() if err != nil { return } msg, err := data.Decode(string(payload)) if err != nil { fmt.Fprintf(stderr, "decode error: %v\n") } if err := t.Execute(stdout, msg); err != nil { fmt.Fprintf(stderr, "rendering error: %v\n", err) out.Send(data.Empty().Set("status", "1").Bytes(), nil) return } if err := out.Send(payload, attachment); err != nil { return } } }
func (rcv *Receiver) Run() error { r := beam.NewRouter(nil) r.NewRoute().KeyExists("cmd").Handler(func(p []byte, f *os.File) error { // Use the attachment as a beam return channel peer, err := beam.FileConn(f) if err != nil { f.Close() return err } f.Close() defer peer.Close() msg := data.Message(p) cmd := msg.Get("cmd") job := rcv.Engine.Job(cmd[0], cmd[1:]...) // Decode env env, err := data.Decode(msg.GetOne("env")) if err != nil { return fmt.Errorf("error decoding 'env': %v", err) } job.Env().InitMultiMap(env) stdout, err := beam.SendRPipe(peer, data.Empty().Set("cmd", "log", "stdout").Bytes()) if err != nil { return err } job.Stdout.Add(stdout) stderr, err := beam.SendRPipe(peer, data.Empty().Set("cmd", "log", "stderr").Bytes()) if err != nil { return err } job.Stderr.Add(stderr) stdin, err := beam.SendWPipe(peer, data.Empty().Set("cmd", "log", "stdin").Bytes()) if err != nil { return err } job.Stdin.Add(stdin) // ignore error because we pass the raw status job.Run() err = peer.Send(data.Empty().Set("cmd", "status", fmt.Sprintf("%d", job.status)).Bytes(), nil) if err != nil { return err } return nil }) _, err := beam.Copy(r, rcv.peer) return err }