mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Merge branch 'chad-ux-improvements' into 'master'
Chad ux improvements See merge request !20
This commit is contained in:
2
Gopkg.lock
generated
2
Gopkg.lock
generated
@@ -509,4 +509,4 @@ memo = "f5b1c7d56bf54bc74276d2d9f46275abedb0dce21386c1418a79e1b0ea972c25"
|
||||
branch = "v2"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
revision = "cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b"
|
||||
revision = "cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b"
|
||||
136
README.md
136
README.md
@@ -1,14 +1,9 @@
|
||||
# NONAME... :(
|
||||
# Oracle Functions
|
||||
|
||||
[](https://circleci.com/gh/treeder/functions)
|
||||
[](https://godoc.org/github.com/treeder/functions)
|
||||
<!-- [](https://godoc.org/github.com/treeder/functions) -->
|
||||
|
||||
Welcome to Oracle Functions! The open source serverless platform.
|
||||
|
||||
## What is Oracle Functions?
|
||||
|
||||
Oracle Functions is an open source [serverless](serverless.md) platform, or as we like to refer to it, Functions as a
|
||||
Service (FaaS) platform that you can run anywhere.
|
||||
Oracle Functions is an event-driven, open source, [functions-as-a-service](serverless.md) compute
|
||||
platform that you can run anywhere. Some of it's key features:
|
||||
|
||||
* Write once
|
||||
* [Any language](docs/faq.md#which-languages-are-supported)
|
||||
@@ -19,31 +14,32 @@ Service (FaaS) platform that you can run anywhere.
|
||||
* Easy to use [for developers](docs/README.md#for-developers)
|
||||
* Easy to manage [for operators](docs/README.md#for-operators)
|
||||
* Written in [Go](https://golang.org)
|
||||
* Simple yet powerful extensibility
|
||||
|
||||
## Join Our Community
|
||||
|
||||
TODO: Slack or Discord community.
|
||||
|
||||
## Quickstart
|
||||
|
||||
This guide will get you up and running in a few minutes.
|
||||
|
||||
### Prequisites
|
||||
## Prequisites
|
||||
|
||||
* Docker 17.05 or later installed and running
|
||||
* Logged into Docker Hub (`docker login`)
|
||||
|
||||
# UNTIL THIS IS PUBLIC, YOU'LL NEED TO BUILD AND RUN THE CODE FROM THIS REPO
|
||||
## Usage
|
||||
|
||||
### Installation
|
||||
|
||||
NOTE: The following instructions apply while the project is a private repo. This will
|
||||
build the Functions server and the CLI tool directly from the repo instead of
|
||||
using pre-built containers. Once the project is public, these steps will be unnecessary.
|
||||
|
||||
```sh
|
||||
# install cli tool
|
||||
# Build and Install CLI tool
|
||||
cd fn
|
||||
make dep # just once
|
||||
make install
|
||||
# Start server:
|
||||
|
||||
# Build and Run Functions Server
|
||||
cd ..
|
||||
make dep # just once
|
||||
make run
|
||||
make run # will build as well
|
||||
```
|
||||
|
||||
<!-- ADD BACK ONCE PUBLIC
|
||||
@@ -71,43 +67,37 @@ configuration options [here](docs/operating/options.md). If you are on Windows,
|
||||
|
||||
-->
|
||||
|
||||
### Write a Function
|
||||
### Your First Function
|
||||
|
||||
Functions are small, bite sized bits of code that do one simple thing. Forget about monoliths when using functions,
|
||||
just focus on the task that you want the function to perform.
|
||||
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 Go function that just returns "Hello ${NAME}!":
|
||||
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.)
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func main() {
|
||||
p := &Person{Name: "World"}
|
||||
json.NewDecoder(os.Stdin).Decode(p)
|
||||
fmt.Printf("Hello %v!", p.Name)
|
||||
fmt.Println("Hello from Oracle Functions!")
|
||||
}
|
||||
```
|
||||
|
||||
Copy and paste the code above into a file called `func.go`, then run the following commands to build your function
|
||||
and deploy it.
|
||||
Now run the following CLI commands:
|
||||
|
||||
```sh
|
||||
# Initilize your function, replace $USERNAME with your Docker Hub username.
|
||||
fn init $USERNAME/hello
|
||||
# Test it - you can pass data into it too by piping it in, eg: `cat hello.payload.json | fn run`
|
||||
# Initialize your function
|
||||
# This detects your runtime from the code above and creates a func.yaml
|
||||
fn init <DOCKERHUB_USERNAME>/hello
|
||||
|
||||
# Test your function
|
||||
# This will run inside a container exactly how it will on the server
|
||||
fn run
|
||||
# Once it's ready, deploy it to your functions server (default localhost:8080)
|
||||
fn apps create myapp
|
||||
|
||||
# Deploy your functions to the Oracle Functions server (default localhost:8080)
|
||||
# This will create a route to your function as well
|
||||
fn deploy myapp
|
||||
```
|
||||
|
||||
@@ -117,59 +107,39 @@ Now you can call your function:
|
||||
curl http://localhost:8080/r/myapp/hello
|
||||
```
|
||||
|
||||
Or surf to it: http://localhost:8080/r/myapp/hello
|
||||
Or in a browser: [http://localhost:8080/r/myapp/hello](http://localhost:8080/r/myapp/hello)
|
||||
|
||||
To update your function:
|
||||
That's it! You just deployed your first function and called it. Now to update your function
|
||||
you can update your code and run `fn deploy myapp` again.
|
||||
|
||||
```sh
|
||||
# Just update your code and run:
|
||||
fn deploy myapp
|
||||
```
|
||||
## To Learn More
|
||||
|
||||
See the [documentation](docs/README.md) for more information. And you can find a bunch of examples in various languages in the [examples](examples/) directory. You can also
|
||||
write your functions in AWS's [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)
|
||||
|
||||
## Functions UI
|
||||
## Get Involved
|
||||
|
||||
- TODO: Slack or Discord community
|
||||
- Learn how to [contribute](CONTRIBUTING.md)
|
||||
- See [milestones](https://gitlab.oracledx.com/odx/functions/milestones) for detailed issues
|
||||
|
||||
|
||||
## User Interface
|
||||
|
||||
This is the graphical user interface for Oracle Functions. It is currently not buildable.
|
||||
|
||||
```sh
|
||||
docker run --rm -it --link functions:api -p 4000:4000 -e "API_URL=http://api:8080" treeder/functions-ui
|
||||
```
|
||||
|
||||
For more information, see: https://github.com/treeder/functions-ui
|
||||
For more information, see: [https://github.com/treeder/functions-ui](https://github.com/treeder/functions-ui)
|
||||
|
||||
## Writing Functions
|
||||
|
||||
See [Writing Functions](docs/writing.md).
|
||||
# Next up
|
||||
|
||||
And you can find a bunch of examples in the [/examples](/examples) directory.
|
||||
### Check out the [Tutorial Series](examples/tutorial/).
|
||||
|
||||
## More Documentation
|
||||
It will demonstrate some of Oracle Functions capabilities through a series of exmaples. We'll try to show examples in most major languages. This is a great place to start!
|
||||
|
||||
See [docs/](docs/README.md) for full documentation.
|
||||
|
||||
## Roadmap
|
||||
|
||||
These are the high level roadmap goals. See [milestones](https://github.com/treeder/functions/milestones) for detailed issues.
|
||||
|
||||
* ~~Alpha 1 - November 2016~~
|
||||
* Initial release of base framework
|
||||
* Lambda support
|
||||
* ~~Alpha 2 - December 2016~~
|
||||
* Streaming input for hot functions #214
|
||||
* Logging endpoint(s) for per function debugging #263
|
||||
* Beta 1 - January 2017
|
||||
* Smart Load Balancer #151
|
||||
* Beta 2 - February 2017
|
||||
* Cron like scheduler #100
|
||||
* GA - March 2017
|
||||
|
||||
## Support
|
||||
|
||||
You can get community support via:
|
||||
|
||||
* [Stack Overflow](http://stackoverflow.com/questions/tagged/functions)
|
||||
* [Slack](http://get.iron.io/open-slack)
|
||||
|
||||
## Want to contribute to Oracle Functions?
|
||||
|
||||
See [contributing](CONTRIBUTING.md).
|
||||
|
||||
@@ -211,6 +211,20 @@ func (s *Server) startGears(ctx context.Context) {
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatalln("Failed to serve functions API.")
|
||||
}
|
||||
|
||||
const runHeader = `
|
||||
____ __
|
||||
/ __ \_________ ______/ /__
|
||||
/ / / / ___/ __ / ___/ / _ \
|
||||
/ /_/ / / / /_/ / /__/ / __/
|
||||
\_________ \__,_/\___/_/\____
|
||||
/ ____/_ __ ___ _____/ /_( )___ ____ _____
|
||||
/ /_ / / / / __ \/ ___/ __/ / __ \/ __ \/ ___/
|
||||
/ __/ / /_/ / / / / /__/ /_/ / /_/ / / / (__ )
|
||||
/_/ \____/_/ /_/\___/\__/_/\____/_/ /_/____/
|
||||
`
|
||||
|
||||
logrus.Infof(runHeader)
|
||||
logrus.Infof("Serving Functions API on address `%s`", listen)
|
||||
|
||||
svr := &supervisor.Supervisor{
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
# Example Functions
|
||||
|
||||
This directory has a collection of example functions you can look at to learn more about how to write them
|
||||
or just copy one and build on it to get started faster.
|
||||
This directory has a collection of example functions you can look at to learn more about how to write them or just copy one and build on it to get started faster.
|
||||
|
||||
## Hello World Examples
|
||||
## Tutorial Series
|
||||
|
||||
The [Hello World examples](hello/) are the most basic functions you can write and we'll try to have an example in most major languages.
|
||||
This is a good place to start and good examples to copy and build upon.
|
||||
The [Tutorial Series](tutorial/) will demonstrate some of Oracle Functions capabilities through a series of exmaples. We'll try to show examples in most major languages. This is a great place to start!
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# Quick Example for a Go Function (3 minutes)
|
||||
|
||||
This example will show you how to test and deploy Go (Golang) code to Oracle Functions.
|
||||
|
||||
```sh
|
||||
# create your func.yaml file
|
||||
fn init <YOUR_DOCKERHUB_USERNAME>/hello
|
||||
# build the function
|
||||
fn build
|
||||
# test it
|
||||
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 myapp /hello
|
||||
```
|
||||
|
||||
Now you can call your function on Oracle Functions:
|
||||
|
||||
```sh
|
||||
curl -H "Content-Type: application/json" -X POST -d @hello.payload.json http://localhost:8080/r/myapp/hello
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
Be sure you're dependencies are in the `vendor/` directory and that's it.
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
## Quick Example for a NodeJS Function (4 minutes)
|
||||
|
||||
This example will show you how to test and deploy a Node function to Oracle Functions.
|
||||
|
||||
```sh
|
||||
# create your func.yaml file
|
||||
fn init <YOUR_DOCKERHUB_USERNAME>/hello
|
||||
# build the function
|
||||
fn build
|
||||
# test it
|
||||
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 myapp /hello
|
||||
```
|
||||
|
||||
Now surf to: http://localhost:8080/r/myapp/hello
|
||||
|
||||
## Dependencies
|
||||
|
||||
Create a [package.json](https://docs.npmjs.com/getting-started/using-a-package.json) file in your functions directory.
|
||||
|
||||
Run:
|
||||
|
||||
```sh
|
||||
docker run --rm -v "$PWD":/function -w /function funcy/node:dev npm install
|
||||
```
|
||||
|
||||
Then everything should work.
|
||||
|
||||
For example, using the `package.json` file in this directory which includes the [request](https://www.npmjs.com/package/request) package, you can add this to func.js and it will work:
|
||||
|
||||
```js
|
||||
var request = require('request');
|
||||
request('http://www.google.com', function (error, response, body) {
|
||||
if (!error && response.statusCode == 200) {
|
||||
console.log(body) // Show the HTML for the Google homepage.
|
||||
}
|
||||
})
|
||||
```
|
||||
1
examples/hello/php/.gitignore
vendored
1
examples/hello/php/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
vendor/
|
||||
@@ -1,6 +0,0 @@
|
||||
FROM funcy/php
|
||||
|
||||
WORKDIR /app
|
||||
ADD . /app
|
||||
|
||||
ENTRYPOINT ["php", "hello.php"]
|
||||
@@ -1,48 +0,0 @@
|
||||
## Quick Example for a PHP Function (4 minutes)
|
||||
|
||||
This example will show you how to test and deploy Go (Golang) code to Oracle Functions.
|
||||
|
||||
### 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/php:dev composer install
|
||||
```
|
||||
|
||||
The important step here is to ensure you replace `USERNAME` with your Docker Hub account name. Some points of note:
|
||||
the application name is `phpapp` and the route for incoming requests is `/hello`. These informations are relevant for
|
||||
the moment you try to test this function.
|
||||
|
||||
### 2. Build:
|
||||
|
||||
```sh
|
||||
# build the function
|
||||
fn build
|
||||
# test it
|
||||
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 phpapp /hello
|
||||
```
|
||||
|
||||
`-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.
|
||||
|
||||
```sh
|
||||
cat hello.payload.json | fn call phpapp /hello
|
||||
```
|
||||
|
||||
Here's a curl example to show how easy it is to do in any language:
|
||||
|
||||
```sh
|
||||
curl -H "Content-Type: application/json" -X POST -d @hello.payload.json http://localhost:8080/r/phpapp/hello
|
||||
```
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"require": {
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
name: USERNAME/hello
|
||||
version: 0.0.1
|
||||
path: /hello
|
||||
build:
|
||||
- docker run --rm -v "$PWD":/worker -w /worker funcy/php:dev composer install
|
||||
@@ -1,44 +0,0 @@
|
||||
## Quick Example for a Ruby Function (4 minutes)
|
||||
|
||||
This example will show you how to test and deploy a Ruby function to Oracle Functions.
|
||||
|
||||
```sh
|
||||
# create your func.yaml file
|
||||
fn init <YOUR_DOCKERHUB_USERNAME>/hello
|
||||
# install dependencies, we need the json gem to run this
|
||||
docker run --rm -it -v ${pwd}:/worker -w /worker funcy/ruby:dev bundle install --standalone --clean
|
||||
# build the function
|
||||
fn build
|
||||
# test it
|
||||
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 myapp /hello
|
||||
```
|
||||
|
||||
Now surf to: http://localhost:8080/r/myapp/hello
|
||||
|
||||
## Dependencies
|
||||
|
||||
Create a [Gemfile](http://bundler.io/gemfile.html) file in your function directory, then run:
|
||||
|
||||
```sh
|
||||
docker run --rm -it -v ${pwd}:/worker -w /worker funcy/ruby:dev bundle install --standalone --clean
|
||||
```
|
||||
|
||||
Ruby doesn't pick up the gems automatically, so you'll have to add this to the top of your `func.rb` file:
|
||||
|
||||
```ruby
|
||||
require_relative 'bundle/bundler/setup'
|
||||
```
|
||||
|
||||
Open `func.rb` to see it in action.
|
||||
|
||||
To update dependencies:
|
||||
|
||||
```sh
|
||||
docker run --rm -it -v ${pwd}:/worker -w /worker funcy/ruby:dev bundle update
|
||||
# then install again to vendor them
|
||||
docker run --rm -it -v ${pwd}:/worker -w /worker funcy/ruby:dev bundle update
|
||||
```
|
||||
15
examples/tutorial/README.md
Normal file
15
examples/tutorial/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
# Tutorial Series
|
||||
|
||||
Welcome to the Oracle Functions Tutorial Series, the best way to get started with Oracle Functions and serverless computing. In the following
|
||||
tutorials, we'll gradually introduce many of the key features of Oracle Functions.
|
||||
|
||||
|
||||
**[Tutorial 1](examples/tutorial/hello)**
|
||||
: Learn the basics about sending data into your function
|
||||
|
||||
**[Tutorial 2](examples/tutorial/params)**: Learn how to get parameters from a web request
|
||||
|
||||
**[Tutorial 3](examples/tutorial/hotfunctions)**: Write your first HotFunction (stays alive to minimize latency between requests)
|
||||
|
||||
**[Tutorial 4]()**: TBD
|
||||
65
examples/tutorial/hello/go/README.md
Normal file
65
examples/tutorial/hello/go/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Tutorial 1: Go Function w/ Input (3 minutes)
|
||||
|
||||
This example will show you how to test and deploy Go (Golang) code to Oracle Functions. It will also demonstrate passing data in through stdin.
|
||||
|
||||
### First, run the following commands:
|
||||
|
||||
```sh
|
||||
# Initialize your function creating a func.yaml file
|
||||
fn init <DOCKERHUB_USERNAME>/hello
|
||||
|
||||
# Test your function. This will run inside a container exactly how it will on the server
|
||||
fn run
|
||||
|
||||
# Now try with an input
|
||||
cat hello.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/hello
|
||||
```
|
||||
|
||||
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/myapp/hello
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
### Note on Dependencies
|
||||
|
||||
In Go, simply put them all in the `vendor/` directory.
|
||||
|
||||
# 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**
|
||||
```go
|
||||
json.NewDecoder(os.Stdin).Decode(p)
|
||||
```
|
||||
|
||||
3. We wrote our output to **stdout**
|
||||
```go
|
||||
fmt.Printf("Hello")
|
||||
```
|
||||
|
||||
4. We sent **stderr** to the server logs
|
||||
```go
|
||||
log.Println("here")
|
||||
```
|
||||
|
||||
|
||||
# Next Up
|
||||
## [Tutorial 2: Input Parameters](examples/tutorial/params)
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
@@ -13,5 +14,7 @@ type Person struct {
|
||||
func main() {
|
||||
p := &Person{Name: "World"}
|
||||
json.NewDecoder(os.Stdin).Decode(p)
|
||||
fmt.Printf("Hello %v!", p.Name)
|
||||
fmt.Printf("Hello %v!\n", p.Name)
|
||||
|
||||
log.Println("---> stderr goes to the server logs.")
|
||||
}
|
||||
89
examples/tutorial/hello/node/README.md
Normal file
89
examples/tutorial/hello/node/README.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Tutorial 1: NodeJS Function w/ Input (3 minutes)
|
||||
|
||||
This example will show you how to test and deploy Node code to Oracle Functions. It will also demonstrate passing data in through stdin.
|
||||
|
||||
### First, run the following commands:
|
||||
|
||||
```sh
|
||||
# Initialize your function creating a func.yaml file
|
||||
fn init <DOCKERHUB_USERNAME>/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
|
||||
|
||||
# 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/hello
|
||||
```
|
||||
|
||||
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/myapp/hello
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
### Note on Dependencies
|
||||
|
||||
Create a [package.json](https://docs.npmjs.com/getting-started/using-a-package.json) file in your functions directory.
|
||||
|
||||
Run:
|
||||
|
||||
```sh
|
||||
docker run --rm -v "$PWD":/function -w /function funcy/node:dev npm install
|
||||
```
|
||||
|
||||
Then everything should work.
|
||||
|
||||
For example, using the `package.json` file in this directory which includes the [request](https://www.npmjs.com/package/request) package, you can add this to func.js and it will work:
|
||||
|
||||
```js
|
||||
var request = require('request');
|
||||
request('http://www.google.com', function (error, response, body) {
|
||||
if (!error && response.statusCode == 200) {
|
||||
console.log(body) // Show the HTML for the Google homepage.
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
# 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**
|
||||
```node
|
||||
obj = JSON.parse(fs.readFileSync('/dev/stdin').toString())
|
||||
```
|
||||
|
||||
3. We wrote our output to **stdout**
|
||||
```node
|
||||
console.log
|
||||
```
|
||||
|
||||
4. We sent **stderr** to the server logs
|
||||
```node
|
||||
console.error
|
||||
```
|
||||
|
||||
|
||||
# Next Up
|
||||
## [Tutorial 2: Input Parameters](examples/tutorial/params)
|
||||
|
||||
|
||||
|
||||
@@ -7,3 +7,5 @@ try {
|
||||
}
|
||||
} catch(e) {}
|
||||
console.log("Hello", name, "from Node!");
|
||||
|
||||
console.error("Stderr goes to the server logs...");
|
||||
3
examples/tutorial/hello/php/.gitignore
vendored
Normal file
3
examples/tutorial/hello/php/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
vendor/
|
||||
func.yaml
|
||||
composer.lock
|
||||
94
examples/tutorial/hello/php/README.md
Normal file
94
examples/tutorial/hello/php/README.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Tutorial 1: PHP Function w/ Input (3 minutes)
|
||||
|
||||
This example will show you how to test and deploy PHP code to Oracle Functions. It will also demonstrate passing data in through stdin.
|
||||
|
||||
### First, run the following commands:
|
||||
|
||||
```sh
|
||||
# Initialize your function creating a func.yaml file
|
||||
fn init <DOCKERHUB_USERNAME>/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
|
||||
|
||||
# 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/hello
|
||||
```
|
||||
|
||||
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/myapp/hello
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
### Note on Dependencies
|
||||
|
||||
In PHP, you can create a [composer](https://getcomposer.org/) file in your function directory, then run:
|
||||
|
||||
```sh
|
||||
fn build
|
||||
```
|
||||
|
||||
This will rebuild your gems and vendor them. PHP doesn't pick them up automatically, so you'll have to add this to the top of your `func.php` file:
|
||||
|
||||
```php
|
||||
require 'vendor/autoload.php';
|
||||
```
|
||||
|
||||
Open `func.php` to see it in action.
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
```sh
|
||||
cat hello.payload.json | fn call phpapp /hello
|
||||
```
|
||||
|
||||
|
||||
|
||||
# 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**
|
||||
```php
|
||||
$payload = json_decode(file_get_contents("php://stdin"), true);
|
||||
```
|
||||
|
||||
3. We wrote our output to **stdout**
|
||||
```php
|
||||
echo "Hello World!\n";
|
||||
```
|
||||
|
||||
4. We sent **stderr** to the server logs
|
||||
```php
|
||||
fwrite(STDERR, "--> this will go to stderr (server logs)\n");
|
||||
```
|
||||
|
||||
5. We added PHP dependencies and enabled them using:
|
||||
```php
|
||||
require 'vendor/autoload.php';
|
||||
```
|
||||
|
||||
|
||||
# Next Up
|
||||
## [Tutorial 2: Input Parameters](examples/tutorial/params)
|
||||
5
examples/tutorial/hello/php/composer.json
Normal file
5
examples/tutorial/hello/php/composer.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"require": {
|
||||
"monolog/monolog": "1.0.*"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
<?php
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
fwrite(STDERR, "--> this will go to stderr (server logs)\n");
|
||||
stream_set_blocking(STDIN, 0);
|
||||
$payload = json_decode(file_get_contents("php://stdin"), true);
|
||||
if (isset($payload['name'])) {
|
||||
echo "Hello ", $payload['name'],"!\n\n";
|
||||
echo "Hello ", $payload['name'],"!\n";
|
||||
} else {
|
||||
echo "Hello World!\n\n";
|
||||
echo "Hello World!\n";
|
||||
}
|
||||
6
examples/tutorial/hello/php/func.yaml
Normal file
6
examples/tutorial/hello/php/func.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
name: carimura2/hello
|
||||
version: 0.0.2
|
||||
runtime: php
|
||||
entrypoint: php func.php
|
||||
path: /hello
|
||||
max_concurrency: 1
|
||||
96
examples/tutorial/hello/ruby/README.md
Normal file
96
examples/tutorial/hello/ruby/README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Tutorial 1: Ruby Function w/ Input (3 minutes)
|
||||
|
||||
This example will show you how to test and deploy Ruby code to Oracle Functions. It will also demonstrate passing data in through stdin.
|
||||
|
||||
### First, run the following commands:
|
||||
|
||||
```sh
|
||||
# Initialize your function creating a func.yaml file
|
||||
fn init <DOCKERHUB_USERNAME>/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
|
||||
|
||||
# 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/hello
|
||||
```
|
||||
|
||||
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/myapp/hello
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
### Note on Dependencies
|
||||
|
||||
In Ruby, we create a [Gemfile](http://bundler.io/gemfile.html) file in your function directory, then run:
|
||||
|
||||
```sh
|
||||
fn build
|
||||
```
|
||||
|
||||
This will rebuild your gems and vendor them. Ruby doesn't pick up the gems automatically, so you'll have to add this to the top of your `func.rb` file:
|
||||
|
||||
```ruby
|
||||
require_relative 'bundle/bundler/setup'
|
||||
```
|
||||
|
||||
Open `func.rb` to see it in action.
|
||||
|
||||
To update dependencies:
|
||||
|
||||
```sh
|
||||
# Let's run bundle update
|
||||
docker run --rm -it -v ${PWD}:/worker -w /worker funcy/ruby:dev bundle update
|
||||
|
||||
# Then bundle install again to vendor them
|
||||
docker run --rm -it -v ${PWD}:/worker -w /worker funcy/ruby:dev bundle install --standalone --clean
|
||||
```
|
||||
|
||||
# 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**
|
||||
```ruby
|
||||
payload = STDIN.read
|
||||
```
|
||||
|
||||
3. We wrote our output to **stdout**
|
||||
```ruby
|
||||
puts "Hello #{name} from Ruby!"
|
||||
```
|
||||
|
||||
4. We sent **stderr** to the server logs
|
||||
```ruby
|
||||
STDERR.puts
|
||||
```
|
||||
|
||||
5. We enabled our Ruby gem dependencies using `require_relative`
|
||||
```ruby
|
||||
require_relative 'bundle/bundler/setup'
|
||||
```
|
||||
|
||||
|
||||
# Next Up
|
||||
## [Tutorial 2: Input Parameters](examples/tutorial/params)
|
||||
|
||||
|
||||
|
||||
@@ -9,4 +9,6 @@ if payload != ""
|
||||
name = payload['name']
|
||||
end
|
||||
|
||||
puts "Hello #{name} from Ruby!"
|
||||
puts "Hello #{name}!"
|
||||
|
||||
STDERR.puts "---> STDERR goes to server logs"
|
||||
30
examples/tutorial/params/func.go
Normal file
30
examples/tutorial/params/func.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := os.Getenv("REQUEST_URL")
|
||||
|
||||
fmt.Printf("REQUEST_URL --> %v\n\n", s)
|
||||
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
m, _ := url.ParseQuery(u.RawQuery)
|
||||
|
||||
if len(m) == 0 {
|
||||
fmt.Println("Try adding some URL params like &id=123")
|
||||
} else {
|
||||
for k, v := range m {
|
||||
fmt.Printf("found param: %v, val: %v\n", k, v[0])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
6
examples/tutorial/params/func.yaml
Normal file
6
examples/tutorial/params/func.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
name: carimura2/fn3_request
|
||||
version: 0.0.6
|
||||
runtime: go
|
||||
entrypoint: ./func
|
||||
path: /fn3
|
||||
max_concurrency: 1
|
||||
@@ -52,6 +52,7 @@
|
||||
ignored = ["github.com/treeder/functions", "github.com/treeder/functions/api/version"]
|
||||
|
||||
[[dependencies]]
|
||||
branch = "master"
|
||||
name = "github.com/aws/aws-sdk-go"
|
||||
version = "^1.8.23"
|
||||
|
||||
|
||||
15
fn/apps.go
15
fn/apps.go
@@ -145,7 +145,20 @@ func (a *appsCmd) create(c *cli.Context) error {
|
||||
return fmt.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(resp.Payload.App.Name, "created")
|
||||
const createHeader = `
|
||||
____ __
|
||||
/ __ \_________ ______/ /__
|
||||
/ / / / ___/ __ / ___/ / _ \
|
||||
/ /_/ / / / /_/ / /__/ / __/
|
||||
\_________ \__,_/\___/_/\____ _
|
||||
/ ____/_ ______ _____/ /_(_)___ ____ _____
|
||||
/ /_ / / / / __ \/ ___/ __/ / __ \/ __ \/ ___/
|
||||
/ __/ / /_/ / / / / /__/ /_/ / /_/ / / / (__ )
|
||||
/_/ \____/_/ /_/\___/\__/_/\____/_/ /_/____/
|
||||
`
|
||||
|
||||
fmt.Println(createHeader)
|
||||
fmt.Println("Successfully created app: ", resp.Payload.App.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
32
fn/init.go
32
fn/init.go
@@ -17,19 +17,20 @@ import (
|
||||
|
||||
"strings"
|
||||
|
||||
"gitlab.oracledx.com/odx/functions/fn/langs"
|
||||
"github.com/urfave/cli"
|
||||
"gitlab.oracledx.com/odx/functions/fn/langs"
|
||||
)
|
||||
|
||||
var (
|
||||
fileExtToRuntime = map[string]string{
|
||||
".go": "go",
|
||||
".js": "node",
|
||||
".rb": "ruby",
|
||||
".py": "python",
|
||||
".rs": "rust",
|
||||
".cs": "dotnet",
|
||||
".fs": "dotnet",
|
||||
".go": "go",
|
||||
".js": "node",
|
||||
".rb": "ruby",
|
||||
".py": "python",
|
||||
".php": "php",
|
||||
".rs": "rust",
|
||||
".cs": "dotnet",
|
||||
".fs": "dotnet",
|
||||
}
|
||||
|
||||
fnInitRuntimes []string
|
||||
@@ -99,7 +100,7 @@ func (a *initFnCmd) init(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
if ff != nil {
|
||||
return errors.New("function file already exists")
|
||||
return errors.New("Function file already exists")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +131,7 @@ func (a *initFnCmd) init(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("func.yaml created.")
|
||||
fmt.Println("func.yaml created")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -142,11 +143,11 @@ func (a *initFnCmd) buildFuncFile(c *cli.Context) error {
|
||||
|
||||
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>")
|
||||
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>")
|
||||
}
|
||||
|
||||
if exists("Dockerfile") {
|
||||
fmt.Println("Dockerfile found, will use that to build.")
|
||||
fmt.Println("Dockerfile found. Let's use that to build...")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -157,9 +158,10 @@ func (a *initFnCmd) buildFuncFile(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
a.runtime = rt
|
||||
fmt.Printf("assuming %v runtime\n", rt)
|
||||
fmt.Printf("Found %v, assuming %v runtime.\n", rt, rt)
|
||||
} else {
|
||||
fmt.Println("Runtime:", a.runtime)
|
||||
}
|
||||
fmt.Println("runtime:", a.runtime)
|
||||
if _, ok := acceptableFnRuntimes[a.runtime]; !ok {
|
||||
return fmt.Errorf("init does not support the %s runtime, you'll have to create your own Dockerfile for this function", a.runtime)
|
||||
}
|
||||
@@ -193,5 +195,5 @@ func detectRuntime(path string) (runtime string, err error) {
|
||||
return runtime, nil
|
||||
}
|
||||
}
|
||||
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.")
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ func GetLangHelper(lang string) LangHelper {
|
||||
return &RubyLangHelper{}
|
||||
case "python":
|
||||
return &PythonHelper{}
|
||||
case "php":
|
||||
return &PhpLangHelper{}
|
||||
case "rust":
|
||||
return &RustLangHelper{}
|
||||
case "dotnet":
|
||||
|
||||
49
fn/langs/php.go
Normal file
49
fn/langs/php.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package langs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PhpLangHelper struct {
|
||||
BaseHelper
|
||||
}
|
||||
|
||||
func (lh *PhpLangHelper) Entrypoint() string {
|
||||
return "php func.php"
|
||||
}
|
||||
|
||||
func (lh *PhpLangHelper) HasPreBuild() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (lh *PhpLangHelper) PreBuild() error {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists(filepath.Join(wd, "composer.json")) {
|
||||
return nil
|
||||
}
|
||||
|
||||
pbcmd := fmt.Sprintf("docker run --rm -v %s:/worker -w /worker funcy/php:dev composer install", wd)
|
||||
fmt.Println("Running prebuild command:", pbcmd)
|
||||
parts := strings.Fields(pbcmd)
|
||||
head := parts[0]
|
||||
parts = parts[1:len(parts)]
|
||||
cmd := exec.Command(head, parts...)
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("error running docker build: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lh *PhpLangHelper) AfterBuild() error {
|
||||
return nil
|
||||
}
|
||||
@@ -37,7 +37,7 @@ func newFn() *cli.App {
|
||||
app.Version = vers.Version
|
||||
app.Authors = []cli.Author{{Name: "Oracle Corporation"}}
|
||||
app.Description = "Oracle Functions command line tools"
|
||||
app.UsageText = `Check the manual at https://github.com/treeder/functions/blob/master/fn/README.md`
|
||||
app.UsageText = `Check the manual at https://gitlab.oracledx.com/odx/functions/blob/master/fn/README.md`
|
||||
|
||||
cli.AppHelpTemplate = `{{.Name}} {{.Version}}{{if .Description}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user