func (c *TagsCommand) Run(args []string) int { var tagPairs []string var delTags []string cmdFlags := flag.NewFlagSet("tags", flag.ContinueOnError) cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } cmdFlags.Var((*agent.AppendSliceValue)(&tagPairs), "set", "tag pairs, specified as key=value") cmdFlags.Var((*agent.AppendSliceValue)(&delTags), "delete", "tag keys to unset") rpcAddr := RPCAddrFlag(cmdFlags) rpcAuth := RPCAuthFlag(cmdFlags) if err := cmdFlags.Parse(args); err != nil { return 1 } if len(tagPairs) == 0 && len(delTags) == 0 { c.Ui.Output(c.Help()) return 1 } client, err := RPCClient(*rpcAddr, *rpcAuth) if err != nil { c.Ui.Error(fmt.Sprintf("Error connecting to Serf agent: %s", err)) return 1 } defer client.Close() tags, err := agent.UnmarshalTags(tagPairs) if err != nil { c.Ui.Error(fmt.Sprintf("Error: %s", err)) return 1 } if err := client.UpdateTags(tags, delTags); err != nil { c.Ui.Error(fmt.Sprintf("Error setting tags: %s", err)) return 1 } c.Ui.Output("Successfully updated agent tags") return 0 }
func (c *QueryCommand) Run(args []string) int { var noAck bool var nodes []string var tags []string var timeout time.Duration var format string cmdFlags := flag.NewFlagSet("event", flag.ContinueOnError) cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } cmdFlags.Var((*agent.AppendSliceValue)(&nodes), "node", "node filter") cmdFlags.Var((*agent.AppendSliceValue)(&tags), "tag", "tag filter") cmdFlags.DurationVar(&timeout, "timeout", 0, "query timeout") cmdFlags.BoolVar(&noAck, "no-ack", false, "no-ack") cmdFlags.StringVar(&format, "format", "text", "output format") rpcAddr := RPCAddrFlag(cmdFlags) rpcAuth := RPCAuthFlag(cmdFlags) if err := cmdFlags.Parse(args); err != nil { return 1 } // Setup the filter tags filterTags, err := agent.UnmarshalTags(tags) if err != nil { c.Ui.Error(fmt.Sprintf("Error: %s", err)) return 1 } args = cmdFlags.Args() if len(args) < 1 { c.Ui.Error("A query name must be specified.") c.Ui.Error("") c.Ui.Error(c.Help()) return 1 } else if len(args) > 2 { c.Ui.Error("Too many command line arguments. Only a name and payload must be specified.") c.Ui.Error("") c.Ui.Error(c.Help()) return 1 } name := args[0] var payload []byte if len(args) == 2 { payload = []byte(args[1]) } cl, err := RPCClient(*rpcAddr, *rpcAuth) if err != nil { c.Ui.Error(fmt.Sprintf("Error connecting to Serf agent: %s", err)) return 1 } defer cl.Close() // Setup the the response handler var handler queryRespFormat switch format { case "text": handler = &textQueryRespFormat{ ui: c.Ui, name: name, noAck: noAck, } case "json": handler = &jsonQueryRespFormat{ ui: c.Ui, Responses: make(map[string]string), } default: c.Ui.Error(fmt.Sprintf("Invalid format: %s", format)) return 1 } ackCh := make(chan string, 128) respCh := make(chan client.NodeResponse, 128) params := client.QueryParam{ FilterNodes: nodes, FilterTags: filterTags, RequestAck: !noAck, Timeout: timeout, Name: name, Payload: payload, AckCh: ackCh, RespCh: respCh, } if err := cl.Query(¶ms); err != nil { c.Ui.Error(fmt.Sprintf("Error sending query: %s", err)) return 1 } handler.Started() OUTER: for { select { case a := <-ackCh: if a == "" { break OUTER } handler.AckReceived(a) case r := <-respCh: if r.From == "" { break OUTER } handler.ResponseReceived(r) case <-c.ShutdownCh: return 1 } } if err := handler.Finished(); err != nil { return 1 } return 0 }
func (c *MembersCommand) Run(args []string) int { var detailed bool var roleFilter, statusFilter, nameFilter, format string var tags []string cmdFlags := flag.NewFlagSet("members", flag.ContinueOnError) cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } cmdFlags.BoolVar(&detailed, "detailed", false, "detailed output") cmdFlags.StringVar(&roleFilter, "role", "", "role filter") cmdFlags.StringVar(&statusFilter, "status", "", "status filter") cmdFlags.StringVar(&format, "format", "text", "output format") cmdFlags.Var((*agent.AppendSliceValue)(&tags), "tag", "tag filter") cmdFlags.StringVar(&nameFilter, "name", "", "name filter") rpcAddr := RPCAddrFlag(cmdFlags) rpcAuth := RPCAuthFlag(cmdFlags) if err := cmdFlags.Parse(args); err != nil { return 1 } // Deprecation warning for role if roleFilter != "" { c.Ui.Output("Deprecation warning: 'Role' has been replaced with 'Tags'") tags = append(tags, fmt.Sprintf("role=%s", roleFilter)) } reqtags, err := agent.UnmarshalTags(tags) if err != nil { c.Ui.Error(fmt.Sprintf("Error: %s", err)) return 1 } client, err := RPCClient(*rpcAddr, *rpcAuth) if err != nil { c.Ui.Error(fmt.Sprintf("Error connecting to Serf agent: %s", err)) return 1 } defer client.Close() members, err := client.MembersFiltered(reqtags, statusFilter, nameFilter) if err != nil { c.Ui.Error(fmt.Sprintf("Error retrieving members: %s", err)) return 1 } result := MemberContainer{} for _, member := range members { addr := net.TCPAddr{IP: member.Addr, Port: int(member.Port)} result.Members = append(result.Members, Member{ detail: detailed, Name: member.Name, Addr: addr.String(), Port: member.Port, Tags: member.Tags, Status: member.Status, Proto: map[string]uint8{ "min": member.DelegateMin, "max": member.DelegateMax, "version": member.DelegateCur, }, }) } output, err := formatOutput(result, format) if err != nil { c.Ui.Error(fmt.Sprintf("Encoding error: %s", err)) return 1 } c.Ui.Output(string(output)) return 0 }