github.com/projectriff/riff-cli@v0.0.5-0.20180301104501-5db7a3bd9fc1/cmd/publish.go (about)

     1  /*
     2   * Copyright 2018 the original author or authors.
     3   *
     4   *   Licensed under the Apache License, Version 2.0 (the "License");
     5   *   you may not use this file except in compliance with the License.
     6   *   You may obtain a copy of the License at
     7   *  
     8   *        http://www.apache.org/licenses/LICENSE-2.0
     9   *  
    10   *   Unless required by applicable law or agreed to in writing, software
    11   *   distributed under the License is distributed on an "AS IS" BASIS,
    12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   *   See the License for the specific language governing permissions and
    14   *   limitations under the License.
    15   */
    16  
    17  package cmd
    18  
    19  import (
    20  	"strings"
    21  	"fmt"
    22  	"net/http"
    23  	"io/ioutil"
    24  	"time"
    25  
    26  	"github.com/spf13/cobra"
    27  	"github.com/projectriff/riff-cli/pkg/kubectl"
    28  	"github.com/projectriff/riff-cli/pkg/ioutils"
    29  	"github.com/projectriff/riff-cli/pkg/minikube"
    30  	"github.com/projectriff/riff-cli/pkg/jsonpath"
    31  	"github.com/projectriff/riff-cli/pkg/osutils"
    32  	"github.com/projectriff/riff-cli/cmd/utils"
    33  	"github.com/spf13/viper"
    34  )
    35  
    36  type PublishOptions struct {
    37  	namespace string
    38  	input string
    39  	data  string
    40  	reply bool
    41  	count int
    42  	pause int
    43  }
    44  
    45  var publishOptions PublishOptions
    46  
    47  // publishCmd represents the publish command
    48  var publishCmd = &cobra.Command{
    49  	Use:   "publish",
    50  	Short: "Publish data to a topic using the http-gateway",
    51  	Long: `Publish data to a topic using the http-gateway. For example:
    52  
    53      riff publish -i greetings -d hello -r
    54  
    55  will post 'hello' to the 'greetings' topic and wait for a reply.
    56  `,
    57  	Run: func(cmd *cobra.Command, args []string) {
    58  
    59  		// get the viper value from env var, config file or flag option
    60  		publishOptions.namespace = utils.GetStringValueWithOverride("namespace", *cmd.Flags())
    61  
    62  		// look for PUBLISH_NAMESPACE
    63  		if !cmd.Flags().Changed("namespace") && viper.GetString("PUBLISH_NAMESPACE") != "" {
    64  			publishOptions.namespace = viper.GetString("PUBLISH_NAMESPACE")
    65  			fmt.Printf("Using namespace: %s\n", publishOptions.namespace)
    66  		} else {
    67  			// look for publishNamespace
    68  			if !cmd.Flags().Changed("namespace") && viper.GetString("publishNamespace") != "" {
    69  				publishOptions.namespace = viper.GetString("publishNamespace")
    70  				fmt.Printf("Using namespace: %s\n", publishOptions.namespace)
    71  			}
    72  		}
    73  
    74  		cmdArgs := []string{"get", "--namespace", publishOptions.namespace, "svc", "-l", "component=http-gateway", "-o", "json"}
    75  		output, err := kubectl.ExecForBytes(cmdArgs)
    76  
    77  		if err != nil {
    78  			ioutils.Errorf("Error querying http-gateway %v\n %v\n", err, output)
    79  			return
    80  		}
    81  
    82  		parser := jsonpath.NewParser(output)
    83  
    84  		portType := parser.Value(`$.items[0].spec.type+`)
    85  
    86  		if portType == "" {
    87  			ioutils.Errorf("Unable to locate http-gateway in namespace %v\n", publishOptions.namespace)
    88  			return
    89  		}
    90  
    91  		var ipAddress string
    92  		var port string
    93  
    94  		switch portType {
    95  		case "NodePort":
    96  			ipAddress, err = minikube.QueryIp()
    97  			if err != nil || strings.Contains(ipAddress, "Error getting IP") {
    98  				ipAddress = "127.0.0.1"
    99  			}
   100  			port = parser.Value(`$.items[0].spec.ports[*]?(@.name == "http").nodePort+`)
   101  		case "LoadBalancer":
   102  			ipAddress = parser.Value(`$.items[0].status.loadBalancer.ingress[0].ip+`)
   103  			if ipAddress == "" {
   104  				ioutils.Error("unable to determine http-gateway ip address")
   105  				return
   106  			}
   107  			port = parser.Value(`$.items[0].spec.ports[*]?(@.name == "http").port+`)
   108  
   109  		default:
   110  			ioutils.Errorf("Unkown port type %s", portType)
   111  			return
   112  		}
   113  
   114  		if port == "" {
   115  			ioutils.Error("Unable to determine gateway port")
   116  			return
   117  		}
   118  
   119  		publish(ipAddress, port)
   120  
   121  	},
   122  }
   123  
   124  func publish(ipAddress string, port string) {
   125  	resource := "messages"
   126  	if publishOptions.reply {
   127  		resource = "requests"
   128  	}
   129  
   130  	url := fmt.Sprintf("http://%s:%s/%s/%s", ipAddress, port, resource, publishOptions.input)
   131  
   132  	fmt.Printf("Posting to %s\n", url)
   133  
   134  	for i := 0; i < publishOptions.count; i++ {
   135  
   136  		resp, err := http.Post(url, "text/plain", strings.NewReader(publishOptions.data))
   137  		if err != nil {
   138  			panic(err)
   139  		}
   140  
   141  		defer resp.Body.Close()
   142  		body, err := ioutil.ReadAll(resp.Body)
   143  		if err != nil {
   144  			panic(err)
   145  		}
   146  		fmt.Println(string(body))
   147  
   148  		if (publishOptions.pause > 0) {
   149  			time.Sleep(time.Duration(publishOptions.pause) * time.Second)
   150  		}
   151  	}
   152  }
   153  
   154  func init() {
   155  	rootCmd.AddCommand(publishCmd)
   156  
   157  	// Here you will define your flags and configuration settings.
   158  
   159  	// Cobra supports Persistent Flags which will work for this command
   160  	// and all subcommands, e.g.:
   161  	// publishCmd.PersistentFlags().String("foo", "", "A help for foo")
   162  
   163  	// Cobra supports local flags which will only run when this command
   164  	// is called directly, e.g.:
   165  	// publishCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
   166  
   167  	publishCmd.Flags().StringVarP(&publishOptions.data, "data", "d", "", "the data to post to the http-gateway using the input topic")
   168  	publishCmd.Flags().StringVarP(&publishOptions.input, "input", "i", osutils.GetCWDBasePath(), "the name of the input topic, defaults to name of current directory")
   169  	publishCmd.Flags().BoolVarP(&publishOptions.reply, "reply", "r", false, "wait for a reply containing the results of the function execution")
   170  	publishCmd.Flags().IntVarP(&publishOptions.count, "count", "c", 1, "the number of times to post the data")
   171  	publishCmd.Flags().IntVarP(&publishOptions.pause, "pause", "p", 0, "the number of seconds to wait between postings")
   172  
   173  	publishCmd.Flags().StringP("namespace", "", "default", "the namespace of the http-gateway")
   174  
   175  	publishCmd.MarkFlagRequired("data")
   176  
   177  }