fnctl: add run command and fix env var handling (#211)

* fnctl: add run command and fix env var handling
* fnctl: fix help screens
* fnctl: address code review and fix logic mistake
This commit is contained in:
C Cirello
2016-11-03 08:37:29 -07:00
committed by Seif Lotfy سيف لطفي
parent 5b5422148b
commit 1025caeb04
6 changed files with 123 additions and 16 deletions

View File

@@ -15,6 +15,7 @@ build-docker:
test:
go test -v $(shell glide nv | grep -v examples | grep -v tool | grep -v fnctl)
cd fnctl && $(MAKE) test
test-docker:
docker run -ti --privileged --rm -e LOG_LEVEL=debug \

View File

@@ -30,7 +30,7 @@ func handleSpecial(c *gin.Context) {
}
}
func toEnvName(envtype, name string) string {
func ToEnvName(envtype, name string) string {
name = strings.ToUpper(strings.Replace(name, "-", "_", -1))
return fmt.Sprintf("%s_%s", envtype, name)
}
@@ -128,22 +128,22 @@ func handleRequest(c *gin.Context, enqueue models.Enqueue) {
// app config
for k, v := range app.Config {
envVars[toEnvName("CONFIG", k)] = v
envVars[ToEnvName("CONFIG", k)] = v
}
// route config
for k, v := range found.Config {
envVars[toEnvName("CONFIG", k)] = v
envVars[ToEnvName("CONFIG", k)] = v
}
// params
for _, param := range params {
envVars[toEnvName("PARAM", param.Key)] = param.Value
envVars[ToEnvName("PARAM", param.Key)] = param.Value
}
// headers
for header, value := range c.Request.Header {
envVars[toEnvName("HEADER", header)] = strings.Join(value, " ")
envVars[ToEnvName("HEADER", header)] = strings.Join(value, " ")
}
cfg := &runner.Config{

View File

@@ -9,3 +9,6 @@ docker: vendor
vendor:
go get -u .
test:
go test -v $(shell glide nv)

View File

@@ -21,6 +21,7 @@ func main() {
apps(),
build(),
bump(),
call(),
lambda(),
publish(),
routes(),

View File

@@ -8,6 +8,7 @@ import (
"net/url"
"os"
"path"
"strings"
"text/tabwriter"
"github.com/iron-io/functions_go"
@@ -22,18 +23,20 @@ type routesCmd struct {
func routes() cli.Command {
r := routesCmd{RoutesApi: functions.NewRoutesApi()}
flags := append(confFlags(&r.Configuration), []cli.Flag{}...)
return cli.Command{
Name: "routes",
Usage: "list routes",
ArgsUsage: "fnclt routes",
Flags: append(confFlags(&r.Configuration), []cli.Flag{}...),
Flags: flags,
Action: r.list,
Subcommands: []cli.Command{
{
Name: "run",
Usage: "run a route",
Name: "call",
Usage: "call a route",
ArgsUsage: "appName /path",
Action: r.run,
Action: r.call,
Flags: append(flags, runflags()...),
},
{
Name: "create",
@@ -51,6 +54,20 @@ func routes() cli.Command {
}
}
func call() cli.Command {
r := routesCmd{RoutesApi: functions.NewRoutesApi()}
flags := append([]cli.Flag{}, confFlags(&r.Configuration)...)
flags = append(flags, runflags()...)
return cli.Command{
Name: "call",
Usage: "call a remote function",
ArgsUsage: "appName /path",
Flags: flags,
Action: r.call,
}
}
func (a *routesCmd) list(c *cli.Context) error {
if c.Args().First() == "" {
return errors.New("error: routes listing takes one argument, an app name")
@@ -85,7 +102,7 @@ func (a *routesCmd) list(c *cli.Context) error {
return nil
}
func (a *routesCmd) run(c *cli.Context) error {
func (a *routesCmd) call(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 route")
}
@@ -108,7 +125,15 @@ func (a *routesCmd) run(c *cli.Context) error {
content = os.Stdin
}
resp, err := http.Post(baseURL.ResolveReference(u).String(), "application/json", content)
req, err := http.NewRequest("POST", baseURL.ResolveReference(u).String(), content)
if err != nil {
return fmt.Errorf("error running route: %v", err)
}
req.Header.Set("Content-Type", "application/json")
envAsHeader(req, c.StringSlice("e"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("error running route: %v", err)
}
@@ -117,6 +142,19 @@ func (a *routesCmd) run(c *cli.Context) error {
return nil
}
func envAsHeader(req *http.Request, selectedEnv []string) {
detectedEnv := os.Environ()
if len(selectedEnv) > 0 {
detectedEnv = selectedEnv
}
for _, e := range detectedEnv {
kv := strings.Split(e, "=")
name := kv[0]
req.Header.Set(name, os.Getenv(name))
}
}
func (a *routesCmd) create(c *cli.Context) error {
if c.Args().Get(0) == "" || c.Args().Get(1) == "" || c.Args().Get(2) == "" {
return errors.New("error: routes listing takes three arguments: an app name, a route path and an image")

View File

@@ -1,18 +1,82 @@
package main
import (
"github.com/iron-io/functions_go"
"errors"
"fmt"
"os"
"os/exec"
"strings"
"github.com/urfave/cli"
)
func run() cli.Command {
r := routesCmd{RoutesApi: functions.NewRoutesApi()}
r := runCmd{}
return cli.Command{
Name: "run",
Usage: "run function",
ArgsUsage: "fnclt run appName /path",
Flags: append(confFlags(&r.Configuration), []cli.Flag{}...),
Usage: "run a function locally",
ArgsUsage: "USERNAME/image:tag",
Flags: append(runflags(), []cli.Flag{}...),
Action: r.run,
}
}
type runCmd struct{}
func runflags() []cli.Flag {
return []cli.Flag{
cli.StringSliceFlag{
Name: "e",
Usage: "limit the environment variables sent to function, if ommited then all are sent.",
},
}
}
func (r *runCmd) run(c *cli.Context) error {
image := c.Args().First()
if image == "" {
return errors.New("error: image name is missing")
}
sh := []string{"docker", "run", "--rm", "-i"}
var env []string
detectedEnv := os.Environ()
if se := c.StringSlice("e"); len(se) > 0 {
detectedEnv = se
}
for _, e := range detectedEnv {
shellvar, envvar := extractEnvVar(e)
sh = append(sh, shellvar...)
env = append(env, envvar)
}
dockerenv := []string{"DOCKER_TLS_VERIFY", "DOCKER_HOST", "DOCKER_CERT_PATH", "DOCKER_MACHINE_NAME"}
for _, e := range dockerenv {
env = append(env, fmt.Sprint(e, "=", os.Getenv(e)))
}
sh = append(sh, image)
cmd := exec.Command(sh[0], sh[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = env
return cmd.Run()
}
func extractEnvVar(e string) ([]string, string) {
kv := strings.Split(e, "=")
name := toEnvName("HEADER", kv[0])
sh := []string{"-e", name}
env := fmt.Sprintf("%s=%s", name, os.Getenv(kv[0]))
return sh, env
}
// From server.toEnvName()
func toEnvName(envtype, name string) string {
name = strings.ToUpper(strings.Replace(name, "-", "_", -1))
return fmt.Sprintf("%s_%s", envtype, name)
}