mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Merge branch 'master' into slack
This commit is contained in:
31
README.md
31
README.md
@@ -49,17 +49,19 @@ configuration options [here](docs/operating/options.md). If you are on Windows,
|
||||
|
||||
Functions are small but powerful blocks of code that generally do one simple thing. Forget about monoliths when using functions, just focus on the task that you want the function to perform.
|
||||
|
||||
The following is a simple Go program that outputs a string to STDOUT. Copy and paste the code below into a file called `func.go`. Currently the function must be named func.your_language_extention (ie func.go, func.js, etc.)
|
||||
First, create an empty directory called `hello` and cd into it.
|
||||
|
||||
The following is a simple Go program that outputs a string to STDOUT. Copy and paste the code below into a file called `func.go`.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("Hello from Fn!")
|
||||
fmt.Println("Hello from Fn!")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -68,12 +70,15 @@ Now run the following CLI commands:
|
||||
```sh
|
||||
# Initialize your function
|
||||
# This detects your runtime from the code above and creates a func.yaml
|
||||
fn init <DOCKERHUB_USERNAME>/hello
|
||||
fn init
|
||||
|
||||
# Test your function
|
||||
# This will run inside a container exactly how it will on the server
|
||||
fn run
|
||||
|
||||
# Set your Docker Hub username
|
||||
export FN_REGISTRY=<DOCKERHUB_USERNAME>
|
||||
|
||||
# Deploy your functions to the Fn server (default localhost:8080)
|
||||
# This will create a route to your function as well
|
||||
fn deploy myapp
|
||||
@@ -83,19 +88,21 @@ Now you can call your function:
|
||||
|
||||
```sh
|
||||
curl http://localhost:8080/r/myapp/hello
|
||||
# or:
|
||||
fn call myapp /hello
|
||||
```
|
||||
|
||||
Or in a browser: [http://localhost:8080/r/myapp/hello](http://localhost:8080/r/myapp/hello)
|
||||
|
||||
That's it! You just deployed your first function and called it. Now to update your function
|
||||
That's it! You just deployed your first function and called it. To update your function
|
||||
you can update your code and run `fn deploy myapp` again.
|
||||
|
||||
## To Learn More
|
||||
|
||||
- Visit our Functions [Tutorial Series](examples/tutorial/)
|
||||
- See our [full documentation](docs/README.md)
|
||||
- View all of our [examples](/examples)
|
||||
- You can also write your functions in AWS [Lambda format](docs/lambda/README.md)
|
||||
* Visit our Functions [Tutorial Series](examples/tutorial/)
|
||||
* See our [full documentation](docs/README.md)
|
||||
* View all of our [examples](/examples)
|
||||
* You can also write your functions in AWS [Lambda format](docs/lambda/README.md)
|
||||
|
||||
## Get Involved
|
||||
|
||||
@@ -103,7 +110,6 @@ you can update your code and run `fn deploy myapp` again.
|
||||
- Learn how to [contribute](CONTRIBUTING.md)
|
||||
- See [milestones](https://github.com/fnproject/fn/milestones) for detailed issues
|
||||
|
||||
|
||||
## User Interface
|
||||
|
||||
This is the graphical user interface for Fn. It is currently not buildable.
|
||||
@@ -114,9 +120,8 @@ docker run --rm -it --link functions:api -p 4000:4000 -e "API_URL=http://api:808
|
||||
|
||||
For more information, see: [https://github.com/treeder/functions-ui](https://github.com/treeder/functions-ui)
|
||||
|
||||
## Next up
|
||||
|
||||
# Next up
|
||||
|
||||
### Check out the [Tutorial Series](examples/tutorial/).
|
||||
### Check out the [Tutorial Series](examples/tutorial/)
|
||||
|
||||
It will demonstrate some of Fn capabilities through a series of exmaples. We'll try to show examples in most major languages. This is a great place to start!
|
||||
|
||||
@@ -4,6 +4,9 @@ all: vendor build
|
||||
build:
|
||||
go build -o fn
|
||||
|
||||
install:
|
||||
go build -o ${GOPATH}/bin/fn
|
||||
|
||||
docker: vendor
|
||||
GOOS=linux go build -o fn
|
||||
docker build -t treeder/fn .
|
||||
@@ -23,3 +26,5 @@ release:
|
||||
GOOS=darwin go build -o fn_mac
|
||||
GOOS=windows go build -o fn.exe
|
||||
docker run --rm -v ${PWD}:/go/src/github.com/fnproject/fn/cli -w /go/src/github.com/fnproject/fn/cli funcy/go:dev go build -o fn_alpine
|
||||
|
||||
.PHONY: install
|
||||
|
||||
@@ -12,13 +12,13 @@ if you are using Node, put the code that you want to execute in the file `func.j
|
||||
Run:
|
||||
|
||||
```sh
|
||||
fn init <DOCKER_HUB_USERNAME>/<FUNCTION_NAME>
|
||||
fn init [<FUNCTION_NAME>]
|
||||
```
|
||||
|
||||
If you want to override the convention with configuration, you can do that as well using:
|
||||
|
||||
```sh
|
||||
fn init [--runtime node] [--entrypoint "node hello.js"] <DOCKER_HUB_USERNAME>/<FUNCTION_NAME>
|
||||
fn init [--runtime node] [--entrypoint "node hello.js"] [<FUNCTION_NAME>]
|
||||
```
|
||||
|
||||
Or, if you want full control, just make a Dockerfile. If `init` finds a Dockerfile, it will use that instead of runtime and entrypoint.
|
||||
|
||||
49
cli/apps.go
49
cli/apps.go
@@ -102,17 +102,17 @@ func (a *appsCmd) list(c *cli.Context) error {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
// fmt.Println("err type:", reflect.TypeOf(err))
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiapps.GetAppsAppNotFound:
|
||||
return fmt.Errorf("error: %v", err.(*apiapps.GetAppsAppNotFound).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %v", e.Payload.Error.Message)
|
||||
case *apiapps.GetAppsAppDefault:
|
||||
return fmt.Errorf("unexpected error: %v", err.(*apiapps.GetAppsAppDefault).Payload.Error.Message)
|
||||
return fmt.Errorf("unexpected error: %v", e.Payload.Error.Message)
|
||||
case *apiapps.GetAppsDefault:
|
||||
// this is the one getting called, not sure what the one above is?
|
||||
return fmt.Errorf("unexpected error: %v", err.(*apiapps.GetAppsDefault).Payload.Error.Message)
|
||||
return fmt.Errorf("unexpected error: %v", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(resp.Payload.Apps) == 0 {
|
||||
@@ -139,15 +139,16 @@ func (a *appsCmd) create(c *cli.Context) error {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiapps.PostAppsBadRequest:
|
||||
return fmt.Errorf("error: %v", err.(*apiapps.PostAppsBadRequest).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %v", e.Payload.Error.Message)
|
||||
case *apiapps.PostAppsConflict:
|
||||
return fmt.Errorf("error: %v", err.(*apiapps.PostAppsConflict).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %v", e.Payload.Error.Message)
|
||||
case *apiapps.PostAppsDefault:
|
||||
return fmt.Errorf("unexpected error: %v", err.(*apiapps.PostAppsDefault).Payload.Error.Message)
|
||||
return fmt.Errorf("unexpected error: %v", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("Successfully created app: ", resp.Payload.App.Name)
|
||||
@@ -215,15 +216,16 @@ func (a *appsCmd) patchApp(appName string, app *models.App) error {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiapps.PatchAppsAppBadRequest:
|
||||
return errors.New(err.(*apiapps.PatchAppsAppBadRequest).Payload.Error.Message)
|
||||
return errors.New(e.Payload.Error.Message)
|
||||
case *apiapps.PatchAppsAppNotFound:
|
||||
return errors.New(err.(*apiapps.PatchAppsAppNotFound).Payload.Error.Message)
|
||||
return errors.New(e.Payload.Error.Message)
|
||||
case *apiapps.PatchAppsAppDefault:
|
||||
return errors.New(err.(*apiapps.PatchAppsAppDefault).Payload.Error.Message)
|
||||
return errors.New(e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -243,13 +245,14 @@ func (a *appsCmd) inspect(c *cli.Context) error {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiapps.GetAppsAppNotFound:
|
||||
return fmt.Errorf("error: %v", err.(*apiapps.GetAppsAppNotFound).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %v", e.Payload.Error.Message)
|
||||
case *apiapps.GetAppsAppDefault:
|
||||
return fmt.Errorf("unexpected error: %v", err.(*apiapps.GetAppsAppDefault).Payload.Error.Message)
|
||||
return fmt.Errorf("unexpected error: %v", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
@@ -294,11 +297,11 @@ func (a *appsCmd) delete(c *cli.Context) error {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiapps.DeleteAppsAppNotFound:
|
||||
return errors.New(err.(*apiapps.DeleteAppsAppNotFound).Payload.Error.Message)
|
||||
return errors.New(e.Payload.Error.Message)
|
||||
case *apiapps.DeleteAppsAppDefault:
|
||||
return errors.New(err.(*apiapps.DeleteAppsAppDefault).Payload.Error.Message)
|
||||
return errors.New(e.Payload.Error.Message)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
@@ -40,8 +40,6 @@ func (b *buildcmd) flags() []cli.Flag {
|
||||
|
||||
// build will take the found valid function and build it
|
||||
func (b *buildcmd) build(c *cli.Context) error {
|
||||
verbwriter := verbwriter(b.verbose)
|
||||
|
||||
path, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -51,11 +49,11 @@ func (b *buildcmd) build(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
ff, err := buildfunc(verbwriter, fn, b.noCache)
|
||||
ff, err := buildfunc(fn, b.noCache)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Function %v built successfully.\n", ff.FullName())
|
||||
fmt.Printf("Function %v built successfully.\n", ff.ImageName())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ func (b *bumpcmd) flags() []cli.Flag {
|
||||
|
||||
// bump will take the found valid function and bump its version
|
||||
func (b *bumpcmd) bump(c *cli.Context) error {
|
||||
verbwriter := verbwriter(b.verbose)
|
||||
|
||||
path, err := os.Getwd()
|
||||
if err != nil {
|
||||
@@ -52,7 +51,7 @@ func (b *bumpcmd) bump(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(verbwriter, "bumping version for", fn)
|
||||
fmt.Println("bumping version for", fn)
|
||||
|
||||
funcfile, err := parsefuncfile(fn)
|
||||
if err != nil {
|
||||
|
||||
16
cli/calls.go
16
cli/calls.go
@@ -64,12 +64,12 @@ func (call *callsCmd) get(ctx *cli.Context) error {
|
||||
}
|
||||
resp, err := call.client.Call.GetAppsAppCallsCall(¶ms)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apicall.GetAppsAppCallsCallNotFound:
|
||||
return fmt.Errorf("error: %v", err.(*apicall.GetAppsAppCallsCallNotFound).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %v", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
|
||||
}
|
||||
printCalls([]*models.Call{resp.Payload.Call})
|
||||
return nil
|
||||
@@ -87,12 +87,12 @@ func (call *callsCmd) list(ctx *cli.Context) error {
|
||||
}
|
||||
resp, err := call.client.Call.GetAppsAppCalls(¶ms)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apicall.GetCallsCallNotFound:
|
||||
return fmt.Errorf("error: %v", err.(*apicall.GetCallsCallNotFound).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %v", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
|
||||
}
|
||||
printCalls(resp.Payload.Calls)
|
||||
return nil
|
||||
|
||||
@@ -11,6 +11,10 @@ import (
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
const (
|
||||
envFnToken = "FN_TOKEN"
|
||||
)
|
||||
|
||||
func Host() string {
|
||||
apiURL := os.Getenv("API_URL")
|
||||
if apiURL == "" {
|
||||
@@ -26,8 +30,8 @@ func Host() string {
|
||||
|
||||
func APIClient() *fnclient.Functions {
|
||||
transport := httptransport.New(Host(), "/v1", []string{"http"})
|
||||
if os.Getenv("FN_TOKEN") != "" {
|
||||
transport.DefaultAuthentication = httptransport.BearerToken(os.Getenv("FN_TOKEN"))
|
||||
if os.Getenv(envFnToken) != "" {
|
||||
transport.DefaultAuthentication = httptransport.BearerToken(os.Getenv(envFnToken))
|
||||
}
|
||||
|
||||
// create the API client, with the transport
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
@@ -22,18 +23,23 @@ import (
|
||||
const (
|
||||
functionsDockerImage = "funcy/functions"
|
||||
minRequiredDockerVersion = "17.5.0"
|
||||
envFnRegistry = "FN_REGISTRY"
|
||||
)
|
||||
|
||||
func verbwriter(verbose bool) io.Writer {
|
||||
// this is too limiting, removes all logs which isn't what we want
|
||||
// verbwriter := ioutil.Discard
|
||||
// if verbose {
|
||||
verbwriter := os.Stderr
|
||||
// }
|
||||
return verbwriter
|
||||
type HasRegistry interface {
|
||||
Registry() string
|
||||
}
|
||||
|
||||
func buildfunc(verbwriter io.Writer, fn string, noCache bool) (*funcfile, error) {
|
||||
func setRegistryEnv(hr HasRegistry) {
|
||||
if hr.Registry() != "" {
|
||||
err := os.Setenv(envFnRegistry, hr.Registry())
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't set %s env var: %v\n", envFnRegistry, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func buildfunc(fn string, noCache bool) (*funcfile, error) {
|
||||
funcfile, err := parsefuncfile(fn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -53,23 +59,21 @@ func buildfunc(verbwriter io.Writer, fn string, noCache bool) (*funcfile, error)
|
||||
}
|
||||
}
|
||||
|
||||
if err := localbuild(verbwriter, fn, funcfile.Build); err != nil {
|
||||
if err := localbuild(fn, funcfile.Build); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := dockerbuild(verbwriter, fn, funcfile, noCache); err != nil {
|
||||
if err := dockerbuild(fn, funcfile, noCache); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return funcfile, nil
|
||||
}
|
||||
|
||||
func localbuild(verbwriter io.Writer, path string, steps []string) error {
|
||||
func localbuild(path string, steps []string) error {
|
||||
for _, cmd := range steps {
|
||||
exe := exec.Command("/bin/sh", "-c", cmd)
|
||||
exe.Dir = filepath.Dir(path)
|
||||
exe.Stderr = verbwriter
|
||||
exe.Stdout = verbwriter
|
||||
if err := exe.Run(); err != nil {
|
||||
return fmt.Errorf("error running command %v (%v)", cmd, err)
|
||||
}
|
||||
@@ -78,7 +82,7 @@ func localbuild(verbwriter io.Writer, path string, steps []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func dockerbuild(verbwriter io.Writer, path string, ff *funcfile, noCache bool) error {
|
||||
func dockerbuild(path string, ff *funcfile, noCache bool) error {
|
||||
err := dockerVersionCheck()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -89,9 +93,9 @@ func dockerbuild(verbwriter io.Writer, path string, ff *funcfile, noCache bool)
|
||||
var helper langs.LangHelper
|
||||
dockerfile := filepath.Join(dir, "Dockerfile")
|
||||
if !exists(dockerfile) {
|
||||
helper = langs.GetLangHelper(*ff.Runtime)
|
||||
helper = langs.GetLangHelper(ff.Runtime)
|
||||
if helper == nil {
|
||||
return fmt.Errorf("Cannot build, no language helper found for %v", *ff.Runtime)
|
||||
return fmt.Errorf("Cannot build, no language helper found for %v", ff.Runtime)
|
||||
}
|
||||
dockerfile, err = writeTmpDockerfile(helper, dir, ff)
|
||||
if err != nil {
|
||||
@@ -106,7 +110,7 @@ func dockerbuild(verbwriter io.Writer, path string, ff *funcfile, noCache bool)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Building image %v\n", ff.FullName())
|
||||
fmt.Printf("Building image %v\n", ff.ImageName())
|
||||
|
||||
cancel := make(chan os.Signal, 3)
|
||||
signal.Notify(cancel, os.Interrupt) // and others perhaps
|
||||
@@ -117,7 +121,7 @@ func dockerbuild(verbwriter io.Writer, path string, ff *funcfile, noCache bool)
|
||||
go func(done chan<- error) {
|
||||
args := []string{
|
||||
"build",
|
||||
"-t", ff.FullName(),
|
||||
"-t", ff.ImageName(),
|
||||
"-f", dockerfile,
|
||||
}
|
||||
if noCache {
|
||||
@@ -261,8 +265,12 @@ func extractEnvConfig(configs []string) map[string]string {
|
||||
}
|
||||
|
||||
func dockerpush(ff *funcfile) error {
|
||||
fmt.Println("Pushing to docker registry...")
|
||||
cmd := exec.Command("docker", "push", ff.FullName())
|
||||
err := validImageName(ff.ImageName())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Pushing %v to docker registry...", ff.ImageName())
|
||||
cmd := exec.Command("docker", "push", ff.ImageName())
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
if err := cmd.Run(); err != nil {
|
||||
@@ -271,6 +279,19 @@ func dockerpush(ff *funcfile) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validImageName(n string) error {
|
||||
// must have at least owner name and a tag
|
||||
split := strings.Split(n, ":")
|
||||
if len(split) < 2 {
|
||||
return errors.New("image name must have a tag")
|
||||
}
|
||||
split2 := strings.Split(split[0], "/")
|
||||
if len(split2) < 2 {
|
||||
return errors.New("image name must have an owner and name, eg: username/myfunc. Be sure to set FN_REGISTRY env var or pass in --registry.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func appNamePath(img string) (string, string) {
|
||||
sep := strings.Index(img, "/")
|
||||
if sep < 0 {
|
||||
|
||||
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
@@ -40,8 +39,11 @@ type deploycmd struct {
|
||||
incremental bool
|
||||
skippush bool
|
||||
noCache bool
|
||||
registry string
|
||||
}
|
||||
|
||||
verbwriter io.Writer
|
||||
func (cmd *deploycmd) Registry() string {
|
||||
return cmd.registry
|
||||
}
|
||||
|
||||
func (p *deploycmd) flags() []cli.Flag {
|
||||
@@ -73,18 +75,23 @@ func (p *deploycmd) flags() []cli.Flag {
|
||||
Usage: "does not push Docker built images onto Docker Hub - useful for local development.",
|
||||
Destination: &p.skippush,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "registry",
|
||||
Usage: "Sets the Docker owner for images and optionally the registry. This will be prefixed to your function name for pushing to Docker registries. eg: `--registry username` will set your Docker Hub owner. `--registry registry.hub.docker.com/username` will set the registry and owner.",
|
||||
Destination: &p.registry,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *deploycmd) scan(c *cli.Context) error {
|
||||
p.appName = c.Args().First()
|
||||
p.verbwriter = verbwriter(p.verbose)
|
||||
|
||||
var walked bool
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatalln("Couldn't get working directory:", err)
|
||||
}
|
||||
setRegistryEnv(p)
|
||||
|
||||
err = filepath.Walk(wd, func(path string, info os.FileInfo, err error) error {
|
||||
if path != wd && info.IsDir() {
|
||||
@@ -101,7 +108,7 @@ func (p *deploycmd) scan(c *cli.Context) error {
|
||||
|
||||
e := p.deploy(c, path)
|
||||
if err != nil {
|
||||
fmt.Fprintln(p.verbwriter, path, e)
|
||||
fmt.Println(path, e)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
@@ -110,7 +117,7 @@ func (p *deploycmd) scan(c *cli.Context) error {
|
||||
return e
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(p.verbwriter, "error: %s\n", err)
|
||||
fmt.Printf("error: %s\n", err)
|
||||
}
|
||||
|
||||
if !walked {
|
||||
@@ -132,7 +139,7 @@ func (p *deploycmd) deploy(c *cli.Context, funcFilePath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
funcfile, err := buildfunc(p.verbwriter, funcFileName, p.noCache)
|
||||
funcfile, err := buildfunc(funcFileName, p.noCache)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -152,14 +159,14 @@ func (p *deploycmd) deploy(c *cli.Context, funcFilePath string) error {
|
||||
}
|
||||
|
||||
func (p *deploycmd) route(c *cli.Context, ff *funcfile) error {
|
||||
fmt.Printf("Updating route %s using image %s...\n", ff.Path, ff.FullName())
|
||||
fmt.Printf("Updating route %s using image %s...\n", ff.Path, ff.ImageName())
|
||||
if err := resetBasePath(p.Configuration); err != nil {
|
||||
return fmt.Errorf("error setting endpoint: %v", err)
|
||||
}
|
||||
|
||||
routesCmd := routesCmd{client: client.APIClient()}
|
||||
rt := &models.Route{}
|
||||
if err := routeWithFuncFile(c, ff, rt); err != nil {
|
||||
if err := routeWithFuncFile(ff, rt); err != nil {
|
||||
return fmt.Errorf("error getting route with funcfile: %s", err)
|
||||
}
|
||||
return routesCmd.putRoute(c, p.appName, ff.Path, rt)
|
||||
|
||||
107
cli/funcfile.go
107
cli/funcfile.go
@@ -9,7 +9,6 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
fnmodels "github.com/funcy/functions_go/models"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
@@ -39,19 +38,37 @@ type fftest struct {
|
||||
}
|
||||
|
||||
type funcfile struct {
|
||||
fnmodels.Route
|
||||
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Version string `yaml:"version,omitempty" json:"version,omitempty"`
|
||||
Runtime *string `yaml:"runtime,omitempty" json:"runtime,omitempty"`
|
||||
Runtime string `yaml:"runtime,omitempty" json:"runtime,omitempty"`
|
||||
Entrypoint string `yaml:"entrypoint,omitempty" json:"entrypoint,omitempty"`
|
||||
Cmd string `yaml:"cmd,omitempty" json:"cmd,omitempty"`
|
||||
Build []string `yaml:"build,omitempty" json:"build,omitempty"`
|
||||
Tests []fftest `yaml:"tests,omitempty" json:"tests,omitempty"`
|
||||
|
||||
// route specific
|
||||
Type string `yaml:"type,omitempty" json:"type,omitempty"`
|
||||
Memory uint64 `yaml:"memory,omitempty" json:"memory,omitempty"`
|
||||
Format string `yaml:"format,omitempty" json:"format,omitempty"`
|
||||
Timeout *int32 `yaml:"timeout,omitempty" json:"timeout,omitempty"`
|
||||
Path string `yaml:"path,omitempty" json:"path,omitempty"`
|
||||
Config map[string]string `yaml:"config,omitempty" json:"config,omitempty"`
|
||||
Headers map[string][]string `yaml:"headers,omitempty" json:"headers,omitempty"`
|
||||
IDLETimeout *int32 `yaml:"idle_timeout,omitempty" json:"idle_timeout,omitempty"`
|
||||
}
|
||||
|
||||
func (ff *funcfile) FullName() string {
|
||||
func (ff *funcfile) ImageName() string {
|
||||
fname := ff.Name
|
||||
if !strings.Contains(fname, "/") {
|
||||
// then we'll prefix FN_REGISTRY
|
||||
reg := os.Getenv(envFnRegistry)
|
||||
if reg != "" {
|
||||
if reg[len(reg)-1] != '/' {
|
||||
reg += "/"
|
||||
}
|
||||
fname = fmt.Sprintf("%s%s", reg, fname)
|
||||
}
|
||||
}
|
||||
if ff.Version != "" {
|
||||
fname = fmt.Sprintf("%s:%s", fname, ff.Version)
|
||||
}
|
||||
@@ -59,11 +76,11 @@ func (ff *funcfile) FullName() string {
|
||||
}
|
||||
|
||||
func (ff *funcfile) RuntimeTag() (runtime, tag string) {
|
||||
if ff.Runtime == nil {
|
||||
if ff.Runtime == "" {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
rt := *ff.Runtime
|
||||
rt := ff.Runtime
|
||||
tagpos := strings.Index(rt, ":")
|
||||
if tagpos == -1 {
|
||||
return rt, ""
|
||||
@@ -72,65 +89,6 @@ func (ff *funcfile) RuntimeTag() (runtime, tag string) {
|
||||
return rt[:tagpos], rt[tagpos+1:]
|
||||
}
|
||||
|
||||
type flatfuncfile struct {
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Version string `yaml:"version,omitempty" json:"version,omitempty"`
|
||||
Runtime *string `yaml:"runtime,omitempty" json:"runtime,omitempty"`
|
||||
Entrypoint string `yaml:"entrypoint,omitempty" json:"entrypoint,omitempty"`
|
||||
Cmd string `yaml:"cmd,omitempty" json:"cmd,omitempty"`
|
||||
Build []string `yaml:"build,omitempty" json:"build,omitempty"`
|
||||
Tests []fftest `yaml:"tests,omitempty" json:"tests,omitempty"`
|
||||
|
||||
// route specific
|
||||
Type string `yaml:"type,omitempty" json:"type,omitempty"`
|
||||
Memory uint64 `yaml:"memory,omitempty" json:"memory,omitempty"`
|
||||
Format string `yaml:"format,omitempty" json:"format,omitempty"`
|
||||
Timeout *int32 `yaml:"timeout,omitempty" json:"timeout,omitempty"`
|
||||
Path string `yaml:"path,omitempty" json:"path,omitempty"`
|
||||
Config map[string]string `yaml:"config,omitempty" json:"config,omitempty"`
|
||||
Headers map[string][]string `yaml:"headers,omitempty" json:"headers,omitempty"`
|
||||
}
|
||||
|
||||
func (ff *funcfile) MakeFlat() flatfuncfile {
|
||||
return flatfuncfile{
|
||||
Name: ff.Name,
|
||||
Version: ff.Version,
|
||||
Runtime: ff.Runtime,
|
||||
Entrypoint: ff.Entrypoint,
|
||||
Cmd: ff.Cmd,
|
||||
Build: ff.Build,
|
||||
Tests: ff.Tests,
|
||||
// route-specific
|
||||
Type: ff.Type,
|
||||
Memory: ff.Memory,
|
||||
Format: ff.Format,
|
||||
Timeout: ff.Timeout,
|
||||
Path: ff.Path,
|
||||
Config: ff.Config,
|
||||
Headers: ff.Headers,
|
||||
}
|
||||
}
|
||||
|
||||
func (fff *flatfuncfile) MakeFuncFile() *funcfile {
|
||||
ff := &funcfile{
|
||||
Name: fff.Name,
|
||||
Version: fff.Version,
|
||||
Runtime: fff.Runtime,
|
||||
Entrypoint: fff.Entrypoint,
|
||||
Cmd: fff.Cmd,
|
||||
Build: fff.Build,
|
||||
Tests: fff.Tests,
|
||||
}
|
||||
ff.Type = fff.Type
|
||||
ff.Memory = fff.Memory
|
||||
ff.Format = fff.Format
|
||||
ff.Timeout = fff.Timeout
|
||||
ff.Path = fff.Path
|
||||
ff.Config = fff.Config
|
||||
ff.Headers = fff.Headers
|
||||
return ff
|
||||
}
|
||||
|
||||
func findFuncfile(path string) (string, error) {
|
||||
for _, fn := range validfn {
|
||||
fullfn := filepath.Join(path, fn)
|
||||
@@ -176,9 +134,10 @@ func decodeFuncfileJSON(path string) (*funcfile, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not open %s for parsing. Error: %v", path, err)
|
||||
}
|
||||
fff := new(flatfuncfile)
|
||||
err = json.NewDecoder(f).Decode(fff)
|
||||
ff := fff.MakeFuncFile()
|
||||
ff := &funcfile{}
|
||||
// ff.Route = &fnmodels.Route{}
|
||||
err = json.NewDecoder(f).Decode(ff)
|
||||
// ff := fff.MakeFuncFile()
|
||||
return ff, err
|
||||
}
|
||||
|
||||
@@ -187,9 +146,9 @@ func decodeFuncfileYAML(path string) (*funcfile, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not open %s for parsing. Error: %v", path, err)
|
||||
}
|
||||
fff := new(flatfuncfile)
|
||||
err = yaml.Unmarshal(b, fff)
|
||||
ff := fff.MakeFuncFile()
|
||||
ff := &funcfile{}
|
||||
err = yaml.Unmarshal(b, ff)
|
||||
// ff := fff.MakeFuncFile()
|
||||
return ff, err
|
||||
}
|
||||
|
||||
@@ -198,11 +157,11 @@ func encodeFuncfileJSON(path string, ff *funcfile) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not open %s for encoding. Error: %v", path, err)
|
||||
}
|
||||
return json.NewEncoder(f).Encode(ff.MakeFlat())
|
||||
return json.NewEncoder(f).Encode(ff)
|
||||
}
|
||||
|
||||
func encodeFuncfileYAML(path string, ff *funcfile) error {
|
||||
b, err := yaml.Marshal(ff.MakeFlat())
|
||||
b, err := yaml.Marshal(ff)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not encode function file. Error: %v", err)
|
||||
}
|
||||
|
||||
88
cli/init.go
88
cli/init.go
@@ -45,12 +45,8 @@ func init() {
|
||||
}
|
||||
|
||||
type initFnCmd struct {
|
||||
name string
|
||||
force bool
|
||||
runtime string
|
||||
entrypoint string
|
||||
cmd string
|
||||
version string
|
||||
force bool
|
||||
funcfile
|
||||
}
|
||||
|
||||
func initFlags(a *initFnCmd) []cli.Flag {
|
||||
@@ -63,17 +59,22 @@ func initFlags(a *initFnCmd) []cli.Flag {
|
||||
cli.StringFlag{
|
||||
Name: "runtime",
|
||||
Usage: "choose an existing runtime - " + strings.Join(fnInitRuntimes, ", "),
|
||||
Destination: &a.runtime,
|
||||
Destination: &a.Runtime,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "entrypoint",
|
||||
Usage: "entrypoint is the command to run to start this function - equivalent to Dockerfile ENTRYPOINT.",
|
||||
Destination: &a.entrypoint,
|
||||
Destination: &a.Entrypoint,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cmd",
|
||||
Usage: "command to run to start this function - equivalent to Dockerfile CMD.",
|
||||
Destination: &a.Entrypoint,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "version",
|
||||
Usage: "function version",
|
||||
Destination: &a.version,
|
||||
Destination: &a.Version,
|
||||
Value: initialVersion,
|
||||
},
|
||||
}
|
||||
@@ -82,15 +83,16 @@ func initFlags(a *initFnCmd) []cli.Flag {
|
||||
}
|
||||
|
||||
func initFn() cli.Command {
|
||||
a := initFnCmd{}
|
||||
a := &initFnCmd{}
|
||||
// funcfile := &funcfile{}
|
||||
|
||||
return cli.Command{
|
||||
Name: "init",
|
||||
Usage: "create a local func.yaml file",
|
||||
Description: "Creates a func.yaml file in the current directory. ",
|
||||
ArgsUsage: "<DOCKERHUB_USERNAME/FUNCTION_NAME>",
|
||||
Description: "Creates a func.yaml file in the current directory.",
|
||||
ArgsUsage: "[FUNCTION_NAME]",
|
||||
Action: a.init,
|
||||
Flags: initFlags(&a),
|
||||
Flags: initFlags(a),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,13 +111,13 @@ func (a *initFnCmd) init(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
runtimeSpecified := a.runtime != ""
|
||||
|
||||
err := a.buildFuncFile(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtimeSpecified := a.Runtime != ""
|
||||
|
||||
if runtimeSpecified {
|
||||
err := a.generateBoilerplate()
|
||||
if err != nil {
|
||||
@@ -123,21 +125,12 @@ func (a *initFnCmd) init(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
ff := &funcfile{
|
||||
*rt,
|
||||
a.name,
|
||||
a.version,
|
||||
&a.runtime,
|
||||
a.entrypoint,
|
||||
a.cmd,
|
||||
[]string{},
|
||||
[]fftest{},
|
||||
}
|
||||
ff := a.funcfile
|
||||
|
||||
_, path := appNamePath(ff.FullName())
|
||||
_, path := appNamePath(ff.ImageName())
|
||||
ff.Path = path
|
||||
|
||||
if err := encodeFuncfileYAML("func.yaml", ff); err != nil {
|
||||
if err := encodeFuncfileYAML("func.yaml", &ff); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -146,7 +139,7 @@ func (a *initFnCmd) init(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func (a *initFnCmd) generateBoilerplate() error {
|
||||
helper := langs.GetLangHelper(a.runtime)
|
||||
helper := langs.GetLangHelper(a.Runtime)
|
||||
if helper != nil && helper.HasBoilerplate() {
|
||||
if err := helper.GenerateBoilerplate(); err != nil {
|
||||
if err == langs.ErrBoilerplateExists {
|
||||
@@ -162,47 +155,52 @@ func (a *initFnCmd) generateBoilerplate() error {
|
||||
func (a *initFnCmd) buildFuncFile(c *cli.Context) error {
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error detecting current working directory: %s", err)
|
||||
return fmt.Errorf("error detecting current working directory: %v", err)
|
||||
}
|
||||
|
||||
a.name = c.Args().First()
|
||||
if a.name == "" || strings.Contains(a.name, ":") {
|
||||
return errors.New("please specify a name for your function in the following format <DOCKERHUB_USERNAME>/<FUNCTION_NAME>.\nTry: fn init <DOCKERHUB_USERNAME>/<FUNCTION_NAME>")
|
||||
a.Name = c.Args().First()
|
||||
// if a.name == "" {
|
||||
// // return errors.New("please specify a name for your function.\nTry: fn init <FUNCTION_NAME>")
|
||||
// } else
|
||||
if a.Name == "" {
|
||||
// then use current directory for name
|
||||
a.Name = filepath.Base(pwd)
|
||||
} else if strings.Contains(a.Name, ":") {
|
||||
return errors.New("function name cannot contain a colon")
|
||||
}
|
||||
|
||||
if exists("Dockerfile") {
|
||||
fmt.Println("Dockerfile found. Let's use that to build...")
|
||||
return nil
|
||||
}
|
||||
|
||||
var rt string
|
||||
if a.runtime == "" {
|
||||
if a.Runtime == "" {
|
||||
rt, err = detectRuntime(pwd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.runtime = rt
|
||||
a.Runtime = rt
|
||||
fmt.Printf("Found %v, assuming %v runtime.\n", rt, rt)
|
||||
} else {
|
||||
fmt.Println("Runtime:", a.runtime)
|
||||
fmt.Println("Runtime:", a.Runtime)
|
||||
}
|
||||
helper := langs.GetLangHelper(a.runtime)
|
||||
helper := langs.GetLangHelper(a.Runtime)
|
||||
if helper == nil {
|
||||
fmt.Printf("init does not support the %s runtime, you'll have to create your own Dockerfile for this function", a.runtime)
|
||||
fmt.Printf("init does not support the %s runtime, you'll have to create your own Dockerfile for this function", a.Runtime)
|
||||
}
|
||||
|
||||
if a.entrypoint == "" {
|
||||
if a.Entrypoint == "" {
|
||||
if helper != nil {
|
||||
a.entrypoint = helper.Entrypoint()
|
||||
a.Entrypoint = helper.Entrypoint()
|
||||
}
|
||||
}
|
||||
if a.cmd == "" {
|
||||
if a.Cmd == "" {
|
||||
if helper != nil {
|
||||
a.cmd = helper.Cmd()
|
||||
a.Cmd = helper.Cmd()
|
||||
}
|
||||
}
|
||||
if a.entrypoint == "" && a.cmd == "" {
|
||||
return fmt.Errorf("could not detect entrypoint or cmd for %v, use --entrypoint and/or --cmd to set them explicitly", a.runtime)
|
||||
if a.Entrypoint == "" && a.Cmd == "" {
|
||||
return fmt.Errorf("could not detect entrypoint or cmd for %v, use --entrypoint and/or --cmd to set them explicitly", a.Runtime)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -221,5 +219,5 @@ func detectRuntime(path string) (runtime string, err error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no supported files found to guess runtime, please set runtime explicitly with --runtime flag.")
|
||||
return "", fmt.Errorf("no supported files found to guess runtime, please set runtime explicitly with --runtime flag")
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ func createFunctionYaml(opts createImageOptions, functionName string) error {
|
||||
funcDesc := &funcfile{
|
||||
Name: opts.Name,
|
||||
Version: "0.0.1",
|
||||
Runtime: &opts.Base,
|
||||
Runtime: opts.Base,
|
||||
Cmd: opts.Handler,
|
||||
}
|
||||
funcDesc.Config = opts.Config
|
||||
|
||||
@@ -41,12 +41,12 @@ func (log *logsCmd) get(ctx *cli.Context) error {
|
||||
}
|
||||
resp, err := log.client.Operations.GetAppsAppCallsCallLog(¶ms)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apicall.GetAppsAppCallsCallLogNotFound:
|
||||
return fmt.Errorf("error: %v", err.(*apicall.GetAppsAppCallsCallLogNotFound).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %v", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
|
||||
}
|
||||
fmt.Print(resp.Payload.Log.Log)
|
||||
return nil
|
||||
|
||||
@@ -132,7 +132,7 @@ func main() {
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
// TODO: this doesn't seem to get called even when an error returns from a command, but maybe urfave is doing a non zero exit anyways? nope: https://github.com/urfave/cli/issues/610
|
||||
fmt.Printf("Error occurred: %v, exiting...\n", err)
|
||||
fmt.Fprintf(os.Stderr, "Error occurred: %v, exiting...\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
18
cli/push.go
18
cli/push.go
@@ -20,7 +20,12 @@ func push() cli.Command {
|
||||
}
|
||||
|
||||
type pushcmd struct {
|
||||
verbose bool
|
||||
verbose bool
|
||||
registry string
|
||||
}
|
||||
|
||||
func (cmd *pushcmd) Registry() string {
|
||||
return cmd.registry
|
||||
}
|
||||
|
||||
func (p *pushcmd) flags() []cli.Flag {
|
||||
@@ -30,6 +35,11 @@ func (p *pushcmd) flags() []cli.Flag {
|
||||
Usage: "verbose mode",
|
||||
Destination: &p.verbose,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "registry",
|
||||
Usage: "Sets the Docker owner for images and optionally the registry. This will be prefixed to your function name for pushing to Docker registries. eg: `--registry username` will set your Docker Hub owner. `--registry registry.hub.docker.com/username` will set the registry and owner.",
|
||||
Destination: &p.registry,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +48,7 @@ func (p *pushcmd) flags() []cli.Flag {
|
||||
// push the container, and finally it will update function's route. Optionally,
|
||||
// the route can be overriden inside the functions file.
|
||||
func (p *pushcmd) push(c *cli.Context) error {
|
||||
verbwriter := verbwriter(p.verbose)
|
||||
setRegistryEnv(p)
|
||||
|
||||
ff, err := loadFuncfile()
|
||||
if err != nil {
|
||||
@@ -48,12 +58,12 @@ func (p *pushcmd) push(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(verbwriter, "pushing", ff.FullName())
|
||||
fmt.Println("pushing", ff.ImageName())
|
||||
|
||||
if err := dockerpush(ff); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Function %v pushed successfully to Docker Hub.\n", ff.FullName())
|
||||
fmt.Printf("Function %v pushed successfully to Docker Hub.\n", ff.ImageName())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -181,13 +181,14 @@ func (a *routesCmd) list(c *cli.Context) error {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiroutes.GetAppsAppRoutesNotFound:
|
||||
return fmt.Errorf("error: %s", err.(*apiroutes.GetAppsAppRoutesNotFound).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %s", e.Payload.Error.Message)
|
||||
case *apiroutes.GetAppsAppRoutesDefault:
|
||||
return fmt.Errorf("unexpected error: %s", err.(*apiroutes.GetAppsAppRoutesDefault).Payload.Error.Message)
|
||||
return fmt.Errorf("unexpected error: %s", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
|
||||
@@ -260,7 +261,7 @@ func routeWithFlags(c *cli.Context, rt *fnmodels.Route) {
|
||||
}
|
||||
}
|
||||
|
||||
func routeWithFuncFile(c *cli.Context, ff *funcfile, rt *fnmodels.Route) error {
|
||||
func routeWithFuncFile(ff *funcfile, rt *fnmodels.Route) error {
|
||||
var err error
|
||||
if ff == nil {
|
||||
ff, err = loadFuncfile()
|
||||
@@ -268,8 +269,8 @@ func routeWithFuncFile(c *cli.Context, ff *funcfile, rt *fnmodels.Route) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if ff.FullName() != "" { // args take precedence
|
||||
rt.Image = ff.FullName()
|
||||
if ff.ImageName() != "" { // args take precedence
|
||||
rt.Image = ff.ImageName()
|
||||
}
|
||||
if ff.Format != "" {
|
||||
rt.Format = ff.Format
|
||||
@@ -286,7 +287,15 @@ func routeWithFuncFile(c *cli.Context, ff *funcfile, rt *fnmodels.Route) error {
|
||||
if ff.Memory != 0 {
|
||||
rt.Memory = ff.Memory
|
||||
}
|
||||
// TODO idle_timeout? headers? config? why is a func file not a yaml unmarshal of a route?
|
||||
if rt.IDLETimeout != nil {
|
||||
rt.IDLETimeout = ff.IDLETimeout
|
||||
}
|
||||
if len(rt.Headers) != 0 {
|
||||
rt.Headers = ff.Headers
|
||||
}
|
||||
if len(rt.Config) != 0 {
|
||||
rt.Config = ff.Config
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -299,7 +308,7 @@ func (a *routesCmd) create(c *cli.Context) error {
|
||||
rt.Path = route
|
||||
rt.Image = c.Args().Get(2)
|
||||
|
||||
if err := routeWithFuncFile(c, nil, rt); err != nil {
|
||||
if err := routeWithFuncFile(nil, rt); err != nil {
|
||||
return fmt.Errorf("error getting route info: %s", err)
|
||||
}
|
||||
|
||||
@@ -328,15 +337,16 @@ func (a *routesCmd) postRoute(c *cli.Context, appName string, rt *fnmodels.Route
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiroutes.PostAppsAppRoutesBadRequest:
|
||||
return fmt.Errorf("error: %s", err.(*apiroutes.PostAppsAppRoutesBadRequest).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %s", e.Payload.Error.Message)
|
||||
case *apiroutes.PostAppsAppRoutesConflict:
|
||||
return fmt.Errorf("error: %s", err.(*apiroutes.PostAppsAppRoutesConflict).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %s", e.Payload.Error.Message)
|
||||
case *apiroutes.PostAppsAppRoutesDefault:
|
||||
return fmt.Errorf("unexpected error: %s", err.(*apiroutes.PostAppsAppRoutesDefault).Payload.Error.Message)
|
||||
return fmt.Errorf("unexpected error: %s", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
fmt.Println(resp.Payload.Route.Path, "created with", resp.Payload.Route.Image)
|
||||
@@ -352,15 +362,16 @@ func (a *routesCmd) patchRoute(c *cli.Context, appName, routePath string, r *fnm
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiroutes.PatchAppsAppRoutesRouteBadRequest:
|
||||
return fmt.Errorf("error: %s", err.(*apiroutes.PatchAppsAppRoutesRouteBadRequest).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %s", e.Payload.Error.Message)
|
||||
case *apiroutes.PatchAppsAppRoutesRouteNotFound:
|
||||
return fmt.Errorf("error: %s", err.(*apiroutes.PatchAppsAppRoutesRouteNotFound).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %s", e.Payload.Error.Message)
|
||||
case *apiroutes.PatchAppsAppRoutesRouteDefault:
|
||||
return fmt.Errorf("unexpected error: %s", err.(*apiroutes.PatchAppsAppRoutesRouteDefault).Payload.Error.Message)
|
||||
return fmt.Errorf("unexpected error: %s", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -374,13 +385,14 @@ func (a *routesCmd) putRoute(c *cli.Context, appName, routePath string, r *fnmod
|
||||
Body: &fnmodels.RouteWrapper{Route: r},
|
||||
})
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiroutes.PutAppsAppRoutesRouteBadRequest:
|
||||
return fmt.Errorf("error: %s", err.(*apiroutes.PutAppsAppRoutesRouteBadRequest).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %s", e.Payload.Error.Message)
|
||||
case *apiroutes.PutAppsAppRoutesRouteDefault:
|
||||
return fmt.Errorf("unexpected error: %s", err.(*apiroutes.PutAppsAppRoutesRouteDefault).Payload.Error.Message)
|
||||
return fmt.Errorf("unexpected error: %s", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -392,7 +404,7 @@ func (a *routesCmd) update(c *cli.Context) error {
|
||||
rt := &fnmodels.Route{}
|
||||
|
||||
if !c.Bool("ignore-fn-file") {
|
||||
if err := routeWithFuncFile(c, nil, rt); err != nil {
|
||||
if err := routeWithFuncFile(nil, rt); err != nil {
|
||||
return fmt.Errorf("error updating route: %s", err)
|
||||
}
|
||||
}
|
||||
@@ -461,13 +473,14 @@ func (a *routesCmd) inspect(c *cli.Context) error {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiroutes.GetAppsAppRoutesRouteNotFound:
|
||||
return fmt.Errorf("error: %s", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %s", e.Payload.Error.Message)
|
||||
case *apiroutes.GetAppsAppRoutesRouteDefault:
|
||||
return fmt.Errorf("unexpected error: %s", err.(*apiroutes.GetAppsAppRoutesRouteDefault).Payload.Error.Message)
|
||||
return fmt.Errorf("unexpected error: %s", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
@@ -508,13 +521,14 @@ func (a *routesCmd) delete(c *cli.Context) error {
|
||||
Route: route,
|
||||
})
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
switch e := err.(type) {
|
||||
case *apiroutes.DeleteAppsAppRoutesRouteNotFound:
|
||||
return fmt.Errorf("error: %s", err.(*apiroutes.DeleteAppsAppRoutesRouteNotFound).Payload.Error.Message)
|
||||
return fmt.Errorf("error: %s", e.Payload.Error.Message)
|
||||
case *apiroutes.DeleteAppsAppRoutesRouteDefault:
|
||||
return fmt.Errorf("unexpected error: %s", err.(*apiroutes.DeleteAppsAppRoutesRouteDefault).Payload.Error.Message)
|
||||
return fmt.Errorf("unexpected error: %s", e.Payload.Error.Message)
|
||||
default:
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
fmt.Println(appName, route, "deleted")
|
||||
|
||||
@@ -176,7 +176,7 @@ func runff(ff *funcfile, stdin io.Reader, stdout, stderr io.Writer, method strin
|
||||
stdin = strings.NewReader(body)
|
||||
}
|
||||
|
||||
sh = append(sh, ff.FullName())
|
||||
sh = append(sh, ff.ImageName())
|
||||
cmd := exec.Command(sh[0], sh[1:]...)
|
||||
cmd.Stdin = stdin
|
||||
cmd.Stdout = stdout
|
||||
|
||||
@@ -95,7 +95,7 @@ func (t *testcmd) test(c *cli.Context) error {
|
||||
|
||||
fmt.Printf("Running %v tests...", len(tests))
|
||||
|
||||
target := ff.FullName()
|
||||
target := ff.ImageName()
|
||||
runtest := runlocaltest
|
||||
if t.remote != "" {
|
||||
if ff.Path == "" {
|
||||
@@ -116,7 +116,7 @@ func (t *testcmd) test(c *cli.Context) error {
|
||||
}
|
||||
|
||||
errorCount := 0
|
||||
fmt.Println("running tests on", ff.FullName(), ":")
|
||||
fmt.Println("running tests on", ff.ImageName(), ":")
|
||||
for i, tt := range tests {
|
||||
fmt.Printf("\nTest %v\n", i+1)
|
||||
start := time.Now()
|
||||
|
||||
Reference in New Issue
Block a user