github.com/fnproject/cli@v0.0.0-20240508150455-e5d88bd86117/commands/start.go (about) 1 /* 2 * Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package commands 18 19 import ( 20 "fmt" 21 "log" 22 "os" 23 "os/exec" 24 "os/signal" 25 "path/filepath" 26 "syscall" 27 28 "github.com/fnproject/cli/common" 29 "github.com/fnproject/cli/config" 30 "github.com/urfave/cli" 31 ) 32 33 // StartCommand returns start server cli.command 34 func StartCommand() cli.Command { 35 return cli.Command{ 36 Name: "start", 37 Usage: "Start a local Fn server", 38 Category: "SERVER COMMANDS", 39 Description: "This command starts a local Fn server by downloading its docker image.", 40 Action: start, 41 Flags: []cli.Flag{ 42 cli.StringFlag{ 43 Name: "log-level", 44 Usage: "--log-level debug to enable debugging", 45 }, 46 cli.BoolFlag{ 47 Name: "detach, d", 48 Usage: "Run container in background.", 49 }, 50 cli.StringFlag{ 51 Name: "env-file", 52 Usage: "Path to Fn server configuration file.", 53 }, 54 cli.StringFlag{ 55 Name: "version", 56 Usage: "Specify a specific fnproject/fnserver version to run, ex: '1.2.3'.", 57 Value: "latest", 58 }, 59 cli.IntFlag{ 60 Name: "port, p", 61 Value: 8080, 62 Usage: "Specify port number to bind to on the host.", 63 }, 64 }, 65 } 66 } 67 68 func start(c *cli.Context) error { 69 var fnDir string 70 home := config.GetHomeDir() 71 72 if c.String("data-dir") != "" { 73 fnDir = c.String("data-dir") 74 } else { 75 fnDir = filepath.Join(home, ".fn") 76 } 77 78 args := []string{"run", "--rm", "-i", 79 "--name", "fnserver", 80 "-v", fmt.Sprintf("%s/iofs:/iofs", fnDir), 81 "-e", fmt.Sprintf("FN_IOFS_DOCKER_PATH=%s/iofs", fnDir), 82 "-e", "FN_IOFS_PATH=/iofs", 83 "-v", fmt.Sprintf("%s/data:/app/data", fnDir), 84 "-v", "/var/run/docker.sock:/var/run/docker.sock", 85 "--privileged", 86 "-p", fmt.Sprintf("%d:8080", c.Int("port")), 87 "--entrypoint", "./fnserver", 88 } 89 if c.String("log-level") != "" { 90 args = append(args, "-e", fmt.Sprintf("FN_LOG_LEVEL=%v", c.String("log-level"))) 91 } 92 if c.String("env-file") != "" { 93 args = append(args, "--env-file", c.String("env-file")) 94 } 95 if c.Bool("detach") { 96 args = append(args, "-d") 97 } 98 99 image := fmt.Sprintf("%s:%s", common.FunctionsDockerImage, c.String("version")) 100 args = append(args, image) 101 cmd := exec.Command("docker", args...) 102 cmd.Stdout = os.Stdout 103 cmd.Stderr = os.Stderr 104 err := cmd.Start() 105 if err != nil { 106 log.Fatalln("Starting command failed:", err) 107 } 108 109 done := make(chan error, 1) 110 go func() { 111 done <- cmd.Wait() 112 }() 113 // catch ctrl-c and kill 114 sigC := make(chan os.Signal, 2) 115 signal.Notify(sigC, os.Interrupt, syscall.SIGTERM) 116 117 log.Println("¡¡¡ 'fn start' should NOT be used for PRODUCTION !!! see https://github.com/fnproject/fn-helm/") 118 119 for { 120 select { 121 case <-sigC: 122 log.Println("Interrupt caught, exiting") 123 err = cmd.Process.Signal(syscall.SIGTERM) 124 if err != nil { 125 log.Println("Error: could not kill process:", err) 126 return err 127 } 128 case err := <-done: 129 if err != nil { 130 log.Println("Error: processed finished with error", err) 131 } 132 } 133 return err 134 } 135 }