Deploy will automatically create a route if it doesn't exist.

This commit is contained in:
Travis Reeder
2017-05-17 15:11:44 -07:00
parent ad9e692fda
commit fedf08964e
7 changed files with 75 additions and 53 deletions

View File

@@ -32,21 +32,13 @@ The first time after you fork or after dependencies get updated, run:
make dep make dep
``` ```
Then after every change, run: Then after every change, run
```sh ```sh
make build make run
``` ```
to build the `functions` binary. to build and run the `functions` binary. It will start Functions using an embedded `Bolt` database running on port `8080`.
### Run
```sh
./functions
```
will start IronFunctions using an embedded `Bolt` database running on port `8080`.
### Test ### Test

View File

@@ -20,8 +20,8 @@ test-build-arm:
GOARCH=arm GOARM=7 $(MAKE) build GOARCH=arm GOARM=7 $(MAKE) build
GOARCH=arm64 $(MAKE) build GOARCH=arm64 $(MAKE) build
run: run: build
./functions GIN_MODE=debug ./functions
docker-dep: docker-dep:
# todo: need to create a dep tool image for this (or just ditch this) # todo: need to create a dep tool image for this (or just ditch this)

View File

@@ -131,6 +131,7 @@ fn init $USERNAME/hello
# Test it - you can pass data into it too by piping it in, eg: `cat hello.payload.json | fn run` # Test it - you can pass data into it too by piping it in, eg: `cat hello.payload.json | fn run`
fn run fn run
# Once it's ready, deploy it to your functions server (default localhost:8080) # Once it's ready, deploy it to your functions server (default localhost:8080)
fn apps create myapp
fn deploy myapp fn deploy myapp
``` ```

View File

@@ -14,8 +14,8 @@ import (
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/boltdb/bolt" "github.com/boltdb/bolt"
"gitlab.oracledx.com/odx/functions/api/models"
"gitlab.oracledx.com/odx/functions/api/datastore/internal/datastoreutil" "gitlab.oracledx.com/odx/functions/api/datastore/internal/datastoreutil"
"gitlab.oracledx.com/odx/functions/api/models"
) )
type BoltDatastore struct { type BoltDatastore struct {

View File

@@ -46,6 +46,7 @@ func (s *Server) handleRouteUpdate(c *gin.Context) {
} }
if wroute.Route.Image != "" { if wroute.Route.Image != "" {
// This was checking that an image exists, but it's too slow of an operation. Checks at runtime now.
// err = s.Runner.EnsureImageExists(ctx, &task.Config{ // err = s.Runner.EnsureImageExists(ctx, &task.Config{
// Image: wroute.Route.Image, // Image: wroute.Route.Image,
// }) // })
@@ -57,6 +58,10 @@ func (s *Server) handleRouteUpdate(c *gin.Context) {
} }
route, err := s.Datastore.UpdateRoute(ctx, wroute.Route) route, err := s.Datastore.UpdateRoute(ctx, wroute.Route)
if err == models.ErrRoutesNotFound {
// try insert then
route, err = s.Datastore.InsertRoute(ctx, wroute.Route)
}
if err != nil { if err != nil {
handleErrorResponse(c, err) handleErrorResponse(c, err)
return return

View File

@@ -5,9 +5,11 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"path"
"path/filepath" "path/filepath"
"time" "time"
"github.com/Sirupsen/logrus"
functions "github.com/iron-io/functions_go" functions "github.com/iron-io/functions_go"
"github.com/iron-io/functions_go/models" "github.com/iron-io/functions_go/models"
"github.com/urfave/cli" "github.com/urfave/cli"
@@ -52,7 +54,7 @@ func (p *deploycmd) flags() []cli.Flag {
Usage: "working directory", Usage: "working directory",
Destination: &p.wd, Destination: &p.wd,
EnvVar: "WORK_DIR", EnvVar: "WORK_DIR",
Value: "./", // Value: "./",
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "i", Name: "i",
@@ -72,9 +74,14 @@ func (p *deploycmd) scan(c *cli.Context) error {
p.verbwriter = verbwriter(p.verbose) p.verbwriter = verbwriter(p.verbose)
var walked bool var walked bool
wd, err := os.Getwd()
if err != nil {
logrus.Fatalln("Couldn't get current directory:", err)
}
// logrus.Infoln("wd:", wd)
err := filepath.Walk(p.wd, func(path string, info os.FileInfo, err error) error { err = filepath.Walk(wd, func(path string, info os.FileInfo, err error) error {
if path != p.wd && info.IsDir() { if path != wd && info.IsDir() {
return filepath.SkipDir return filepath.SkipDir
} }
@@ -97,7 +104,7 @@ func (p *deploycmd) scan(c *cli.Context) error {
return e return e
}) })
if err != nil { if err != nil {
fmt.Fprintf(p.verbwriter, "file walk error: %s\n", err) fmt.Fprintf(p.verbwriter, "error: %s\n", err)
} }
if !walked { if !walked {
@@ -111,18 +118,23 @@ func (p *deploycmd) scan(c *cli.Context) error {
// Parse functions file, bump version, build image, push to registry, and // Parse functions file, bump version, build image, push to registry, and
// finally it will update function's route. Optionally, // finally it will update function's route. Optionally,
// the route can be overriden inside the functions file. // the route can be overriden inside the functions file.
func (p *deploycmd) deploy(c *cli.Context, path string) error { func (p *deploycmd) deploy(c *cli.Context, funcFilePath string) error {
fmt.Fprintln(p.verbwriter, "deploying", path) funcFileName := path.Base(funcFilePath)
err := c.App.Command("bump").Run(c) err := c.App.Command("bump").Run(c)
if err != nil { if err != nil {
return err return err
} }
funcfile, err := buildfunc(p.verbwriter, path) funcfile, err := buildfunc(p.verbwriter, funcFileName)
if err != nil { if err != nil {
return err return err
} }
if funcfile.Path == nil || *funcfile.Path == "" {
dirName := "/" + path.Base(path.Dir(funcFilePath))
funcfile.Path = &dirName
}
logrus.Infof("funcfile %+v", funcfile)
if p.skippush { if p.skippush {
return nil return nil
@@ -132,18 +144,18 @@ func (p *deploycmd) deploy(c *cli.Context, path string) error {
return err return err
} }
return p.route(c, path, funcfile) return p.route(c, funcfile)
} }
func (p *deploycmd) route(c *cli.Context, path string, ff *funcfile) error { func (p *deploycmd) route(c *cli.Context, ff *funcfile) error {
if err := resetBasePath(p.Configuration); err != nil { if err := resetBasePath(p.Configuration); err != nil {
return fmt.Errorf("error setting endpoint: %v", err) return fmt.Errorf("error setting endpoint: %v", err)
} }
routesCmd := routesCmd{client: apiClient()} routesCmd := routesCmd{client: apiClient()}
rt := &models.Route{} rt := &models.Route{}
routeWithFuncFile(c, rt) routeWithFuncFile(c, ff, rt)
return routesCmd.patchRoute(p.appName, *ff.Path, rt) return routesCmd.patchRoute(c, p.appName, *ff.Path, rt)
} }
func expandEnvConfig(configs map[string]string) map[string]string { func expandEnvConfig(configs map[string]string) map[string]string {

View File

@@ -287,26 +287,31 @@ func routeWithFlags(c *cli.Context, rt *models.Route) {
} }
} }
func routeWithFuncFile(c *cli.Context, rt *models.Route) { func routeWithFuncFile(c *cli.Context, ff *funcfile, rt *models.Route) error {
ff, err := loadFuncfile() var err error
if err == nil { if ff == nil {
if ff.FullName() != "" { // args take precedence ff, err = loadFuncfile()
rt.Image = ff.FullName() if err != nil {
} return err
if ff.Format != nil {
rt.Format = *ff.Format
}
if ff.MaxConcurrency != nil {
rt.MaxConcurrency = int32(*ff.MaxConcurrency)
}
if ff.Timeout != nil {
to := int64(ff.Timeout.Seconds())
rt.Timeout = &to
}
if rt.Path == "" && ff.Path != nil {
rt.Path = *ff.Path
} }
} }
if ff.FullName() != "" { // args take precedence
rt.Image = ff.FullName()
}
if ff.Format != nil {
rt.Format = *ff.Format
}
if ff.MaxConcurrency != nil {
rt.MaxConcurrency = int32(*ff.MaxConcurrency)
}
if ff.Timeout != nil {
to := int64(ff.Timeout.Seconds())
rt.Timeout = &to
}
if rt.Path == "" && ff.Path != nil {
rt.Path = *ff.Path
}
return nil
} }
func (a *routesCmd) create(c *cli.Context) error { func (a *routesCmd) create(c *cli.Context) error {
@@ -317,17 +322,21 @@ func (a *routesCmd) create(c *cli.Context) error {
rt.Path = route rt.Path = route
rt.Image = c.Args().Get(2) rt.Image = c.Args().Get(2)
routeWithFuncFile(c, rt) routeWithFuncFile(c, nil, rt)
routeWithFlags(c, rt) routeWithFlags(c, rt)
if rt.Path == "" { if rt.Path == "" {
return errors.New("error: route path is missing") return errors.New("route path is missing")
} }
if rt.Image == "" { if rt.Image == "" {
fmt.Println("No image specified, using `iron/hello`") return errors.New("no image specified")
rt.Image = "iron/hello"
} }
return a.postRoute(c, appName, rt)
}
func (a *routesCmd) postRoute(c *cli.Context, appName string, rt *fnmodels.Route) error {
body := &models.RouteWrapper{ body := &models.RouteWrapper{
Route: rt, Route: rt,
} }
@@ -354,7 +363,8 @@ func (a *routesCmd) create(c *cli.Context) error {
return nil return nil
} }
func (a *routesCmd) patchRoute(appName, routePath string, r *fnmodels.Route) error { func (a *routesCmd) patchRoute(c *cli.Context, appName, routePath string, r *fnmodels.Route) error {
// TODO: this getting the old version and merging should be on the server side, not here on the client.
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,
@@ -364,7 +374,9 @@ func (a *routesCmd) patchRoute(appName, routePath string, r *fnmodels.Route) err
if err != nil { if err != nil {
switch err.(type) { switch err.(type) {
case *apiroutes.GetAppsAppRoutesRouteNotFound: case *apiroutes.GetAppsAppRoutesRouteNotFound:
return fmt.Errorf("error: %s", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message) // return fmt.Errorf("error: %s", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message)
// then insert it
return a.postRoute(c, appName, r)
case *apiroutes.GetAppsAppRoutesDefault: case *apiroutes.GetAppsAppRoutesDefault:
return fmt.Errorf("unexpected error: %s", err.(*apiroutes.GetAppsAppRoutesDefault).Payload.Error.Message) return fmt.Errorf("unexpected error: %s", err.(*apiroutes.GetAppsAppRoutesDefault).Payload.Error.Message)
} }
@@ -446,10 +458,10 @@ func (a *routesCmd) update(c *cli.Context) error {
route := cleanRoutePath(c.Args().Get(1)) route := cleanRoutePath(c.Args().Get(1))
rt := &models.Route{} rt := &models.Route{}
routeWithFuncFile(c, rt) routeWithFuncFile(c, nil, rt)
routeWithFlags(c, rt) routeWithFlags(c, rt)
err := a.patchRoute(appName, route, rt) err := a.patchRoute(c, appName, route, rt)
if err != nil { if err != nil {
return err return err
} }
@@ -470,7 +482,7 @@ func (a *routesCmd) configSet(c *cli.Context) error {
patchRoute.Config[key] = value patchRoute.Config[key] = value
err := a.patchRoute(appName, route, &patchRoute) err := a.patchRoute(c, appName, route, &patchRoute)
if err != nil { if err != nil {
return err return err
} }
@@ -490,7 +502,7 @@ func (a *routesCmd) configUnset(c *cli.Context) error {
patchRoute.Config["-"+key] = "" patchRoute.Config["-"+key] = ""
err := a.patchRoute(appName, route, &patchRoute) err := a.patchRoute(c, appName, route, &patchRoute)
if err != nil { if err != nil {
return err return err
} }