github.com/iron-io/functions@v0.0.0-20180820112432-d59d7d1c40b2/fn/commands/images/run.go (about) 1 package commands 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/iron-io/functions/fn/common" 7 "github.com/urfave/cli" 8 "io" 9 "os" 10 "os/exec" 11 "strings" 12 ) 13 14 func Run() cli.Command { 15 r := runCmd{} 16 17 return cli.Command{ 18 Name: "run", 19 Usage: "run a function locally", 20 ArgsUsage: "[username/image:tag]", 21 Flags: append(Runflags(), []cli.Flag{}...), 22 Action: r.run, 23 } 24 } 25 26 type runCmd struct{} 27 28 func Runflags() []cli.Flag { 29 return []cli.Flag{ 30 cli.StringSliceFlag{ 31 Name: "e", 32 Usage: "select environment variables to be sent to function", 33 }, 34 cli.StringSliceFlag{ 35 Name: "link", 36 Usage: "select container links for the function", 37 }, 38 cli.StringFlag{ 39 Name: "method", 40 Usage: "http method for function", 41 }, 42 } 43 } 44 45 func (r *runCmd) run(c *cli.Context) error { 46 image := c.Args().First() 47 if image == "" { 48 ff, err := common.LoadFuncfile() 49 if err != nil { 50 if _, ok := err.(*common.NotFoundError); ok { 51 return errors.New("error: image name is missing or no function file found") 52 } 53 return err 54 } 55 image = ff.FullName() 56 } 57 58 return Runff(image, Stdin(), os.Stdout, os.Stderr, c.String("method"), c.StringSlice("e"), c.StringSlice("link")) 59 } 60 61 func Runff(image string, stdin io.Reader, stdout, stderr io.Writer, method string, restrictedEnv []string, links []string) error { 62 sh := []string{"docker", "run", "--rm", "-i"} 63 64 var env []string 65 detectedEnv := os.Environ() 66 if len(restrictedEnv) > 0 { 67 detectedEnv = restrictedEnv 68 } 69 70 if method == "" { 71 if stdin == nil { 72 method = "GET" 73 } else { 74 method = "POST" 75 } 76 } 77 sh = append(sh, "-e", kvEq("METHOD", method)) 78 79 for _, e := range detectedEnv { 80 shellvar, envvar := extractEnvVar(e) 81 sh = append(sh, shellvar...) 82 env = append(env, envvar) 83 } 84 85 for _, l := range links { 86 sh = append(sh, "--link", l) 87 } 88 89 dockerenv := []string{"DOCKER_TLS_VERIFY", "DOCKER_HOST", "DOCKER_CERT_PATH", "DOCKER_MACHINE_NAME"} 90 for _, e := range dockerenv { 91 env = append(env, fmt.Sprint(e, "=", os.Getenv(e))) 92 } 93 94 sh = append(sh, image) 95 cmd := exec.Command(sh[0], sh[1:]...) 96 cmd.Stdin = stdin 97 cmd.Stdout = stdout 98 cmd.Stderr = stderr 99 cmd.Env = env 100 return cmd.Run() 101 } 102 103 func extractEnvVar(e string) ([]string, string) { 104 kv := strings.Split(e, "=") 105 name := toEnvName("HEADER", kv[0]) 106 sh := []string{"-e", name} 107 var v string 108 if len(kv) > 1 { 109 v = kv[1] 110 } else { 111 v = os.Getenv(kv[0]) 112 } 113 return sh, kvEq(name, v) 114 } 115 116 func kvEq(k, v string) string { 117 return fmt.Sprintf("%s=%s", k, v) 118 } 119 120 // From server.toEnvName() 121 func toEnvName(envtype, name string) string { 122 name = strings.ToUpper(strings.Replace(name, "-", "_", -1)) 123 return fmt.Sprintf("%s_%s", envtype, name) 124 }