github.com/devcamcar/cli@v0.0.0-20181107134215-706a05759d18/commands/invoke.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  
     7  	"github.com/fnproject/cli/client"
     8  	"github.com/fnproject/cli/common"
     9  	"github.com/fnproject/cli/objects/app"
    10  	"github.com/fnproject/cli/objects/fn"
    11  	"github.com/fnproject/fn_go/clientv2"
    12  	"github.com/fnproject/fn_go/provider"
    13  	"github.com/urfave/cli"
    14  	"errors"
    15  )
    16  
    17  // FnInvokeEndpointAnnotation is the annotation that exposes the fn invoke endpoint as defined in models/fn.go
    18  const FnInvokeEndpointAnnotation = "fnproject.io/fn/invokeEndpoint"
    19  
    20  type invokeCmd struct {
    21  	provider provider.Provider
    22  	client   *clientv2.Fn
    23  }
    24  
    25  // InvokeFnFlags used to invoke and fn
    26  var InvokeFnFlags = []cli.Flag{
    27  	cli.StringFlag{
    28  		Name:  "endpoint",
    29  		Usage: "Specify the function invoke endpoint for this function, the app-name and func-name parameters will be ignored",
    30  	},
    31  	cli.StringFlag{
    32  		Name:  "method",
    33  		Usage: "Http method for function",
    34  	},
    35  	cli.StringFlag{
    36  		Name:  "content-type",
    37  		Usage: "The payload Content-Type for the function invocation.",
    38  	},
    39  	cli.BoolFlag{
    40  		Name:  "display-call-id",
    41  		Usage: "whether display call ID or not",
    42  	},
    43  }
    44  
    45  // InvokeCommand returns call cli.command
    46  func InvokeCommand() cli.Command {
    47  	cl := invokeCmd{}
    48  	return cli.Command{
    49  		Name:    "invoke",
    50  		Usage:   "\tInvoke a remote function",
    51  		Aliases: []string{"iv"},
    52  		Before: func(c *cli.Context) error {
    53  			var err error
    54  			cl.provider, err = client.CurrentProvider()
    55  			if err != nil {
    56  				return err
    57  			}
    58  			cl.client = cl.provider.APIClientv2()
    59  			return nil
    60  		},
    61  		ArgsUsage:   "[app-name] [function-name]",
    62  		Flags:       InvokeFnFlags,
    63  		Category:    "DEVELOPMENT COMMANDS",
    64  		Description: "This command explicitly invokes a function.",
    65  		Action:      cl.Invoke,
    66  	}
    67  }
    68  
    69  func (cl *invokeCmd) Invoke(c *cli.Context) error {
    70  	var contentType string
    71  
    72  	invokeURL := c.String("endpoint")
    73  
    74  	if invokeURL == "" {
    75  
    76  		appName := c.Args().Get(0)
    77  		fnName := c.Args().Get(1)
    78  
    79  		if appName == "" || fnName == "" {
    80  			return errors.New("missing app and function name")
    81  		}
    82  
    83  		app, err := app.GetAppByName(cl.client, appName)
    84  		if err != nil {
    85  			return err
    86  		}
    87  		fn, err := fn.GetFnByName(cl.client, app.ID, fnName)
    88  		if err != nil {
    89  			return err
    90  		}
    91  		var ok bool
    92  		invokeURL, ok = fn.Annotations[FnInvokeEndpointAnnotation].(string)
    93  		if !ok {
    94  			return fmt.Errorf("Fn invoke url annotation not present, %s", FnInvokeEndpointAnnotation)
    95  		}
    96  	}
    97  	content := stdin()
    98  	wd := common.GetWd()
    99  
   100  	if c.String("content-type") != "" {
   101  		contentType = c.String("content-type")
   102  	} else {
   103  		_, ff, err := common.FindAndParseFuncFileV20180708(wd)
   104  		if err == nil && ff.Content_type != "" {
   105  			contentType = ff.Content_type
   106  		}
   107  	}
   108  
   109  	return client.Invoke(cl.provider, invokeURL, content, os.Stdout, c.String("method"), c.StringSlice("e"), contentType, c.Bool("display-call-id"))
   110  }