github.com/iron-io/functions@v0.0.0-20180820112432-d59d7d1c40b2/fn/app/app.go (about) 1 package app 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "strings" 8 9 vers "github.com/iron-io/functions/api/version" 10 "github.com/iron-io/functions/fn/commands" 11 image_commands "github.com/iron-io/functions/fn/commands/images" 12 "github.com/iron-io/functions/fn/common" 13 "github.com/urfave/cli" 14 ) 15 16 var aliases = map[string]cli.Command{ 17 "build": image_commands.Build(), 18 "bump": image_commands.Bump(), 19 "deploy": image_commands.Deploy(), 20 "push": image_commands.Push(), 21 "run": image_commands.Run(), 22 "call": commands.Call(), 23 } 24 25 func aliasesFn() []cli.Command { 26 cmds := []cli.Command{} 27 for alias, cmd := range aliases { 28 cmd.Name = alias 29 cmd.Hidden = true 30 cmds = append(cmds, cmd) 31 } 32 return cmds 33 } 34 35 func NewFn() *cli.App { 36 common.SetEnv() 37 app := cli.NewApp() 38 app.Name = "fn" 39 app.Version = vers.Version 40 app.Authors = []cli.Author{{Name: "iron.io"}} 41 app.Description = "IronFunctions command line tools" 42 app.UsageText = `Check the manual at https://github.com/iron-io/functions/blob/master/fn/README.md` 43 44 cli.AppHelpTemplate = `{{.Name}} {{.Version}}{{if .Description}} 45 46 {{.Description}}{{end}} 47 48 USAGE: 49 {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}} 50 51 ENVIRONMENT VARIABLES: 52 API_URL - IronFunctions remote API address{{if .VisibleCommands}} 53 54 COMMANDS:{{range .VisibleCategories}}{{if .Name}} 55 {{.Name}}:{{end}}{{range .VisibleCommands}} 56 {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} 57 58 ALIASES: 59 build (images build) 60 bump (images bump) 61 deploy (images deploy) 62 run (images run) 63 call (routes call) 64 push (images push) 65 66 GLOBAL OPTIONS: 67 {{range $index, $option := .VisibleFlags}}{{if $index}} 68 {{end}}{{$option}}{{end}}{{end}} 69 ` 70 71 app.CommandNotFound = func(c *cli.Context, cmd string) { 72 fmt.Fprintf(os.Stderr, "command not found: %v\n", cmd) 73 } 74 app.Commands = []cli.Command{ 75 commands.InitFn(), 76 commands.Apps(), 77 commands.Routes(), 78 commands.Images(), 79 commands.Lambda(), 80 commands.Version(), 81 } 82 app.Commands = append(app.Commands, aliasesFn()...) 83 84 prepareCmdArgsValidation(app.Commands) 85 86 return app 87 } 88 89 func parseArgs(c *cli.Context) ([]string, []string) { 90 args := strings.Split(c.Command.ArgsUsage, " ") 91 var reqArgs []string 92 var optArgs []string 93 for _, arg := range args { 94 if strings.HasPrefix(arg, "[") { 95 optArgs = append(optArgs, arg) 96 } else if strings.Trim(arg, " ") != "" { 97 reqArgs = append(reqArgs, arg) 98 } 99 } 100 return reqArgs, optArgs 101 } 102 103 func prepareCmdArgsValidation(cmds []cli.Command) { 104 // TODO: refactor fn to use urfave/cli.v2 105 // v1 doesn't let us validate args before the cmd.Action 106 107 for i, cmd := range cmds { 108 prepareCmdArgsValidation(cmd.Subcommands) 109 if cmd.Action == nil { 110 continue 111 } 112 action := cmd.Action 113 cmd.Action = func(c *cli.Context) error { 114 reqArgs, _ := parseArgs(c) 115 if c.NArg() < len(reqArgs) { 116 var help bytes.Buffer 117 cli.HelpPrinter(&help, cli.CommandHelpTemplate, c.Command) 118 return fmt.Errorf("ERROR: Missing required arguments: %s\n\n%s", strings.Join(reqArgs[c.NArg():], " "), help.String()) 119 } 120 return cli.HandleAction(action, c) 121 } 122 cmds[i] = cmd 123 } 124 }