Refactored msgbus client CLI to use cobra

This commit is contained in:
James Mills 2018-03-01 00:17:22 +00:00
parent 1dded6cc6b
commit 2f7d09660f
No known key found for this signature in database
GPG Key ID: AC4C014F1440EBD6
5 changed files with 237 additions and 84 deletions

View File

@ -1,88 +1,5 @@
package main
import (
"flag"
"io/ioutil"
"log"
"os"
"os/signal"
"syscall"
"github.com/prologic/msgbus/client"
)
const defaultTopic = "hello"
func main() {
var url string
flag.StringVar(
&url, "url",
"http://localhost:8000", "url to connect to",
)
flag.Parse()
client := client.NewClient(url, nil)
if flag.Arg(0) == "sub" {
subscribe(client, flag.Arg(1))
} else if flag.Arg(0) == "pub" {
publish(client, flag.Arg(1), flag.Arg(2))
} else if flag.Arg(0) == "pull" {
pull(client, flag.Arg(1))
} else {
log.Fatalf("invalid command %s", flag.Arg(0))
}
}
func publish(client *client.Client, topic, message string) {
if topic == "" {
topic = defaultTopic
}
if message == "" || message == "-" {
log.Printf("Reading message from stdin...\n")
buf, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("error reading message from stdin: %s", err)
}
message = string(buf[:])
}
err := client.Publish(topic, message)
if err != nil {
log.Fatalf("error publishing message: %s", err)
}
}
func pull(client *client.Client, topic string) {
if topic == "" {
topic = defaultTopic
}
client.Pull(topic)
}
func subscribe(client *client.Client, topic string) {
if topic == "" {
topic = defaultTopic
}
s := client.Subscribe(topic)
go s.Run()
sigs := make(chan os.Signal, 1)
done := make(chan bool, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigs
log.Printf("caught signal %s: ", sig)
s.Stop()
done <- true
}()
<-done
Execute()
}

67
cmd/msgbus/pub.go Normal file
View File

@ -0,0 +1,67 @@
package main
import (
"io/ioutil"
"log"
"os"
"github.com/spf13/cobra"
"github.com/prologic/msgbus/client"
)
// pubCmd represents the pub command
var pubCmd = &cobra.Command{
Use: "pub [flags] <topic> [<message>|-]",
Short: "Publish a new message",
Long: `This publishes a new message either from positional command-line
arguments or from standard input if - is used as the first and only argument.
This is an asynchronous operation and does not wait for a response unless the
-w/--wait option is also present.`,
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
uri := cmd.Flag("uri").Value.String()
client := client.NewClient(uri, nil)
topic := args[0]
message := ""
if len(args) == 2 {
message = args[1]
}
publish(client, topic, message)
},
}
func init() {
RootCmd.AddCommand(pubCmd)
pubCmd.Flags().BoolP(
"wait", "w", false,
"Waits for a response and prints it before terminating",
)
}
const defaultTopic = "hello"
func publish(client *client.Client, topic, message string) {
if topic == "" {
topic = defaultTopic
}
if message == "" || message == "-" {
log.Printf("Reading message from stdin...\n")
buf, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("error reading message from stdin: %s", err)
}
message = string(buf[:])
}
err := client.Publish(topic, message)
if err != nil {
log.Fatalf("error publishing message: %s", err)
}
}

40
cmd/msgbus/pull.go Normal file
View File

@ -0,0 +1,40 @@
package main
import (
"github.com/spf13/cobra"
"github.com/prologic/msgbus/client"
)
// pullCmd represents the pub command
var pullCmd = &cobra.Command{
Use: "pull [flags] <topic>",
Short: "Pulls a message from a given topic",
Long: `This pulls a message from the given topic if there are any messages
and prints the message to standard output. Otherwise if the queue for the
given topic is empty, this does nothing.
This is primarily useful in situations where a subscription was lost and you
want to "catch up" and pull any messages left in the queue for that topic.`,
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
uri := cmd.Flag("uri").Value.String()
client := client.NewClient(uri, nil)
topic := args[0]
pull(client, topic)
},
}
func init() {
RootCmd.AddCommand(pullCmd)
}
func pull(client *client.Client, topic string) {
if topic == "" {
topic = defaultTopic
}
client.Pull(topic)
}

73
cmd/msgbus/root.go Normal file
View File

@ -0,0 +1,73 @@
package main
import (
"fmt"
"os"
"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var configFile string
// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
Use: "msgbus",
Short: "Command-line client for msgbus",
Long: `This is the command-line client for the msgbus daemon msgbusd.
This lets you publish, subscribe and pull messages from a running msgbusd
instance. This is the reference implementation of using the msgbus client
library for publishing and subscribing to topics.`,
}
// Execute adds all child commands to the root command
// and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := RootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func init() {
cobra.OnInitialize(initConfig)
RootCmd.PersistentFlags().StringVar(
&configFile, "config", "",
"config file (default is $HOME/.msgbus.yaml)",
)
RootCmd.PersistentFlags().StringP(
"uri", "u", "http://localhost:8000",
"URI to connect to msgbusd",
)
}
// initConfig reads in config file and ENV variables if set.
func initConfig() {
if configFile != "" {
// Use config file from the flag.
viper.SetConfigFile(configFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// Search config in home directory with name ".cobra-example" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".cobra-example")
}
viper.AutomaticEnv() // read in environment variables that match
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
fmt.Println("Using config file:", viper.ConfigFileUsed())
}
}

56
cmd/msgbus/sub.go Normal file
View File

@ -0,0 +1,56 @@
package main
import (
"log"
"os"
"os/signal"
"syscall"
"github.com/spf13/cobra"
"github.com/prologic/msgbus/client"
)
// subCmd represents the pub command
var subCmd = &cobra.Command{
Use: "sub [flags] <topic>",
Short: "Subscribe to a topic",
Long: `This subscribes to the given topic and for every message published
to the topic, the message is printed to standard output.`,
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
uri := cmd.Flag("uri").Value.String()
client := client.NewClient(uri, nil)
topic := args[0]
subscribe(client, topic)
},
}
func init() {
RootCmd.AddCommand(subCmd)
}
func subscribe(client *client.Client, topic string) {
if topic == "" {
topic = defaultTopic
}
s := client.Subscribe(topic)
go s.Run()
sigs := make(chan os.Signal, 1)
done := make(chan bool, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigs
log.Printf("caught signal %s: ", sig)
s.Stop()
done <- true
}()
<-done
}