func commandSocketHandle(c net.Conn) { defer c.Close() enc := json.NewEncoder(c) dec := json.NewDecoder(c) var err error for err == nil { var cmd *minicli.Command cmd, err = readLocalCommand(dec) if err != nil { break } if cmd == nil { err = sendLocalResp(enc, nil, false) continue } // HAX: Don't record the read command if hasCommand(cmd, "read") { cmd.SetRecord(false) } // HAX: Work around so that we can add the more boolean. var prev minicli.Responses // Keep sending until we hit the first error, then just consume the // channel to ensure that we release any locks acquired by cmd. for resp := range RunCommands(cmd) { if prev != nil && err == nil { err = sendLocalResp(enc, prev, true) } else if err != nil && len(resp) > 0 { log.Info("dropping resp from %v", resp[0].Host) } prev = resp } if err == nil { err = sendLocalResp(enc, prev, false) } } // finally, log the error, if there was one if err == nil || err == io.EOF { log.Infoln("command client disconnected") } else if err != nil && strings.Contains(err.Error(), "write: broken pipe") { log.Infoln("command client disconnected without waiting for responses") } else if err != nil { log.Errorln(err) } }
// runCommandGlobally runs the given command across all nodes on meshage, // including the local node and combines the results into a single channel. func runCommandGlobally(cmd *minicli.Command) <-chan minicli.Responses { // Keep the original CLI input original := cmd.Original record := cmd.Record cmd, err := minicli.Compilef("mesh send %s %s", Wildcard, original) if err != nil { log.Fatal("cannot run `%v` globally -- %v", original, err) } cmd.SetRecord(record) return runCommands(cmd, cmd.Subcommand) }