fn: apps commands improvements (#476)

* improve apps commands

* fix app and routes update config and headers unset

* add the command config set/unset back

* prevent extractEnvConfig to panic if not valid key=value

* add examples to readme.md

* fix fn routes
This commit is contained in:
Pedro Nasser
2017-01-30 17:23:34 -02:00
committed by Travis Reeder
parent 5609a76c19
commit c62e22f5fe
4 changed files with 349 additions and 298 deletions

View File

@@ -56,20 +56,20 @@ fn push
You can operate IronFunctions from the command line.
```sh
$ fn apps # list apps
$ fn apps list # list apps
myapp
$ fn apps create otherapp # create new app
otherapp created
$ fn apps config otherapp # show app-specific configuration
this application has no configurations
$ fn apps inspect otherapp config # show app-specific configuration
{ ... }
$ fn apps
myapp
otherapp
$ fn routes myapp # list routes of an app
$ fn routes list myapp # list routes of an app
path image
/hello iron/hello
@@ -191,6 +191,47 @@ $ fn routes create myapp
$ fn test --remote myapp
```
## Other examples of usage
### Creating a new function from source
```
fn init iron/hello --runtime ruby
fn deploy myapp /hello
```
### Updating function
```
fn deploy myapp (discover route path if available in func.yaml)
```
### Testing function locally
```
fn run iron/hello
```
### Testing route
```
fn call myapp /hello
```
### App management
```
fn apps create myapp
fn apps update myapp --headers "content-type=application/json"
fn apps config set log_level info
fn apps inspect myapp
fn apps delete myapp
```
### Route management
```
fn routes create myapp /hello iron/hello
fn routes update myapp /hello --timeout 30 --type async
fn routes config set myapp /hello log_level info
fn routes inspect myapp /hello
fn routes delete myapp /hello
```
## Contributing
Ensure you have Go configured and installed in your environment. Once it is

View File

@@ -5,13 +5,15 @@ import (
"errors"
"fmt"
"os"
"text/tabwriter"
"context"
"github.com/iron-io/functions_go"
fnclient "github.com/iron-io/functions_go/client"
apiapps "github.com/iron-io/functions_go/client/apps"
"github.com/iron-io/functions_go/models"
"github.com/jmoiron/jsonq"
"github.com/urfave/cli"
"strings"
)
type appsCmd struct {
@@ -40,32 +42,29 @@ func apps() cli.Command {
},
},
{
Name: "list",
Aliases: []string{"l"},
Usage: "list all apps",
Action: a.list,
Name: "inspect",
Aliases: []string{"i"},
Usage: "retrieve one or all apps properties",
ArgsUsage: "`app` [property.[key]]",
Action: a.inspect,
},
{
Name: "update",
Aliases: []string{"u"},
Usage: "update an `app`",
ArgsUsage: "`app`",
Action: a.update,
Flags: []cli.Flag{
cli.StringSliceFlag{
Name: "config,c",
Usage: "route configuration",
},
},
},
{
Name: "config",
Usage: "operate an application configuration set",
Usage: "manage your apps's function configs",
Subcommands: []cli.Command{
{
Name: "view",
Aliases: []string{"v"},
Usage: "view all configuration keys for this app",
ArgsUsage: "`app`",
Action: a.configList,
Flags: []cli.Flag{
cli.BoolFlag{
Name: "shell,s",
Usage: "output in shell format",
},
cli.BoolFlag{
Name: "json,j",
Usage: "output in JSON format",
},
},
},
{
Name: "set",
Aliases: []string{"s"},
@@ -82,6 +81,12 @@ func apps() cli.Command {
},
},
},
{
Name: "list",
Aliases: []string{"l"},
Usage: "list all apps",
Action: a.list,
},
{
Name: "delete",
Usage: "delete an app",
@@ -120,7 +125,7 @@ func (a *appsCmd) list(c *cli.Context) error {
func (a *appsCmd) create(c *cli.Context) error {
if c.Args().First() == "" {
return errors.New("error: app creating takes one argument, an app name")
return errors.New("error: missing app name after create command")
}
body := &models.AppWrapper{App: &models.App{
@@ -149,50 +154,23 @@ func (a *appsCmd) create(c *cli.Context) error {
return nil
}
func (a *appsCmd) configList(c *cli.Context) error {
func (a *appsCmd) update(c *cli.Context) error {
if c.Args().First() == "" {
return errors.New("error: app description takes one argument, an app name")
return errors.New("error: missing app name after update command")
}
appName := c.Args().Get(0)
appName := c.Args().First()
resp, err := a.client.Apps.GetAppsApp(&apiapps.GetAppsAppParams{
Context: context.Background(),
App: appName,
})
patchedApp := &functions.App{
Config: extractEnvConfig(c.StringSlice("config")),
}
err := a.patchApp(appName, patchedApp)
if err != nil {
switch err.(type) {
case *apiapps.GetAppsAppNotFound:
return fmt.Errorf("error: %v", err.(*apiapps.GetAppsAppNotFound).Payload.Error.Message)
case *apiapps.GetAppsAppDefault:
return fmt.Errorf("unexpected error: %v", err.(*apiapps.GetAppsAppDefault).Payload.Error.Message)
}
return fmt.Errorf("unexpected error: %v", err)
return err
}
config := resp.Payload.App.Config
if len(config) == 0 {
return errors.New("this application has no configurations")
}
if c.Bool("json") {
if err := json.NewEncoder(os.Stdout).Encode(config); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
} else if c.Bool("shell") {
for k, v := range resp.Payload.App.Config {
fmt.Print("export ", k, "=", v, "\n")
}
} else {
fmt.Println(resp.Payload.App.Name, "configuration:")
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, ' ', 0)
for k, v := range config {
fmt.Fprint(w, k, ":\t", v, "\n")
}
w.Flush()
}
fmt.Println("app", appName, "updated")
return nil
}
@@ -205,34 +183,17 @@ func (a *appsCmd) configSet(c *cli.Context) error {
key := c.Args().Get(1)
value := c.Args().Get(2)
resp, err := a.client.Apps.GetAppsApp(&apiapps.GetAppsAppParams{
Context: context.Background(),
App: appName,
})
if err != nil {
switch err.(type) {
case *apiapps.GetAppsAppNotFound:
return fmt.Errorf("error: %v", err.(*apiapps.GetAppsAppNotFound).Payload.Error.Message)
case *apiapps.GetAppsAppDefault:
return fmt.Errorf("unexpected error: %v", err.(*apiapps.GetAppsAppDefault).Payload.Error.Message)
}
return fmt.Errorf("unexpected error: %v", err)
app := &functions.App{
Config: make(map[string]string),
}
config := resp.Payload.App.Config
app.Config[key] = value
if config == nil {
config = make(map[string]string)
}
config[key] = value
if err := a.patchApp(appName, config); err != nil {
if err := a.patchApp(appName, app); err != nil {
return fmt.Errorf("error updating app configuration: %v", err)
}
fmt.Println(resp.Payload.App.Name, "updated", key, "with", value)
fmt.Println(appName, "updated", key, "with", value)
return nil
}
@@ -244,6 +205,21 @@ func (a *appsCmd) configUnset(c *cli.Context) error {
appName := c.Args().Get(0)
key := c.Args().Get(1)
app := &functions.App{
Config: make(map[string]string),
}
app.Config["-"+key] = ""
if err := a.patchApp(appName, app); err != nil {
return fmt.Errorf("error updating app configuration: %v", err)
}
fmt.Printf("removed key '%s' from app '%s' \n", key, appName)
return nil
}
func (a *appsCmd) patchApp(appName string, app *functions.App) error {
resp, err := a.client.Apps.GetAppsApp(&apiapps.GetAppsAppParams{
Context: context.Background(),
App: appName,
@@ -259,32 +235,26 @@ func (a *appsCmd) configUnset(c *cli.Context) error {
return fmt.Errorf("unexpected error: %v", err)
}
config := resp.Payload.App.Config
if config == nil {
config = make(map[string]string)
if resp.Payload.App.Config == nil {
resp.Payload.App.Config = map[string]string{}
}
if _, ok := config[key]; !ok {
return fmt.Errorf("configuration key %s not found", key)
resp.Payload.App.Name = ""
if app != nil {
if app.Config != nil {
for k, v := range app.Config {
if string(k[0]) == "-" {
delete(resp.Payload.App.Config, string(k[1:]))
continue
}
resp.Payload.App.Config[k] = v
}
}
}
delete(config, key)
body := &models.AppWrapper{App: resp.Payload.App}
if err := a.patchApp(appName, config); err != nil {
return fmt.Errorf("error updating app configuration: %v", err)
}
fmt.Println(resp.Payload.App.Name, "removed", key)
return nil
}
func (a *appsCmd) patchApp(appName string, config map[string]string) error {
body := &models.AppWrapper{App: &models.App{
Config: config,
}}
_, err := a.client.Apps.PatchAppsApp(&apiapps.PatchAppsAppParams{
_, err = a.client.Apps.PatchAppsApp(&apiapps.PatchAppsAppParams{
Context: context.Background(),
App: appName,
Body: body,
@@ -305,6 +275,59 @@ func (a *appsCmd) patchApp(appName string, config map[string]string) error {
return nil
}
func (a *appsCmd) inspect(c *cli.Context) error {
if c.Args().Get(0) == "" {
return errors.New("error: missing app name after the inspect command")
}
appName := c.Args().First()
prop := c.Args().Get(1)
resp, err := a.client.Apps.GetAppsApp(&apiapps.GetAppsAppParams{
Context: context.Background(),
App: appName,
})
if err != nil {
switch err.(type) {
case *apiapps.GetAppsAppNotFound:
return fmt.Errorf("error: %v", err.(*apiapps.GetAppsAppNotFound).Payload.Error.Message)
case *apiapps.GetAppsAppDefault:
return fmt.Errorf("unexpected error: %v", err.(*apiapps.GetAppsAppDefault).Payload.Error.Message)
}
return fmt.Errorf("unexpected error: %v", err)
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", "\t")
if prop == "" {
enc.Encode(resp.Payload.App)
return nil
}
// TODO: we really need to marshal it here just to
// unmarshal as map[string]interface{}?
data, err := json.Marshal(resp.Payload.App)
if err != nil {
return fmt.Errorf("error inspect app: %v", err)
}
var inspect map[string]interface{}
err = json.Unmarshal(data, &inspect)
if err != nil {
return fmt.Errorf("error inspect app: %v", err)
}
jq := jsonq.NewQuery(inspect)
field, err := jq.Interface(strings.Split(prop, ".")...)
if err != nil {
return errors.New("failed to inspect that apps's field")
}
enc.Encode(field)
return nil
}
func (a *appsCmd) delete(c *cli.Context) error {
appName := c.Args().First()
if appName == "" {
@@ -326,6 +349,6 @@ func (a *appsCmd) delete(c *cli.Context) error {
return fmt.Errorf("unexpected error: %v", err)
}
fmt.Println(appName, "deleted")
fmt.Println("app", appName, "deleted")
return nil
}

View File

@@ -185,8 +185,10 @@ func extractEnvConfig(configs []string) map[string]string {
c := make(map[string]string)
for _, v := range configs {
kv := strings.SplitN(v, "=", 2)
if len(kv) == 2 {
c[kv[0]] = os.ExpandEnv(kv[1])
}
}
return c
}

View File

@@ -17,6 +17,7 @@ import (
fnclient "github.com/iron-io/functions_go/client"
apiroutes "github.com/iron-io/functions_go/client/routes"
"github.com/iron-io/functions_go/models"
fnmodels "github.com/iron-io/functions_go/models"
"github.com/jmoiron/jsonq"
"github.com/urfave/cli"
)
@@ -100,12 +101,10 @@ func routes() cli.Command {
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",
@@ -118,17 +117,14 @@ func routes() cli.Command {
cli.StringFlag{
Name: "format,f",
Usage: "hot container IO format - json or http",
Value: "",
},
cli.IntFlag{
Name: "max-concurrency",
Name: "max-concurrency,mc",
Usage: "maximum concurrency for hot container",
Value: 1,
},
cli.DurationFlag{
Name: "timeout",
Usage: "route timeout",
Value: 30 * time.Second,
Usage: "route timeout (eg. 30s)",
},
},
},
@@ -273,8 +269,8 @@ func envAsHeader(req *http.Request, selectedEnv []string) {
}
func (a *routesCmd) create(c *cli.Context) error {
if c.Args().Get(0) == "" {
return errors.New("error: routes creation takes at least one argument: an app name")
if c.Args().Get(0) == "" || c.Args().Get(1) == "" || c.Args().Get(2) == "" {
return errors.New("error: routes creation takes at least three arguments: app name, route path and image name")
}
appName := c.Args().Get(0)
@@ -361,167 +357,75 @@ func (a *routesCmd) create(c *cli.Context) error {
return nil
}
func (a *routesCmd) delete(c *cli.Context) error {
if c.Args().Get(0) == "" || c.Args().Get(1) == "" {
return errors.New("error: routes listing takes three arguments: an app name and a path")
}
appName := c.Args().Get(0)
route := c.Args().Get(1)
_, err := a.client.Routes.DeleteAppsAppRoutesRoute(&apiroutes.DeleteAppsAppRoutesRouteParams{
Context: context.Background(),
App: appName,
Route: route,
})
if err != nil {
switch err.(type) {
case *apiroutes.DeleteAppsAppRoutesRouteNotFound:
return fmt.Errorf("error: %v", 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: %v", err)
}
fmt.Println(route, "deleted")
return nil
}
// _, err = a.client.Routes.PatchAppsAppRoutesRoute(&apiroutes.PatchAppsAppRoutesRouteParams{
// Context: context.Background(),
// App: appName,
// Route: route,
// Body: resp.Payload,
// })
// if err != nil {
// switch err.(type) {
// case *apiroutes.PatchAppsAppRoutesRouteBadRequest:
// return fmt.Errorf("error: %v", err.(*apiroutes.PatchAppsAppRoutesRouteBadRequest).Payload.Error.Message)
// case *apiroutes.PatchAppsAppRoutesRouteNotFound:
// return fmt.Errorf("error: %v", 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: %v", err)
// }
func (a *routesCmd) update(c *cli.Context) error {
if c.Args().Get(0) == "" || c.Args().Get(1) == "" {
return errors.New("error: route configuration description takes two arguments: an app name and a route")
}
appName := c.Args().Get(0)
route := c.Args().Get(1)
func (a *routesCmd) patchRoute(appName, routePath string, r *fnmodels.Route) error {
resp, err := a.client.Routes.GetAppsAppRoutesRoute(&apiroutes.GetAppsAppRoutesRouteParams{
Context: context.Background(),
App: appName,
Route: route,
})
if err != nil {
switch err.(type) {
case *apiroutes.GetAppsAppRoutesRouteNotFound:
return fmt.Errorf("error: %v", 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: %v", err)
}
config := resp.Payload.Route.Config
if len(config) == 0 {
return errors.New("this route has no configurations")
}
if c.Bool("json") {
if err := json.NewEncoder(os.Stdout).Encode(config); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
} else if c.Bool("shell") {
for k, v := range config {
fmt.Print("export ", k, "=", v, "\n")
}
} else {
fmt.Println(appName, resp.Payload.Route.Path, "configuration:")
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, ' ', 0)
for k, v := range config {
fmt.Fprint(w, k, ":\t", v, "\n")
}
w.Flush()
}
// if route == "" {
// return errors.New("error: route path is missing")
// }
// headers := map[string][]string{}
// for _, header := range c.StringSlice("headers") {
// parts := strings.Split(header, "=")
// headers[parts[0]] = strings.Split(parts[1], ";")
// }
// patchRoute := &functions.Route{
// Image: c.String("image"),
// Memory: c.Int64("memory"),
// Type_: c.String("type"),
// Config: extractEnvConfig(c.StringSlice("config")),
// Headers: headers,
// Format: c.String("format"),
// MaxConcurrency: int32(c.Int64("max-concurrency")),
// Timeout: int32(c.Int64("timeout")),
// }
// err := a.patchRoute(appName, route, patchRoute)
// if err != nil {
// return err
// }
fmt.Println(appName, route, "updated")
return nil
}
func (a *routesCmd) configSet(c *cli.Context) error {
if c.Args().Get(0) == "" || c.Args().Get(1) == "" || c.Args().Get(2) == "" {
return errors.New("error: route configuration setting takes four arguments: an app name, a route, a key and a value")
}
appName := c.Args().Get(0)
route := c.Args().Get(1)
key := c.Args().Get(2)
value := c.Args().Get(3)
resp, err := a.client.Routes.GetAppsAppRoutesRoute(&apiroutes.GetAppsAppRoutesRouteParams{
Context: context.Background(),
App: appName,
Route: route,
Route: routePath,
})
if err != nil {
switch err.(type) {
case *apiroutes.GetAppsAppRoutesRouteNotFound:
return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message)
case *apiroutes.GetAppsAppRoutesRouteDefault:
return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesRouteDefault).Payload.Error.Message)
case *apiroutes.GetAppsAppRoutesDefault:
return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesDefault).Payload.Error.Message)
}
return fmt.Errorf("unexpected error: %v", err)
}
config := resp.Payload.Route.Config
if config == nil {
config = make(map[string]string)
if resp.Payload.Route.Config == nil {
resp.Payload.Route.Config = map[string]string{}
}
config[key] = value
resp.Payload.Route.Config = config
if resp.Payload.Route.Headers == nil {
resp.Payload.Route.Headers = map[string][]string{}
}
resp.Payload.Route.Path = ""
if r != nil {
if r.Config != nil {
for k, v := range r.Config {
if string(k[0]) == "-" {
delete(resp.Payload.Route.Config, string(k[1:]))
continue
}
resp.Payload.Route.Config[k] = v
}
}
if r.Headers != nil {
for k, v := range r.Headers {
if string(k[0]) == "-" {
delete(resp.Payload.Route.Headers, k)
continue
}
resp.Payload.Route.Headers[k] = v
}
}
if r.Image != "" {
resp.Payload.Route.Image = r.Image
}
if r.Format != "" {
resp.Payload.Route.Format = r.Format
}
if r.Type != "" {
resp.Payload.Route.Type = r.Type
}
if r.MaxConcurrency > 0 {
resp.Payload.Route.MaxConcurrency = r.MaxConcurrency
}
if r.Memory > 0 {
resp.Payload.Route.Memory = r.Memory
}
if r.Timeout != nil {
resp.Payload.Route.Timeout = r.Timeout
}
}
_, err = a.client.Routes.PatchAppsAppRoutesRoute(&apiroutes.PatchAppsAppRoutesRouteParams{
Context: context.Background(),
App: appName,
Route: route,
Route: routePath,
Body: resp.Payload,
})
@@ -537,20 +441,82 @@ func (a *routesCmd) configSet(c *cli.Context) error {
return fmt.Errorf("unexpected error: %v", err)
}
fmt.Println(appName, resp.Payload.Route.Path, "updated", key, "with", value)
return nil
}
// patchRoute := functions.Route{
// Config: make(map[string]string),
// }
func (a *routesCmd) update(c *cli.Context) error {
if c.Args().Get(0) == "" || c.Args().Get(1) == "" {
return errors.New("error: route configuration description takes two arguments: an app name and a route")
}
// patchRoute.Config[key] = value
appName := c.Args().Get(0)
route := c.Args().Get(1)
// err := a.patchRoute(appName, route, &patchRoute)
// if err != nil {
// return err
// }
var (
format string
maxC int
timeout time.Duration
)
// fmt.Println(appName, route, "updated", key, "with", value)
if f := c.String("format"); f != "" {
format = f
}
if m := c.Int("max-concurrency"); m > 0 {
maxC = m
}
if t := c.Duration("timeout"); t > 0 {
timeout = t
}
headers := map[string][]string{}
for _, header := range c.StringSlice("headers") {
parts := strings.Split(header, "=")
headers[parts[0]] = strings.Split(parts[1], ";")
}
to := int64(timeout.Seconds())
patchRoute := &fnmodels.Route{
Image: c.String("image"),
Memory: c.Int64("memory"),
Type: c.String("type"),
Config: extractEnvConfig(c.StringSlice("config")),
Headers: headers,
Format: format,
MaxConcurrency: int32(maxC),
Timeout: &to,
}
err := a.patchRoute(appName, route, patchRoute)
if err != nil {
return err
}
fmt.Println(appName, route, "updated")
return nil
}
func (a *routesCmd) configSet(c *cli.Context) error {
if c.Args().Get(0) == "" || c.Args().Get(1) == "" || c.Args().Get(2) == "" {
return errors.New("error: route configuration setting takes four arguments: an app name, a route, a key and a value")
}
appName := c.Args().Get(0)
route := c.Args().Get(1)
key := c.Args().Get(2)
value := c.Args().Get(3)
patchRoute := fnmodels.Route{
Config: make(map[string]string),
}
patchRoute.Config[key] = value
err := a.patchRoute(appName, route, &patchRoute)
if err != nil {
return err
}
fmt.Println(appName, route, "updated", key, "with", value)
return nil
}
@@ -563,36 +529,18 @@ func (a *routesCmd) configUnset(c *cli.Context) error {
route := c.Args().Get(1)
key := c.Args().Get(2)
resp, err := a.client.Routes.GetAppsAppRoutesRoute(&apiroutes.GetAppsAppRoutesRouteParams{
Context: context.Background(),
App: appName,
Route: route,
})
patchRoute := fnmodels.Route{
Config: make(map[string]string),
}
patchRoute.Config["-"+key] = ""
err := a.patchRoute(appName, route, &patchRoute)
if err != nil {
switch err.(type) {
case *apiroutes.GetAppsAppRoutesRouteNotFound:
return fmt.Errorf("error: %v", 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: %v", err)
return err
}
config := resp.Payload.Route.Config
if config == nil {
config = make(map[string]string)
}
if _, ok := config[key]; !ok {
return fmt.Errorf("configuration key %s not found", key)
}
delete(config, key)
resp.Payload.Route.Config = config
fmt.Println(appName, resp.Payload.Route.Path, "removed", key)
fmt.Printf("removed key '%s' from the route '%s%s'", key, appName, key)
return nil
}
@@ -629,12 +577,49 @@ func (a *routesCmd) inspect(c *cli.Context) error {
return nil
}
jq := jsonq.NewQuery(resp.Payload.Route)
data, err := json.Marshal(resp.Payload.Route)
if err != nil {
return fmt.Errorf("failed to inspect route: %v", err)
}
var inspect map[string]interface{}
err = json.Unmarshal(data, &inspect)
if err != nil {
return fmt.Errorf("failed to inspect route: %v", err)
}
jq := jsonq.NewQuery(inspect)
field, err := jq.Interface(strings.Split(prop, ".")...)
if err != nil {
return errors.New("failed to inspect the property")
return errors.New("failed to inspect that route's field")
}
enc.Encode(field)
return nil
}
func (a *routesCmd) delete(c *cli.Context) error {
if c.Args().Get(0) == "" || c.Args().Get(1) == "" {
return errors.New("error: routes listing takes three arguments: an app name and a path")
}
appName := c.Args().Get(0)
route := c.Args().Get(1)
_, err := a.client.Routes.DeleteAppsAppRoutesRoute(&apiroutes.DeleteAppsAppRoutesRouteParams{
Context: context.Background(),
App: appName,
Route: route,
})
if err != nil {
switch err.(type) {
case *apiroutes.DeleteAppsAppRoutesRouteNotFound:
return fmt.Errorf("error: %v", 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: %v", err)
}
fmt.Println(appName, route, "deleted")
return nil
}