diff --git a/README.md b/README.md index 99a80afc8..bc30d2cc7 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,7 @@ can use -- yes, you can share functions! The source code for this function is in You can read more about [writing your own functions here](docs/writing.md). ```sh -fn routes create myapp /hello iron/hello +fn routes create myapp /hello -i iron/hello ``` Or using cURL: diff --git a/docs/definitions.md b/docs/definitions.md index 8ad9b113e..87d13a6ce 100644 --- a/docs/definitions.md +++ b/docs/definitions.md @@ -58,7 +58,7 @@ Note: Route level configuration overrides app level configuration. Using `fn`: ```sh -fn routes create --config k1=v1 --config k2=v2 myapp /path image +fn routes create myapp /path --config k1=v1 --config k2=v2 --image iron/hello ``` Or using a cURL: diff --git a/examples/hash/README.md b/examples/hash/README.md index ea8cd8c41..aaf247dbf 100644 --- a/examples/hash/README.md +++ b/examples/hash/README.md @@ -34,7 +34,7 @@ This will create a docker image and push the image to docker. ## Publishing to IronFunctions ```bash -fn routes create +fn routes create ``` This creates a full path in the form of `http://:/r//` diff --git a/fn/apps.go b/fn/apps.go index ac645ad8b..54617458d 100644 --- a/fn/apps.go +++ b/fn/apps.go @@ -24,15 +24,14 @@ func apps() cli.Command { a := appsCmd{client: apiClient()} return cli.Command{ - Name: "apps", - Usage: "manage applications", - ArgsUsage: "fn apps", + Name: "apps", + Usage: "manage applications", Subcommands: []cli.Command{ { Name: "create", Aliases: []string{"c"}, Usage: "create a new app", - ArgsUsage: "`app`", + ArgsUsage: "", Action: a.create, Flags: []cli.Flag{ cli.StringSliceFlag{ @@ -45,14 +44,14 @@ func apps() cli.Command { Name: "inspect", Aliases: []string{"i"}, Usage: "retrieve one or all apps properties", - ArgsUsage: "`app` [property.[key]]", + ArgsUsage: " [property.[key]]", Action: a.inspect, }, { Name: "update", Aliases: []string{"u"}, Usage: "update an `app`", - ArgsUsage: "`app`", + ArgsUsage: "", Action: a.update, Flags: []cli.Flag{ cli.StringSliceFlag{ @@ -69,14 +68,14 @@ func apps() cli.Command { Name: "set", Aliases: []string{"s"}, Usage: "store a configuration key for this application", - ArgsUsage: "`app` ", + ArgsUsage: " ", Action: a.configSet, }, { Name: "unset", Aliases: []string{"u"}, Usage: "remove a configuration key for this application", - ArgsUsage: "`app` ", + ArgsUsage: " ", Action: a.configUnset, }, }, @@ -124,10 +123,6 @@ func (a *appsCmd) list(c *cli.Context) error { } func (a *appsCmd) create(c *cli.Context) error { - if c.Args().First() == "" { - return errors.New("error: missing app name after create command") - } - body := &models.AppWrapper{App: &models.App{ Name: c.Args().Get(0), Config: extractEnvConfig(c.StringSlice("config")), @@ -155,10 +150,6 @@ func (a *appsCmd) create(c *cli.Context) error { } func (a *appsCmd) update(c *cli.Context) error { - if c.Args().First() == "" { - return errors.New("error: missing app name after update command") - } - appName := c.Args().First() patchedApp := &functions.App{ @@ -175,10 +166,6 @@ func (a *appsCmd) update(c *cli.Context) error { } func (a *appsCmd) configSet(c *cli.Context) error { - if c.Args().Get(0) == "" || c.Args().Get(1) == "" || c.Args().Get(2) == "" { - return errors.New("error: application configuration setting takes three arguments: an app name, a key and a value") - } - appName := c.Args().Get(0) key := c.Args().Get(1) value := c.Args().Get(2) @@ -198,10 +185,6 @@ func (a *appsCmd) configSet(c *cli.Context) error { } func (a *appsCmd) configUnset(c *cli.Context) error { - if c.Args().Get(0) == "" || c.Args().Get(1) == "" { - return errors.New("error: application configuration setting takes three arguments: an app name, a key and a value") - } - appName := c.Args().Get(0) key := c.Args().Get(1) diff --git a/fn/deploy.go b/fn/deploy.go index be0ba9f5a..90aba0208 100644 --- a/fn/deploy.go +++ b/fn/deploy.go @@ -21,7 +21,7 @@ func deploy() cli.Command { flags = append(flags, cmd.flags()...) return cli.Command{ Name: "deploy", - ArgsUsage: "`APPNAME`", + ArgsUsage: "", Usage: "scan local directory for functions, build and push all of them to `APPNAME`.", Flags: flags, Action: cmd.scan, @@ -68,9 +68,6 @@ func (p *deploycmd) flags() []cli.Flag { } func (p *deploycmd) scan(c *cli.Context) error { - if c.Args().First() == "" { - return errors.New("application name is missing") - } p.appName = c.Args().First() p.verbwriter = verbwriter(p.verbose) diff --git a/fn/images.go b/fn/images.go index 03e08b83a..bd36e5562 100644 --- a/fn/images.go +++ b/fn/images.go @@ -11,9 +11,8 @@ type imagesCmd struct { func images() cli.Command { return cli.Command{ - Name: "images", - Usage: "manage function images", - ArgsUsage: "fn images", + Name: "images", + Usage: "manage function images", Subcommands: []cli.Command{ build(), deploy(), diff --git a/fn/lambda.go b/fn/lambda.go index 13ad2fa2b..e497c4807 100644 --- a/fn/lambda.go +++ b/fn/lambda.go @@ -35,28 +35,27 @@ func lambda() cli.Command { flags = append(flags, getFlags()...) return cli.Command{ - Name: "lambda", - Usage: "create and publish lambda functions", - ArgsUsage: "fn lambda", + Name: "lambda", + Usage: "create and publish lambda functions", Subcommands: []cli.Command{ { Name: "create-function", Usage: `create Docker image that can run your Lambda function, where files are the contents of the zip file to be uploaded to AWS Lambda.`, - ArgsUsage: "name runtime handler /path [/paths...]", + ArgsUsage: " [/paths...]", Action: create, Flags: flags, }, { Name: "test-function", Usage: `runs local dockerized Lambda function and writes output to stdout.`, - ArgsUsage: "name [--payload ]", + ArgsUsage: "", Action: test, Flags: flags, }, { Name: "aws-import", Usage: `converts an existing Lambda function to an image, where the function code is downloaded to a directory in the current working directory that has the same name as the Lambda function.`, - ArgsUsage: "arn region image/name [--profile ] [--version ] [--download-only]", + ArgsUsage: " ", Action: awsImport, Flags: flags, }, @@ -103,9 +102,6 @@ func transcribeEnvConfig(configs []string) map[string]string { func create(c *cli.Context) error { args := c.Args() - if len(args) < 4 { - return fmt.Errorf("Expected at least 4 arguments, NAME RUNTIME HANDLER and file %d", len(args)) - } functionName := args[0] runtime := args[1] handler := args[2] @@ -186,9 +182,6 @@ func test(c *cli.Context) error { func awsImport(c *cli.Context) error { args := c.Args() - if len(args) < 3 { - return fmt.Errorf("Missing arguments ARN, REGION and/or IMAGE") - } version := c.String("version") downloadOnly := c.Bool("download-only") diff --git a/fn/main.go b/fn/main.go index 7433d124a..f11167b7e 100644 --- a/fn/main.go +++ b/fn/main.go @@ -1,9 +1,11 @@ package main import ( + "bytes" "fmt" "net/url" "os" + "strings" vers "github.com/iron-io/functions/api/version" functions "github.com/iron-io/functions_go" @@ -76,9 +78,49 @@ GLOBAL OPTIONS: version(), } app.Commands = append(app.Commands, aliasesFn()...) + + prepareCmdArgsValidation(app.Commands) + return app } +func parseArgs(c *cli.Context) ([]string, []string) { + args := strings.Split(c.Command.ArgsUsage, " ") + var reqArgs []string + var optArgs []string + for _, arg := range args { + if strings.HasPrefix(arg, "[") { + optArgs = append(optArgs, arg) + } else { + reqArgs = append(reqArgs, arg) + } + } + return reqArgs, optArgs +} + +func prepareCmdArgsValidation(cmds []cli.Command) { + // TODO: refactor fn to use urfave/cli.v2 + // v1 doesn't let us validate args before the cmd.Action + + for i, cmd := range cmds { + prepareCmdArgsValidation(cmd.Subcommands) + if cmd.Action == nil { + continue + } + action := cmd.Action + cmd.Action = func(c *cli.Context) error { + reqArgs, _ := parseArgs(c) + if c.NArg() < len(reqArgs) { + var help bytes.Buffer + cli.HelpPrinter(&help, cli.CommandHelpTemplate, c.Command) + return fmt.Errorf("ERROR: Missing required arguments: %s\n\n%s", strings.Join(reqArgs[c.NArg():], " "), help.String()) + } + return cli.HandleAction(action, c) + } + cmds[i] = cmd + } +} + func main() { app := newFn() app.Run(os.Args) diff --git a/fn/routes.go b/fn/routes.go index 680d5433d..d8351fc39 100644 --- a/fn/routes.go +++ b/fn/routes.go @@ -12,7 +12,6 @@ import ( "path" "strings" "text/tabwriter" - "time" fnclient "github.com/iron-io/functions_go/client" apiroutes "github.com/iron-io/functions_go/client/routes" @@ -26,19 +25,53 @@ type routesCmd struct { client *fnclient.Functions } +var routeFlags = []cli.Flag{ + cli.StringFlag{ + Name: "image,i", + Usage: "image name", + }, + cli.Int64Flag{ + Name: "memory,m", + Usage: "memory in MiB", + }, + cli.StringFlag{ + Name: "type,t", + Usage: "route type - sync or async", + }, + cli.StringSliceFlag{ + Name: "config,c", + Usage: "route configuration", + }, + cli.StringSliceFlag{ + Name: "headers", + Usage: "route response headers", + }, + cli.StringFlag{ + Name: "format,f", + Usage: "hot container IO format - json or http", + }, + cli.IntFlag{ + Name: "max-concurrency,mc", + Usage: "maximum concurrency for hot container", + }, + cli.DurationFlag{ + Name: "timeout", + Usage: "route timeout (eg. 30s)", + }, +} + func routes() cli.Command { r := routesCmd{client: apiClient()} return cli.Command{ - Name: "routes", - Usage: "manage routes", - ArgsUsage: "fn routes", + Name: "routes", + Usage: "manage routes", Subcommands: []cli.Command{ { Name: "call", Usage: "call a route", - ArgsUsage: "`app` /path", + ArgsUsage: " [image]", Action: r.call, Flags: runflags(), }, @@ -46,87 +79,24 @@ func routes() cli.Command { Name: "list", Aliases: []string{"l"}, Usage: "list routes for `app`", - ArgsUsage: "`app`", + ArgsUsage: "", Action: r.list, }, { Name: "create", Aliases: []string{"c"}, Usage: "create a route in an `app`", - ArgsUsage: "`app` /path [image]", + ArgsUsage: " ", Action: r.create, - Flags: []cli.Flag{ - cli.Int64Flag{ - Name: "memory,m", - Usage: "memory in MiB", - Value: 128, - }, - cli.StringFlag{ - Name: "type,t", - Usage: "route type - sync or async", - Value: "sync", - }, - cli.StringSliceFlag{ - Name: "config,c", - Usage: "route configuration", - }, - cli.StringFlag{ - Name: "format,f", - Usage: "hot function IO format - json or http", - Value: "", - }, - cli.IntFlag{ - Name: "max-concurrency", - Usage: "maximum concurrency for hot function", - Value: 1, - }, - cli.DurationFlag{ - Name: "timeout", - Usage: "route timeout", - Value: 30 * time.Second, - }, - }, + Flags: routeFlags, }, { Name: "update", Aliases: []string{"u"}, Usage: "update a route in an `app`", - ArgsUsage: "`app` /path [image]", + ArgsUsage: " ", Action: r.update, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "image,i", - Usage: "image name", - }, - cli.Int64Flag{ - Name: "memory,m", - Usage: "memory in MiB", - }, - cli.StringFlag{ - Name: "type,t", - Usage: "route type - sync or async", - }, - cli.StringSliceFlag{ - Name: "config,c", - Usage: "route configuration", - }, - cli.StringSliceFlag{ - Name: "headers", - Usage: "route response headers", - }, - cli.StringFlag{ - Name: "format,f", - Usage: "hot container IO format - json or http", - }, - cli.IntFlag{ - Name: "max-concurrency,mc", - Usage: "maximum concurrency for hot container", - }, - cli.DurationFlag{ - Name: "timeout", - Usage: "route timeout (eg. 30s)", - }, - }, + Flags: routeFlags, }, { Name: "config", @@ -136,14 +106,14 @@ func routes() cli.Command { Name: "set", Aliases: []string{"s"}, Usage: "store a configuration key for this route", - ArgsUsage: "`app` /path ", + ArgsUsage: " ", Action: r.configSet, }, { Name: "unset", Aliases: []string{"u"}, Usage: "remove a configuration key for this route", - ArgsUsage: "`app` /path ", + ArgsUsage: " ", Action: r.configUnset, }, }, @@ -152,14 +122,14 @@ func routes() cli.Command { Name: "delete", Aliases: []string{"d"}, Usage: "delete a route from `app`", - ArgsUsage: "`app` /path", + ArgsUsage: " ", Action: r.delete, }, { Name: "inspect", Aliases: []string{"i"}, Usage: "retrieve one or all routes properties", - ArgsUsage: "`app` /path [property.[key]]", + ArgsUsage: " [property.[key]]", Action: r.inspect, }, }, @@ -172,7 +142,7 @@ func call() cli.Command { return cli.Command{ Name: "call", Usage: "call a remote function", - ArgsUsage: "`app` /path", + ArgsUsage: " ", Flags: runflags(), Action: r.call, } @@ -187,10 +157,6 @@ func cleanRoutePath(p string) string { } func (a *routesCmd) list(c *cli.Context) error { - if len(c.Args()) < 1 { - return errors.New("error: routes listing takes one argument: an app name") - } - appName := c.Args().Get(0) resp, err := a.client.Routes.GetAppsAppRoutes(&apiroutes.GetAppsAppRoutesParams{ @@ -201,11 +167,11 @@ func (a *routesCmd) list(c *cli.Context) error { if err != nil { switch err.(type) { case *apiroutes.GetAppsAppRoutesNotFound: - return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesNotFound).Payload.Error.Message) + return fmt.Errorf("error: %s", err.(*apiroutes.GetAppsAppRoutesNotFound).Payload.Error.Message) case *apiroutes.GetAppsAppRoutesDefault: - return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesDefault).Payload.Error.Message) + return fmt.Errorf("unexpected error: %s", err.(*apiroutes.GetAppsAppRoutesDefault).Payload.Error.Message) } - return fmt.Errorf("unexpected error: %v", err) + return fmt.Errorf("unexpected error: %s", err) } w := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0) @@ -214,7 +180,7 @@ func (a *routesCmd) list(c *cli.Context) error { u, err := url.Parse("../") u.Path = path.Join(u.Path, "r", appName, route.Path) if err != nil { - return fmt.Errorf("error parsing functions route path: %v", err) + return fmt.Errorf("error parsing functions route path: %s", err) } fmt.Fprint(w, route.Path, "\t", route.Image, "\n") @@ -225,10 +191,6 @@ func (a *routesCmd) list(c *cli.Context) error { } func (a *routesCmd) call(c *cli.Context) error { - if len(c.Args()) < 2 { - return errors.New("error: routes listing takes three arguments: an app name and a path") - } - appName := c.Args().Get(0) route := cleanRoutePath(c.Args().Get(1)) @@ -253,7 +215,7 @@ func callfn(u string, content io.Reader, output io.Writer, method string, env [] req, err := http.NewRequest(method, u, content) if err != nil { - return fmt.Errorf("error running route: %v", err) + return fmt.Errorf("error running route: %s", err) } req.Header.Set("Content-Type", "application/json") @@ -264,7 +226,7 @@ func callfn(u string, content io.Reader, output io.Writer, method string, env [] resp, err := http.DefaultClient.Do(req) if err != nil { - return fmt.Errorf("error running route: %v", err) + return fmt.Errorf("error running route: %s", err) } io.Copy(output, resp.Body) @@ -328,7 +290,7 @@ func routeWithFlags(c *cli.Context, rt *models.Route) { func routeWithFuncFile(c *cli.Context, rt *models.Route) { ff, err := loadFuncfile() if err == nil { - if rt.Image != "" { // flags take precedence + if ff.FullName() != "" { // args take precedence rt.Image = ff.FullName() } if ff.Format != nil { @@ -348,18 +310,12 @@ func routeWithFuncFile(c *cli.Context, rt *models.Route) { } func (a *routesCmd) create(c *cli.Context) error { - // todo: @pedro , why aren't you just checking the length here? - if len(c.Args()) < 2 { - return errors.New("error: routes listing takes at least two arguments: an app name and a path") - } - appName := c.Args().Get(0) route := cleanRoutePath(c.Args().Get(1)) - image := c.Args().Get(2) rt := &models.Route{} rt.Path = route - rt.Image = image + rt.Image = c.Args().Get(2) routeWithFuncFile(c, rt) routeWithFlags(c, rt) @@ -368,7 +324,8 @@ func (a *routesCmd) create(c *cli.Context) error { return errors.New("error: route path is missing") } if rt.Image == "" { - return errors.New("error: function image name is missing") + fmt.Println("No image specified, using `iron/hello`") + rt.Image = "iron/hello" } body := &models.RouteWrapper{ @@ -384,13 +341,13 @@ func (a *routesCmd) create(c *cli.Context) error { if err != nil { switch err.(type) { case *apiroutes.PostAppsAppRoutesBadRequest: - return fmt.Errorf("error: %v", err.(*apiroutes.PostAppsAppRoutesBadRequest).Payload.Error.Message) + return fmt.Errorf("error: %s", err.(*apiroutes.PostAppsAppRoutesBadRequest).Payload.Error.Message) case *apiroutes.PostAppsAppRoutesConflict: - return fmt.Errorf("error: %v", err.(*apiroutes.PostAppsAppRoutesConflict).Payload.Error.Message) + return fmt.Errorf("error: %s", err.(*apiroutes.PostAppsAppRoutesConflict).Payload.Error.Message) case *apiroutes.PostAppsAppRoutesDefault: - return fmt.Errorf("unexpected error: %v", err.(*apiroutes.PostAppsAppRoutesDefault).Payload.Error.Message) + return fmt.Errorf("unexpected error: %s", err.(*apiroutes.PostAppsAppRoutesDefault).Payload.Error.Message) } - return fmt.Errorf("unexpected error: %v", err) + return fmt.Errorf("unexpected error: %s", err) } fmt.Println(resp.Payload.Route.Path, "created with", resp.Payload.Route.Image) @@ -407,11 +364,11 @@ func (a *routesCmd) patchRoute(appName, routePath string, r *fnmodels.Route) err if err != nil { switch err.(type) { case *apiroutes.GetAppsAppRoutesRouteNotFound: - return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message) + return fmt.Errorf("error: %s", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message) case *apiroutes.GetAppsAppRoutesDefault: - return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesDefault).Payload.Error.Message) + return fmt.Errorf("unexpected error: %s", err.(*apiroutes.GetAppsAppRoutesDefault).Payload.Error.Message) } - return fmt.Errorf("unexpected error: %v", err) + return fmt.Errorf("unexpected error: %s", err) } if resp.Payload.Route.Config == nil { @@ -472,23 +429,19 @@ func (a *routesCmd) patchRoute(appName, routePath string, r *fnmodels.Route) err if err != nil { switch err.(type) { case *apiroutes.PatchAppsAppRoutesRouteBadRequest: - return fmt.Errorf("error: %v", err.(*apiroutes.PatchAppsAppRoutesRouteBadRequest).Payload.Error.Message) + return fmt.Errorf("error: %s", err.(*apiroutes.PatchAppsAppRoutesRouteBadRequest).Payload.Error.Message) case *apiroutes.PatchAppsAppRoutesRouteNotFound: - return fmt.Errorf("error: %v", err.(*apiroutes.PatchAppsAppRoutesRouteNotFound).Payload.Error.Message) + return fmt.Errorf("error: %s", err.(*apiroutes.PatchAppsAppRoutesRouteNotFound).Payload.Error.Message) case *apiroutes.PatchAppsAppRoutesRouteDefault: - return fmt.Errorf("unexpected error: %v", err.(*apiroutes.PatchAppsAppRoutesRouteDefault).Payload.Error.Message) + return fmt.Errorf("unexpected error: %s", err.(*apiroutes.PatchAppsAppRoutesRouteDefault).Payload.Error.Message) } - return fmt.Errorf("unexpected error: %v", err) + return fmt.Errorf("unexpected error: %s", err) } return nil } func (a *routesCmd) update(c *cli.Context) error { - if len(c.Args()) < 2 { - return errors.New("error: route update takes at least two arguments: an app name and a path") - } - appName := c.Args().Get(0) route := cleanRoutePath(c.Args().Get(1)) @@ -506,10 +459,6 @@ func (a *routesCmd) update(c *cli.Context) error { } func (a *routesCmd) configSet(c *cli.Context) error { - if len(c.Args()) < 4 { - return errors.New("error: route configuration updates tak four arguments: an app name, a path, a key and a value") - } - appName := c.Args().Get(0) route := cleanRoutePath(c.Args().Get(1)) key := c.Args().Get(2) @@ -531,10 +480,6 @@ func (a *routesCmd) configSet(c *cli.Context) error { } func (a *routesCmd) configUnset(c *cli.Context) error { - if len(c.Args()) < 3 { - return errors.New("error: route configuration updates take three arguments: an app name, a path and a key") - } - appName := c.Args().Get(0) route := cleanRoutePath(c.Args().Get(1)) key := c.Args().Get(2) @@ -555,10 +500,6 @@ func (a *routesCmd) configUnset(c *cli.Context) error { } func (a *routesCmd) inspect(c *cli.Context) error { - if len(c.Args()) < 2 { - return errors.New("error: routes listing takes three arguments: an app name and a path") - } - appName := c.Args().Get(0) route := cleanRoutePath(c.Args().Get(1)) prop := c.Args().Get(2) @@ -572,11 +513,11 @@ func (a *routesCmd) inspect(c *cli.Context) error { if err != nil { switch err.(type) { case *apiroutes.GetAppsAppRoutesRouteNotFound: - return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message) + return fmt.Errorf("error: %s", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message) case *apiroutes.GetAppsAppRoutesRouteDefault: - return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesRouteDefault).Payload.Error.Message) + return fmt.Errorf("unexpected error: %s", err.(*apiroutes.GetAppsAppRoutesRouteDefault).Payload.Error.Message) } - return fmt.Errorf("unexpected error: %v", err) + return fmt.Errorf("unexpected error: %s", err) } enc := json.NewEncoder(os.Stdout) @@ -589,12 +530,12 @@ func (a *routesCmd) inspect(c *cli.Context) error { data, err := json.Marshal(resp.Payload.Route) if err != nil { - return fmt.Errorf("failed to inspect route: %v", err) + return fmt.Errorf("failed to inspect route: %s", err) } var inspect map[string]interface{} err = json.Unmarshal(data, &inspect) if err != nil { - return fmt.Errorf("failed to inspect route: %v", err) + return fmt.Errorf("failed to inspect route: %s", err) } jq := jsonq.NewQuery(inspect) @@ -608,10 +549,6 @@ func (a *routesCmd) inspect(c *cli.Context) error { } func (a *routesCmd) delete(c *cli.Context) error { - if len(c.Args()) < 2 { - return errors.New("error: routes delete takes two arguments: an app name and a path") - } - appName := c.Args().Get(0) route := cleanRoutePath(c.Args().Get(1)) @@ -623,11 +560,11 @@ func (a *routesCmd) delete(c *cli.Context) error { if err != nil { switch err.(type) { case *apiroutes.DeleteAppsAppRoutesRouteNotFound: - return fmt.Errorf("error: %v", err.(*apiroutes.DeleteAppsAppRoutesRouteNotFound).Payload.Error.Message) + return fmt.Errorf("error: %s", err.(*apiroutes.DeleteAppsAppRoutesRouteNotFound).Payload.Error.Message) case *apiroutes.DeleteAppsAppRoutesRouteDefault: - return fmt.Errorf("unexpected error: %v", err.(*apiroutes.DeleteAppsAppRoutesRouteDefault).Payload.Error.Message) + return fmt.Errorf("unexpected error: %s", err.(*apiroutes.DeleteAppsAppRoutesRouteDefault).Payload.Error.Message) } - return fmt.Errorf("unexpected error: %v", err) + return fmt.Errorf("unexpected error: %s", err) } fmt.Println(appName, route, "deleted") diff --git a/fn/run.go b/fn/run.go index b8bec1bec..728792a08 100644 --- a/fn/run.go +++ b/fn/run.go @@ -17,7 +17,7 @@ func run() cli.Command { return cli.Command{ Name: "run", Usage: "run a function locally", - ArgsUsage: "USERNAME/image:tag", + ArgsUsage: "[username/image:tag]", Flags: append(runflags(), []cli.Flag{}...), Action: r.run, } @@ -36,7 +36,7 @@ func runflags() []cli.Flag { Usage: "select container links for the function", }, cli.StringFlag{ - Name: "method", + Name: "method", Usage: "http method for function", }, }