mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
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:
committed by
Travis Reeder
parent
5609a76c19
commit
c62e22f5fe
49
fn/README.md
49
fn/README.md
@@ -56,20 +56,20 @@ fn push
|
|||||||
You can operate IronFunctions from the command line.
|
You can operate IronFunctions from the command line.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ fn apps # list apps
|
$ fn apps list # list apps
|
||||||
myapp
|
myapp
|
||||||
|
|
||||||
$ fn apps create otherapp # create new app
|
$ fn apps create otherapp # create new app
|
||||||
otherapp created
|
otherapp created
|
||||||
|
|
||||||
$ fn apps config otherapp # show app-specific configuration
|
$ fn apps inspect otherapp config # show app-specific configuration
|
||||||
this application has no configurations
|
{ ... }
|
||||||
|
|
||||||
$ fn apps
|
$ fn apps
|
||||||
myapp
|
myapp
|
||||||
otherapp
|
otherapp
|
||||||
|
|
||||||
$ fn routes myapp # list routes of an app
|
$ fn routes list myapp # list routes of an app
|
||||||
path image
|
path image
|
||||||
/hello iron/hello
|
/hello iron/hello
|
||||||
|
|
||||||
@@ -191,6 +191,47 @@ $ fn routes create myapp
|
|||||||
$ fn test --remote 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
|
## Contributing
|
||||||
|
|
||||||
Ensure you have Go configured and installed in your environment. Once it is
|
Ensure you have Go configured and installed in your environment. Once it is
|
||||||
|
|||||||
231
fn/apps.go
231
fn/apps.go
@@ -5,13 +5,15 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/iron-io/functions_go"
|
||||||
fnclient "github.com/iron-io/functions_go/client"
|
fnclient "github.com/iron-io/functions_go/client"
|
||||||
apiapps "github.com/iron-io/functions_go/client/apps"
|
apiapps "github.com/iron-io/functions_go/client/apps"
|
||||||
"github.com/iron-io/functions_go/models"
|
"github.com/iron-io/functions_go/models"
|
||||||
|
"github.com/jmoiron/jsonq"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type appsCmd struct {
|
type appsCmd struct {
|
||||||
@@ -40,32 +42,29 @@ func apps() cli.Command {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "list",
|
Name: "inspect",
|
||||||
Aliases: []string{"l"},
|
Aliases: []string{"i"},
|
||||||
Usage: "list all apps",
|
Usage: "retrieve one or all apps properties",
|
||||||
Action: a.list,
|
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",
|
Name: "config",
|
||||||
Usage: "operate an application configuration set",
|
Usage: "manage your apps's function configs",
|
||||||
Subcommands: []cli.Command{
|
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",
|
Name: "set",
|
||||||
Aliases: []string{"s"},
|
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",
|
Name: "delete",
|
||||||
Usage: "delete an app",
|
Usage: "delete an app",
|
||||||
@@ -120,7 +125,7 @@ func (a *appsCmd) list(c *cli.Context) error {
|
|||||||
|
|
||||||
func (a *appsCmd) create(c *cli.Context) error {
|
func (a *appsCmd) create(c *cli.Context) error {
|
||||||
if c.Args().First() == "" {
|
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{
|
body := &models.AppWrapper{App: &models.App{
|
||||||
@@ -149,50 +154,23 @@ func (a *appsCmd) create(c *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appsCmd) configList(c *cli.Context) error {
|
func (a *appsCmd) update(c *cli.Context) error {
|
||||||
if c.Args().First() == "" {
|
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{
|
patchedApp := &functions.App{
|
||||||
Context: context.Background(),
|
Config: extractEnvConfig(c.StringSlice("config")),
|
||||||
App: appName,
|
}
|
||||||
})
|
|
||||||
|
|
||||||
|
err := a.patchApp(appName, patchedApp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err.(type) {
|
return err
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config := resp.Payload.App.Config
|
fmt.Println("app", appName, "updated")
|
||||||
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()
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,34 +183,17 @@ func (a *appsCmd) configSet(c *cli.Context) error {
|
|||||||
key := c.Args().Get(1)
|
key := c.Args().Get(1)
|
||||||
value := c.Args().Get(2)
|
value := c.Args().Get(2)
|
||||||
|
|
||||||
resp, err := a.client.Apps.GetAppsApp(&apiapps.GetAppsAppParams{
|
app := &functions.App{
|
||||||
Context: context.Background(),
|
Config: make(map[string]string),
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config := resp.Payload.App.Config
|
app.Config[key] = value
|
||||||
|
|
||||||
if config == nil {
|
if err := a.patchApp(appName, app); err != nil {
|
||||||
config = make(map[string]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
config[key] = value
|
|
||||||
|
|
||||||
if err := a.patchApp(appName, config); err != nil {
|
|
||||||
return fmt.Errorf("error updating app configuration: %v", err)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,6 +205,21 @@ func (a *appsCmd) configUnset(c *cli.Context) error {
|
|||||||
appName := c.Args().Get(0)
|
appName := c.Args().Get(0)
|
||||||
key := c.Args().Get(1)
|
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{
|
resp, err := a.client.Apps.GetAppsApp(&apiapps.GetAppsAppParams{
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
App: appName,
|
App: appName,
|
||||||
@@ -259,32 +235,26 @@ func (a *appsCmd) configUnset(c *cli.Context) error {
|
|||||||
return fmt.Errorf("unexpected error: %v", err)
|
return fmt.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config := resp.Payload.App.Config
|
if resp.Payload.App.Config == nil {
|
||||||
|
resp.Payload.App.Config = map[string]string{}
|
||||||
if config == nil {
|
|
||||||
config = make(map[string]string)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := config[key]; !ok {
|
resp.Payload.App.Name = ""
|
||||||
return fmt.Errorf("configuration key %s not found", key)
|
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 {
|
_, err = a.client.Apps.PatchAppsApp(&apiapps.PatchAppsAppParams{
|
||||||
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{
|
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
App: appName,
|
App: appName,
|
||||||
Body: body,
|
Body: body,
|
||||||
@@ -305,6 +275,59 @@ func (a *appsCmd) patchApp(appName string, config map[string]string) error {
|
|||||||
return nil
|
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 {
|
func (a *appsCmd) delete(c *cli.Context) error {
|
||||||
appName := c.Args().First()
|
appName := c.Args().First()
|
||||||
if appName == "" {
|
if appName == "" {
|
||||||
@@ -326,6 +349,6 @@ func (a *appsCmd) delete(c *cli.Context) error {
|
|||||||
return fmt.Errorf("unexpected error: %v", err)
|
return fmt.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(appName, "deleted")
|
fmt.Println("app", appName, "deleted")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,8 +185,10 @@ func extractEnvConfig(configs []string) map[string]string {
|
|||||||
c := make(map[string]string)
|
c := make(map[string]string)
|
||||||
for _, v := range configs {
|
for _, v := range configs {
|
||||||
kv := strings.SplitN(v, "=", 2)
|
kv := strings.SplitN(v, "=", 2)
|
||||||
|
if len(kv) == 2 {
|
||||||
c[kv[0]] = os.ExpandEnv(kv[1])
|
c[kv[0]] = os.ExpandEnv(kv[1])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
363
fn/routes.go
363
fn/routes.go
@@ -17,6 +17,7 @@ import (
|
|||||||
fnclient "github.com/iron-io/functions_go/client"
|
fnclient "github.com/iron-io/functions_go/client"
|
||||||
apiroutes "github.com/iron-io/functions_go/client/routes"
|
apiroutes "github.com/iron-io/functions_go/client/routes"
|
||||||
"github.com/iron-io/functions_go/models"
|
"github.com/iron-io/functions_go/models"
|
||||||
|
fnmodels "github.com/iron-io/functions_go/models"
|
||||||
"github.com/jmoiron/jsonq"
|
"github.com/jmoiron/jsonq"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
@@ -100,12 +101,10 @@ func routes() cli.Command {
|
|||||||
cli.Int64Flag{
|
cli.Int64Flag{
|
||||||
Name: "memory,m",
|
Name: "memory,m",
|
||||||
Usage: "memory in MiB",
|
Usage: "memory in MiB",
|
||||||
Value: 128,
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "type,t",
|
Name: "type,t",
|
||||||
Usage: "route type - sync or async",
|
Usage: "route type - sync or async",
|
||||||
Value: "sync",
|
|
||||||
},
|
},
|
||||||
cli.StringSliceFlag{
|
cli.StringSliceFlag{
|
||||||
Name: "config,c",
|
Name: "config,c",
|
||||||
@@ -118,17 +117,14 @@ func routes() cli.Command {
|
|||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "format,f",
|
Name: "format,f",
|
||||||
Usage: "hot container IO format - json or http",
|
Usage: "hot container IO format - json or http",
|
||||||
Value: "",
|
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
cli.IntFlag{
|
||||||
Name: "max-concurrency",
|
Name: "max-concurrency,mc",
|
||||||
Usage: "maximum concurrency for hot container",
|
Usage: "maximum concurrency for hot container",
|
||||||
Value: 1,
|
|
||||||
},
|
},
|
||||||
cli.DurationFlag{
|
cli.DurationFlag{
|
||||||
Name: "timeout",
|
Name: "timeout",
|
||||||
Usage: "route timeout",
|
Usage: "route timeout (eg. 30s)",
|
||||||
Value: 30 * time.Second,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -273,8 +269,8 @@ func envAsHeader(req *http.Request, selectedEnv []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *routesCmd) create(c *cli.Context) error {
|
func (a *routesCmd) create(c *cli.Context) error {
|
||||||
if c.Args().Get(0) == "" {
|
if c.Args().Get(0) == "" || c.Args().Get(1) == "" || c.Args().Get(2) == "" {
|
||||||
return errors.New("error: routes creation takes at least one argument: an app name")
|
return errors.New("error: routes creation takes at least three arguments: app name, route path and image name")
|
||||||
}
|
}
|
||||||
|
|
||||||
appName := c.Args().Get(0)
|
appName := c.Args().Get(0)
|
||||||
@@ -361,167 +357,75 @@ func (a *routesCmd) create(c *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *routesCmd) delete(c *cli.Context) error {
|
func (a *routesCmd) patchRoute(appName, routePath string, r *fnmodels.Route) 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)
|
|
||||||
|
|
||||||
resp, err := a.client.Routes.GetAppsAppRoutesRoute(&apiroutes.GetAppsAppRoutesRouteParams{
|
resp, err := a.client.Routes.GetAppsAppRoutesRoute(&apiroutes.GetAppsAppRoutesRouteParams{
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
App: appName,
|
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)
|
|
||||||
}
|
|
||||||
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,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case *apiroutes.GetAppsAppRoutesRouteNotFound:
|
case *apiroutes.GetAppsAppRoutesRouteNotFound:
|
||||||
return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message)
|
return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message)
|
||||||
case *apiroutes.GetAppsAppRoutesRouteDefault:
|
case *apiroutes.GetAppsAppRoutesDefault:
|
||||||
return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesRouteDefault).Payload.Error.Message)
|
return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesDefault).Payload.Error.Message)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("unexpected error: %v", err)
|
return fmt.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config := resp.Payload.Route.Config
|
if resp.Payload.Route.Config == nil {
|
||||||
|
resp.Payload.Route.Config = map[string]string{}
|
||||||
if config == nil {
|
|
||||||
config = make(map[string]string)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config[key] = value
|
if resp.Payload.Route.Headers == nil {
|
||||||
resp.Payload.Route.Config = config
|
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{
|
_, err = a.client.Routes.PatchAppsAppRoutesRoute(&apiroutes.PatchAppsAppRoutesRouteParams{
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
App: appName,
|
App: appName,
|
||||||
Route: route,
|
Route: routePath,
|
||||||
Body: resp.Payload,
|
Body: resp.Payload,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -537,20 +441,82 @@ func (a *routesCmd) configSet(c *cli.Context) error {
|
|||||||
return fmt.Errorf("unexpected error: %v", err)
|
return fmt.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(appName, resp.Payload.Route.Path, "updated", key, "with", value)
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// patchRoute := functions.Route{
|
func (a *routesCmd) update(c *cli.Context) error {
|
||||||
// Config: make(map[string]string),
|
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)
|
var (
|
||||||
// if err != nil {
|
format string
|
||||||
// return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,36 +529,18 @@ func (a *routesCmd) configUnset(c *cli.Context) error {
|
|||||||
route := c.Args().Get(1)
|
route := c.Args().Get(1)
|
||||||
key := c.Args().Get(2)
|
key := c.Args().Get(2)
|
||||||
|
|
||||||
resp, err := a.client.Routes.GetAppsAppRoutesRoute(&apiroutes.GetAppsAppRoutesRouteParams{
|
patchRoute := fnmodels.Route{
|
||||||
Context: context.Background(),
|
Config: make(map[string]string),
|
||||||
App: appName,
|
}
|
||||||
Route: route,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
patchRoute.Config["-"+key] = ""
|
||||||
|
|
||||||
|
err := a.patchRoute(appName, route, &patchRoute)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err.(type) {
|
return err
|
||||||
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
|
fmt.Printf("removed key '%s' from the route '%s%s'", key, appName, key)
|
||||||
|
|
||||||
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)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,12 +577,49 @@ func (a *routesCmd) inspect(c *cli.Context) error {
|
|||||||
return nil
|
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, ".")...)
|
field, err := jq.Interface(strings.Split(prop, ".")...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to inspect the property")
|
return errors.New("failed to inspect that route's field")
|
||||||
}
|
}
|
||||||
enc.Encode(field)
|
enc.Encode(field)
|
||||||
|
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user