diff --git a/command/event.go b/command/event.go new file mode 100644 index 0000000000..d0030d1e73 --- /dev/null +++ b/command/event.go @@ -0,0 +1,139 @@ +package command + +import ( + "flag" + "fmt" + "regexp" + "strings" + + "github.com/armon/consul-api" + "github.com/mitchellh/cli" +) + +// EventCommand is a Command implementation that is used to +// fire new events +type EventCommand struct { + Ui cli.Ui +} + +func (c *EventCommand) Help() string { + helpText := ` +Usage: consul event [options] [payload] + + Dispatches a custom user event across a datacenter. An event must provide + a name, but a payload is optional. Events support filtering using + regular expressions on node name, service, and tag definitions. + +Options: + + -http-addr=127.0.0.1:8500 HTTP address of the Consul agent. + -datacenter="" Datacenter to dispatch in. Defaults to that of agent. + -name="" Name of the event. + -node="" Regular expression to filter on node names + -service="" Regular expression to filter on service instances + -tag="" Regular expression to filter on service tags. Must be used + with -service. +` + return strings.TrimSpace(helpText) +} + +func (c *EventCommand) Run(args []string) int { + var datacenter, name, node, service, tag string + cmdFlags := flag.NewFlagSet("event", flag.ContinueOnError) + cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } + cmdFlags.StringVar(&datacenter, "datacenter", "", "") + cmdFlags.StringVar(&name, "name", "", "") + cmdFlags.StringVar(&node, "node", "", "") + cmdFlags.StringVar(&service, "service", "", "") + cmdFlags.StringVar(&tag, "tag", "", "") + httpAddr := HTTPAddrFlag(cmdFlags) + if err := cmdFlags.Parse(args); err != nil { + return 1 + } + + // Check for a name + if name == "" { + c.Ui.Error("Event name must be specified") + c.Ui.Error("") + c.Ui.Error(c.Help()) + return 1 + } + + // Validate the filters + if node != "" { + if _, err := regexp.Compile(node); err != nil { + c.Ui.Error(fmt.Sprintf("Failed to compile node filter regexp: %v", err)) + return 1 + } + } + if service != "" { + if _, err := regexp.Compile(service); err != nil { + c.Ui.Error(fmt.Sprintf("Failed to compile service filter regexp: %v", err)) + return 1 + } + } + if tag != "" { + if _, err := regexp.Compile(tag); err != nil { + c.Ui.Error(fmt.Sprintf("Failed to compile tag filter regexp: %v", err)) + return 1 + } + } + if tag != "" && service == "" { + c.Ui.Error("Cannot provide tag filter without service filter.") + return 1 + } + + // Check for a payload + var payload []byte + args = cmdFlags.Args() + switch len(args) { + case 0: + case 1: + payload = []byte(args[0]) + default: + c.Ui.Error("Too many command line arguments.") + c.Ui.Error("") + c.Ui.Error(c.Help()) + return 1 + } + + // Create and test the HTTP client + client, err := HTTPClient(*httpAddr) + if err != nil { + c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) + return 1 + } + _, err = client.Agent().NodeName() + if err != nil { + c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err)) + return 1 + } + + // Prepare the request + event := client.Event() + params := &consulapi.UserEvent{ + Name: name, + Payload: payload, + NodeFilter: node, + ServiceFilter: service, + TagFilter: tag, + } + opts := &consulapi.WriteOptions{ + Datacenter: datacenter, + } + + // Fire the event + id, _, err := event.Fire(params, opts) + if err != nil { + c.Ui.Error(fmt.Sprintf("Error firing event: %s", err)) + return 1 + } + + // Write out the ID + c.Ui.Output(fmt.Sprintf("Event ID: %s", id)) + return 0 +} + +func (c *EventCommand) Synopsis() string { + return "Fire a new event" +} diff --git a/command/event_test.go b/command/event_test.go new file mode 100644 index 0000000000..ee4b929a03 --- /dev/null +++ b/command/event_test.go @@ -0,0 +1,29 @@ +package command + +import ( + "github.com/mitchellh/cli" + "strings" + "testing" +) + +func TestEventCommand_implements(t *testing.T) { + var _ cli.Command = &WatchCommand{} +} + +func TestEventCommandRun(t *testing.T) { + a1 := testAgent(t) + defer a1.Shutdown() + + ui := new(cli.MockUi) + c := &EventCommand{Ui: ui} + args := []string{"-http-addr=" + a1.httpAddr, "-name=cmd"} + + code := c.Run(args) + if code != 0 { + t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String()) + } + + if !strings.Contains(ui.OutputWriter.String(), "Event ID: ") { + t.Fatalf("bad: %#v", ui.OutputWriter.String()) + } +} diff --git a/commands.go b/commands.go index 1b98e013af..f68cf20801 100644 --- a/commands.go +++ b/commands.go @@ -25,6 +25,12 @@ func init() { }, nil }, + "event": func() (cli.Command, error) { + return &command.EventCommand{ + Ui: ui, + }, nil + }, + "force-leave": func() (cli.Command, error) { return &command.ForceLeaveCommand{ Ui: ui,