diff --git a/Gopkg.lock b/Gopkg.lock index ee4eedf8a..96ed4bd07 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -32,10 +32,10 @@ revision = "bbf7a2afc14f93e1e0a5c06df524fbd75e5031e5" [[projects]] + branch = "master" name = "github.com/Sirupsen/logrus" packages = [".","hooks/syslog"] - revision = "ba1b36c82c5e05c4f912a88eab0dcd91a171688f" - version = "v0.11.5" + revision = "5e5dc898656f695e2a086b8e12559febbfc01562" [[projects]] branch = "master" @@ -51,9 +51,9 @@ [[projects]] name = "github.com/aws/aws-sdk-go" - packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","private/protocol","private/protocol/json/jsonutil","private/protocol/jsonrpc","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restjson","private/protocol/xml/xmlutil","service/lambda","service/sts"] - revision = "a479673916dcc0f62674f085bb4112272b8d8560" - version = "v1.8.31" + packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/json/jsonutil","private/protocol/jsonrpc","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restjson","private/protocol/xml/xmlutil","service/lambda","service/sts"] + revision = "f9a14dadf426ac17058f5ed3ec9bac9a61b5990b" + version = "v1.8.33" [[projects]] name = "github.com/boltdb/bolt" @@ -119,7 +119,7 @@ branch = "master" name = "github.com/docker/cli" packages = ["cli/config/configfile"] - revision = "6c59636498e96f8d826764f92e9f71599857229d" + revision = "30af87981d8d464c385b247f524fcbc503207940" [[projects]] name = "github.com/docker/distribution" @@ -176,10 +176,10 @@ version = "1.1.1" [[projects]] + branch = "master" name = "github.com/gin-gonic/gin" packages = [".","binding","render"] - revision = "e2212d40c62a98b388a5eb48ecbdcf88534688ba" - version = "v1.1.4" + revision = "d5b353c5d5a560322e6d96121c814115562501f7" [[projects]] name = "github.com/go-ini/ini" @@ -254,16 +254,16 @@ version = "v0.12" [[projects]] + branch = "master" name = "github.com/go-sql-driver/mysql" packages = ["."] - revision = "a0583e0143b1624142adab07e0e97fe106d99561" - version = "v1.3" + revision = "e3f0fdcf52770a162d5a4540ddb8d9957ff456d1" [[projects]] branch = "master" name = "github.com/golang/protobuf" packages = ["proto"] - revision = "9f174c986221c608fb5143bd623b6076a71feae3" + revision = "6e4cc92cc905d5f4a73041c1b8228ea08f4c6147" [[projects]] branch = "master" @@ -394,8 +394,8 @@ [[projects]] name = "github.com/pelletier/go-toml" packages = ["."] - revision = "13d49d4606eb801b8f01ae542b4afc4c6ee3d84a" - version = "v0.5.0" + revision = "5ccdfb18c776b740aecaf085c4d9a2779199c279" + version = "v1.0.0" [[projects]] branch = "master" @@ -404,16 +404,16 @@ revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" [[projects]] + branch = "master" name = "github.com/pkg/errors" packages = ["."] - revision = "645ef00459ed84a119197bfb8d8205042c6df63d" - version = "v0.8.0" + revision = "c605e284fe17294bda444b34710735b29d1a9d90" [[projects]] + branch = "master" name = "github.com/satori/go.uuid" packages = ["."] - revision = "879c5887cd475cd7864858769793b2ceb0d44feb" - version = "v1.1.0" + revision = "5bf94b69c6b68ee1b541973bb8e1144db23a194b" [[projects]] branch = "master" @@ -461,7 +461,7 @@ branch = "master" name = "golang.org/x/crypto" packages = ["bcrypt","blowfish"] - revision = "7e9105388ebff089b3f99f0ef676ea55a6da3a7e" + revision = "e1a4589e7d3ea14a3352255d04b6f1a418845e5e" [[projects]] branch = "master" @@ -502,6 +502,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "d512d36ab747f5eee6b2a62ee56cfde7a18fc185ffd5c99b104cf664819be05d" + inputs-digest = "961ede3bad03a1a3f5ac22d03ac3861a800943fbae4f66de32279d5f9fc85061" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 1a4ceea8d..0a6376fbd 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -71,8 +71,8 @@ name = "code.cloudfoundry.org/bytefmt" [[constraint]] + branch = "master" name = "github.com/Sirupsen/logrus" - version = "0.11.5" [[constraint]] branch = "master" @@ -80,7 +80,7 @@ [[constraint]] name = "github.com/aws/aws-sdk-go" - version = "1.8.31" + version = "1.8.32" [[constraint]] name = "github.com/boltdb/bolt" @@ -131,8 +131,8 @@ version = "1.1.1" [[constraint]] + branch = "master" name = "github.com/gin-gonic/gin" - version = "1.1.4" [[constraint]] branch = "master" @@ -163,8 +163,8 @@ name = "github.com/go-openapi/validate" [[constraint]] + branch = "master" name = "github.com/go-sql-driver/mysql" - version = "1.3.0" [[constraint]] branch = "master" @@ -195,12 +195,12 @@ version = "1.13.1" [[constraint]] + branch = "master" name = "github.com/pkg/errors" - version = "0.8.0" [[constraint]] + branch = "master" name = "github.com/satori/go.uuid" - version = "1.1.0" [[constraint]] branch = "master" diff --git a/examples/tutorial/hello/node/README.md b/examples/tutorial/hello/node/README.md index 83903eb00..4d8e5dfbe 100644 --- a/examples/tutorial/hello/node/README.md +++ b/examples/tutorial/hello/node/README.md @@ -33,7 +33,8 @@ And now with the JSON input: curl -H "Content-Type: application/json" -X POST -d @hello.payload.json http://localhost:8080/r/myapp/hello ``` -That's it! +That's it! Our `fn deploy` packaged our function and sent it to the Oracle Functions server. Try editing `func.js` +and then doing another `fn deploy`. ### Note on Dependencies diff --git a/examples/tutorial/hello/php/README.md b/examples/tutorial/hello/php/README.md index 7c15ea6d4..9cf800536 100644 --- a/examples/tutorial/hello/php/README.md +++ b/examples/tutorial/hello/php/README.md @@ -33,7 +33,8 @@ And now with the JSON input: curl -H "Content-Type: application/json" -X POST -d @hello.payload.json http://localhost:8080/r/myapp/hello ``` -That's it! +That's it! Our `fn deploy` packaged our function and sent it to the Oracle Functions server. Try editing `func.php` +and then doing another `fn deploy`. ### Note on Dependencies diff --git a/examples/tutorial/hello/python/Dockerfile b/examples/tutorial/hello/python/Dockerfile deleted file mode 100644 index 3a7f4cd67..000000000 --- a/examples/tutorial/hello/python/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM funcy/python:2 - -WORKDIR /app -ADD . /app - -ENTRYPOINT ["python", "hello.py"] diff --git a/examples/tutorial/hello/python/README.md b/examples/tutorial/hello/python/README.md index cdce4655d..370472b96 100644 --- a/examples/tutorial/hello/python/README.md +++ b/examples/tutorial/hello/python/README.md @@ -1,48 +1,67 @@ -## Quick Example for a Python Function (4 minutes) +# Tutorial 1: Python Function w/ Input (3 minutes) -This example will show you how to test and deploy Go (Golang) code to Oracle Functions. +This example will show you how to test and deploy Python code to Oracle Functions. It will also demonstrate passing data in through stdin. -### 1. Prepare the `func.yaml` file: - -At func.yaml you will find: - -```yml -name: USERNAME/hello -version: 0.0.1 -path: /hello -build: -- docker run --rm -v "$PWD":/worker -w /worker funcy/python:2-dev pip install -t packages -r requirements.txt -``` - -The important step here is to ensure you replace `USERNAME` with your Docker Hub account name. Some points of note: -the application name is `pythonapp` and the route for incoming requests is `/hello`. These informations are relevant for -the moment you try to test this function. - -### 2. Build: +### First, run the following commands: ```sh -# build the function -fn build -# test it +# Initialize your function creating a func.yaml file +fn init /hello + +# Test your function. +# This will run inside a container exactly how it will on the server. It will also install and vendor dependencies from Gemfile +fn run + +# Now try with an input cat hello.payload.json | fn run -# push it to Docker Hub -fn push -# Create a route to this function on Oracle Functions -fn routes create pythonapp /hello + +# Deploy your functions to the Oracle Functions server (default localhost:8080) +# This will create a route to your function as well +fn deploy myapp ``` - -`-v` is optional, but it allows you to see how this function is being built. - -### 3. Queue jobs for your function - -Now you can start jobs on your function. Let's quickly queue up a job to try it out. +### Now call your function: ```sh -cat hello.payload.json | fn call pythonapp /hello +curl http://localhost:8080/r/myapp/hello ``` -Here's a curl example to show how easy it is to do in any language: +Or call from a browser: [http://localhost:8080/r/myapp/hello](http://localhost:8080/r/myapp/hello) + +And now with the JSON input: ```sh -curl -H "Content-Type: application/json" -X POST -d @hello.payload.json http://localhost:8080/r/pythonapp/hello +curl -H "Content-Type: application/json" -X POST -d @hello.payload.json http://localhost:8080/r/myapp/hello ``` + +That's it! Our `fn deploy` packaged our function and sent it to the Oracle Functions server. Try editing `func.py` +and then doing another `fn deploy`. + +### Note on Dependencies + +In Python, we create a [requirements](https://pip.pypa.io/en/stable/user_guide/) file in your function directory then `fn deploy` will build and deploy with these dependencies. + +# In Review + +1. We piped JSON data into the function at the command line + ```sh + cat hello.payload.json | fn run + ``` + +2. We received our function input through **stdin** + ```python + obj = json.loads(sys.stdin.read()) + ``` + +3. We wrote our output to **stdout** + ```python + print "Hello", name, "!" + ``` + +4. We sent **stderr** to the server logs + ```python + sys.stderr.write("Starting Python Function\n") + ``` + + +# Next Up +## [Tutorial 2: Input Parameters](examples/tutorial/params) \ No newline at end of file diff --git a/examples/tutorial/hello/python/func.py b/examples/tutorial/hello/python/func.py new file mode 100644 index 000000000..8dd634ea9 --- /dev/null +++ b/examples/tutorial/hello/python/func.py @@ -0,0 +1,18 @@ +import sys +sys.path.append("packages") +import os +import json + +sys.stderr.write("Starting Python Function\n") + +name = "World" + +try: + if not os.isatty(sys.stdin.fileno()): + obj = json.loads(sys.stdin.read()) + if obj["name"] != "": + name = obj["name"] +except: + pass + +print "Hello", name, "!" diff --git a/examples/tutorial/hello/python/hello.py b/examples/tutorial/hello/python/hello.py deleted file mode 100644 index cab4ac99b..000000000 --- a/examples/tutorial/hello/python/hello.py +++ /dev/null @@ -1,12 +0,0 @@ -import sys -sys.path.append("packages") -import os -import json - -name = "World" -if not os.isatty(sys.stdin.fileno()): - obj = json.loads(sys.stdin.read()) - if obj["name"] != "": - name = obj["name"] - -print "Hello", name, "!!!" \ No newline at end of file diff --git a/examples/tutorial/hello/ruby/README.md b/examples/tutorial/hello/ruby/README.md index f348f9699..c3ae4dc09 100644 --- a/examples/tutorial/hello/ruby/README.md +++ b/examples/tutorial/hello/ruby/README.md @@ -33,7 +33,9 @@ And now with the JSON input: curl -H "Content-Type: application/json" -X POST -d @hello.payload.json http://localhost:8080/r/myapp/hello ``` -That's it! +That's it! Our `fn deploy` packaged our function and sent it to the Oracle Functions server. Try editing `func.rb` +and then doing another `fn deploy`. + ### Note on Dependencies diff --git a/examples/tutorial/hello/rust/.gitignore b/examples/tutorial/hello/rust/.gitignore new file mode 100644 index 000000000..aee0b953c --- /dev/null +++ b/examples/tutorial/hello/rust/.gitignore @@ -0,0 +1,2 @@ +func.yaml +Cargo.lock diff --git a/examples/tutorial/hello/rust/README.md b/examples/tutorial/hello/rust/README.md index 895f3ba51..25675af52 100644 --- a/examples/tutorial/hello/rust/README.md +++ b/examples/tutorial/hello/rust/README.md @@ -1,33 +1,93 @@ -# Using rust with functions +# Tutorial 1: Rust Function w/ Input (3 minutes) + +This example will show you how to test and deploy Rust code to Oracle Functions. It will also demonstrate passing data in through stdin. The easiest way to create a function in rust is via ***cargo*** and ***fn***. -## Prerequisites +### Prerequisites -First create an epty rust project as follows: +Create an empty rust project as follows: ```bash cargo init --name func --bin ``` -Make sure the project name is ***func*** and is of type ***bin***. Now just edit your code, once done you can create a function. +Make sure the project name is ***func*** and is of type ***bin***. -## Creating a function +Now put the following code in ```main.rs``` (can also copy directly from the file in this repo): -Simply run +```rust +use std::io; +use std::io::Read; -```bash -fn init --runtime=rust / +fn main() { + let mut buffer = String::new(); + let stdin = io::stdin(); + if stdin.lock().read_to_string(&mut buffer).is_ok() { + println!("Hello {}", buffer.trim()); + } +} ``` -This will create the ```func.yaml``` file required by functions, which can be built by running: -```bash -fn build -``` +### Now run the following commands: -## Testing +```sh +# Initialize your function creating a func.yaml file +fn init /rust -```bash +# Test your function. This will run inside a container exactly how it will on the server fn run + +# Now try with an input (copy sample.payload.json from this repo) +cat sample.payload.json | fn run + +# Deploy your functions to the Oracle Functions server (default localhost:8080) +# This will create a route to your function as well +fn deploy myapp ``` +### Now call your function: + +```sh +curl http://localhost:8080/r/myapp/rust +``` + +Or call from a browser: [http://localhost:8080/r/myapp/rust](http://localhost:8080/r/myapp/rust) + +And now with the JSON input: + +```sh +curl -H "Content-Type: application/json" -X POST -d @sample.payload.json http://localhost:8080/r/myapp/rust +``` + +That's it! + +### Note on Dependencies + + + +# In Review + +1. We piped JSON data into the function at the command line + ```sh + cat sample.payload.json | fn run + ``` + +2. We received our function input through **stdin** + ```rust + read_to_string(&mut buffer) + ``` + +3. We wrote our output to **stdout** + ```rust + println!("Hello {}", buffer.trim()); + ``` + +4. We sent **stderr** to the server logs + ```rust + TODO + ``` + + +# Next Up +## [Tutorial 2: Input Parameters](examples/tutorial/params) diff --git a/examples/tutorial/hello/rust/sample.payload.json b/examples/tutorial/hello/rust/sample.payload.json new file mode 100644 index 000000000..7ac7d4cb4 --- /dev/null +++ b/examples/tutorial/hello/rust/sample.payload.json @@ -0,0 +1,3 @@ +{ + "name": "Johnny" +} diff --git a/examples/tutorial/hello/rust/src/main.rs b/examples/tutorial/hello/rust/src/main.rs index 020c757b1..f987fab66 100644 --- a/examples/tutorial/hello/rust/src/main.rs +++ b/examples/tutorial/hello/rust/src/main.rs @@ -7,4 +7,5 @@ fn main() { if stdin.lock().read_to_string(&mut buffer).is_ok() { println!("Hello {}", buffer.trim()); } + //todo: decode json from payload } diff --git a/fn/init.go b/fn/init.go index a0736ae8e..28d65db63 100644 --- a/fn/init.go +++ b/fn/init.go @@ -23,14 +23,14 @@ import ( var ( fileExtToRuntime = map[string]string{ - ".go": "go", - ".js": "node", - ".rb": "ruby", - ".py": "python", - ".php": "php", - ".rs": "rust", - ".cs": "dotnet", - ".fs": "dotnet", + ".go": "go", + ".js": "node", + ".rb": "ruby", + ".py": "python", + ".php": "php", + ".rs": "rust", + ".cs": "dotnet", + ".fs": "dotnet", ".java": "java", } @@ -214,9 +214,10 @@ func (a *initFnCmd) buildFuncFile(c *cli.Context) error { func detectRuntime(path string) (runtime string, err error) { for ext, runtime := range fileExtToRuntime { - filenames := []string { + filenames := []string{ filepath.Join(path, fmt.Sprintf("func%s", ext)), filepath.Join(path, fmt.Sprintf("Func%s", ext)), + filepath.Join(path, fmt.Sprintf("src/main%s", ext)), // rust } for _, filename := range filenames { if exists(filename) { diff --git a/fn/langs/base.go b/fn/langs/base.go index 1449dce81..42c5ee6cf 100644 --- a/fn/langs/base.go +++ b/fn/langs/base.go @@ -2,8 +2,8 @@ package langs import ( "errors" - "os" "fmt" + "os" ) var ( @@ -20,7 +20,7 @@ func GetLangHelper(lang string) LangHelper { case "ruby": return &RubyLangHelper{} case "python": - return &PythonHelper{} + return &PythonLangHelper{} case "php": return &PhpLangHelper{} case "rust": @@ -54,8 +54,8 @@ type LangHelper interface { type BaseHelper struct { } -func (h *BaseHelper) Cmd() string { return "" } -func (h *BaseHelper) HasBoilerplate() bool { return false } +func (h *BaseHelper) Cmd() string { return "" } +func (h *BaseHelper) HasBoilerplate() bool { return false } func (h *BaseHelper) GenerateBoilerplate() error { return nil } func exists(name string) bool { @@ -69,4 +69,4 @@ func exists(name string) bool { func dockerBuildError(err error) error { return fmt.Errorf("error running docker build: %v", err) -} \ No newline at end of file +} diff --git a/fn/langs/python.go b/fn/langs/python.go index f8370eb26..c5e4887ea 100644 --- a/fn/langs/python.go +++ b/fn/langs/python.go @@ -7,20 +7,20 @@ import ( "strings" ) -type PythonHelper struct { +type PythonLangHelper struct { BaseHelper } -func (lh *PythonHelper) Entrypoint() string { +func (lh *PythonLangHelper) Entrypoint() string { return "python2 func.py" } -func (lh *PythonHelper) HasPreBuild() bool { +func (lh *PythonLangHelper) HasPreBuild() bool { return true } // PreBuild for Go builds the binary so the final image can be as small as possible -func (lh *PythonHelper) PreBuild() error { +func (lh *PythonLangHelper) PreBuild() error { wd, err := os.Getwd() if err != nil { return err @@ -40,6 +40,6 @@ func (lh *PythonHelper) PreBuild() error { return nil } -func (lh *PythonHelper) AfterBuild() error { +func (lh *PythonLangHelper) AfterBuild() error { return nil }