// Wrapper for minicli.ProcessCommand for commands that use meshage. // Specifically, for `mesh send all ...`, runs the subcommand locally and // across meshage, combining the results from the two channels into a single // channel. This is useful if you want to get the output of a command from all // nodes in the cluster without having to run a command locally and over // meshage. 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 .record %t %s", Wildcard, record, original) if err != nil { log.Fatal("cannot run `%v` globally -- %v", original, err) } cmd.Record = record cmdLock.Lock() var wg sync.WaitGroup out := make(chan minicli.Responses) cmd, err = cliPreprocessor(cmd) if err != nil { log.Errorln(err) out <- minicli.Responses{ &minicli.Response{ Host: hostname, Error: err.Error(), }, } close(out) return out } // Run the command (should be `mesh send all ...` and the subcommand which // should run locally). ins := []chan minicli.Responses{ minicli.ProcessCommand(cmd), minicli.ProcessCommand(cmd.Subcommand), } // De-mux ins into out for _, in := range ins { wg.Add(1) go func(in chan minicli.Responses) { defer wg.Done() for v := range in { out <- v } }(in) } // Wait until everything has been read before closing the chan and // releasing the lock. go func() { defer cmdLock.Unlock() defer close(out) wg.Wait() }() return out }
// 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) }