Simplified cli commands to make things easier to use.

This commit is contained in:
Travis Reeder
2017-05-15 16:51:59 -07:00
parent 7cfd7d413f
commit 014858143b
5 changed files with 40 additions and 82 deletions

View File

@@ -74,10 +74,10 @@ This guide will get you up and running in a few minutes.
### Run IronFunctions ### Run IronFunctions
To get started quickly with IronFunctions, just fire up an `iron/functions` container: To get started quickly with IronFunctions, just fire up an `treeder/functions` container:
```sh ```sh
docker run --rm -it --name functions -v ${PWD}/data:/app/data -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 iron/functions docker run --rm -it --name functions -v ${PWD}/data:/app/data -v /var/run/docker.sock:/var/run/docker.sock -p 8080:8080 treeder/functions
``` ```
*where ${PWD}/data is the directory where the functions application data files will be stored* *where ${PWD}/data is the directory where the functions application data files will be stored*
@@ -90,7 +90,7 @@ configuration options [here](docs/operating/options.md). If you are on Windows,
Install the IronFunctions CLI tool: Install the IronFunctions CLI tool:
```sh ```sh
curl -LSs https://goo.gl/VZrL8t | sh curl -LSs https://goo.gl/KKDFGn | sh
``` ```
This will download a shell script and execute it. If the script asks for a password, that is because it invokes sudo. This will download a shell script and execute it. If the script asks for a password, that is because it invokes sudo.
@@ -126,18 +126,12 @@ Copy and paste the code above into a file called `func.go`, then run the followi
and deploy it. and deploy it.
```sh ```sh
# create func.yaml file, replace $USERNAME with your Docker Hub username. # Initilize your function, replace $USERNAME with your Docker Hub username.
fn init $USERNAME/hello fn init $USERNAME/hello
# build the function # Test it - you can pass data into it too by piping it in, eg: `cat hello.payload.json | fn run`
fn build
# 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, build and push it to Docker Hub # Once it's ready, deploy it to your functions server (default localhost:8080)
fn build && fn push fn deploy myapp
# create an app - you only do this once per app
fn apps create myapp
# create a route that maps /hello to your new function
fn routes create myapp /hello
``` ```
Now you can call your function: Now you can call your function:
@@ -151,10 +145,8 @@ Or surf to it: http://localhost:8080/r/myapp/hello
To update your function: To update your function:
```sh ```sh
# update a function with a new version and push it # Just update your code and run:
fn bump && fn build && fn push fn deploy myapp
# then update the route
fn routes update myapp /hello
``` ```
See below for more details. And you can find a bunch of examples in various languages in the [examples](examples/) directory. You can also See below for more details. And you can find a bunch of examples in various languages in the [examples](examples/) directory. You can also

3
fn/CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,3 @@
Run `make install` to build and install to local machine for easy testing.

View File

@@ -5,7 +5,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@@ -16,10 +15,11 @@ import (
) )
func verbwriter(verbose bool) io.Writer { func verbwriter(verbose bool) io.Writer {
verbwriter := ioutil.Discard // this is too limiting, removes all logs which isn't what we want
if verbose { // verbwriter := ioutil.Discard
verbwriter = os.Stderr // if verbose {
} verbwriter := os.Stderr
// }
return verbwriter return verbwriter
} }

View File

@@ -4,12 +4,12 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"time" "time"
functions "github.com/iron-io/functions_go" functions "github.com/iron-io/functions_go"
"github.com/iron-io/functions_go/models"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@@ -22,7 +22,7 @@ func deploy() cli.Command {
return cli.Command{ return cli.Command{
Name: "deploy", Name: "deploy",
ArgsUsage: "<appName>", ArgsUsage: "<appName>",
Usage: "scan local directory for functions, build and push all of them to `APPNAME`.", Usage: "deploys a function to the functions server. (bumps, build, pushes and updates route)",
Flags: flags, Flags: flags,
Action: cmd.scan, Action: cmd.scan,
} }
@@ -86,7 +86,7 @@ func (p *deploycmd) scan(c *cli.Context) error {
return nil return nil
} }
e := p.deploy(path) e := p.deploy(c, path)
if err != nil { if err != nil {
fmt.Fprintln(p.verbwriter, path, e) fmt.Fprintln(p.verbwriter, path, e)
} }
@@ -107,13 +107,18 @@ func (p *deploycmd) scan(c *cli.Context) error {
return nil return nil
} }
// deploy will take the found function and check for the presence of a // deploy will perform several actions to deploy to an functions server.
// Dockerfile, and run a three step process: parse functions file, build and // Parse functions file, bump version, build image, push to registry, and
// push the container, 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(path string) error { func (p *deploycmd) deploy(c *cli.Context, path string) error {
fmt.Fprintln(p.verbwriter, "deploying", path) fmt.Fprintln(p.verbwriter, "deploying", path)
err := c.App.Command("bump").Run(c)
if err != nil {
return err
}
funcfile, err := buildfunc(p.verbwriter, path) funcfile, err := buildfunc(p.verbwriter, path)
if err != nil { if err != nil {
return err return err
@@ -127,65 +132,18 @@ func (p *deploycmd) deploy(path string) error {
return err return err
} }
return p.route(path, funcfile) return p.route(c, path, funcfile)
} }
func (p *deploycmd) route(path string, ff *funcfile) error { func (p *deploycmd) route(c *cli.Context, path string, 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)
} }
if ff.Path == nil { routesCmd := routesCmd{client: apiClient()}
_, path := appNamePath(ff.FullName()) rt := &models.Route{}
ff.Path = &path routeWithFuncFile(c, rt)
} return routesCmd.patchRoute(p.appName, *ff.Path, rt)
if ff.Memory == nil {
ff.Memory = new(int64)
}
if ff.Type == nil {
ff.Type = new(string)
}
if ff.Format == nil {
ff.Format = new(string)
}
if ff.MaxConcurrency == nil {
ff.MaxConcurrency = new(int)
}
if ff.Timeout == nil {
dur := time.Duration(0)
ff.Timeout = &dur
}
headers := make(map[string][]string)
for k, v := range ff.Headers {
headers[k] = []string{v}
}
body := functions.RouteWrapper{
Route: functions.Route{
Path: *ff.Path,
Image: ff.FullName(),
Memory: *ff.Memory,
Type_: *ff.Type,
Config: expandEnvConfig(ff.Config),
Headers: headers,
Format: *ff.Format,
MaxConcurrency: int32(*ff.MaxConcurrency),
Timeout: int32(ff.Timeout.Seconds()),
},
}
fmt.Fprintf(p.verbwriter, "updating API with app: %s route: %s name: %s \n", p.appName, *ff.Path, ff.Name)
wrapper, resp, err := p.AppsAppRoutesPost(p.appName, body)
if err != nil {
return fmt.Errorf("error getting routes: %v", err)
}
if resp.StatusCode == http.StatusBadRequest {
return fmt.Errorf("error storing this route: %s", wrapper.Error_.Message)
}
return nil
} }
func expandEnvConfig(configs map[string]string) map[string]string { func expandEnvConfig(configs map[string]string) map[string]string {

View File

@@ -43,6 +43,11 @@ func runflags() []cli.Flag {
} }
func (r *runCmd) run(c *cli.Context) error { func (r *runCmd) run(c *cli.Context) error {
// First, build it
err := c.App.Command("build").Run(c)
if err != nil {
return err
}
image := c.Args().First() image := c.Args().First()
if image == "" { if image == "" {
ff, err := loadFuncfile() ff, err := loadFuncfile()