Coder Social home page Coder Social logo

funk's Introduction

FunK

FunK is a scalable function provider (think to a kind of small FaaS)

๐Ÿ‘‹ FunK is "cloud provider agnostic", you can deploy FunK where you want. You don't need Kubernetes or Docker, but you can if you want.

๐Ÿ‘‹ It means that FunK is ๐ŸŽ‰ Cloud Native

FunK provides:

  • JavaScript functions
  • Kotlin functions

FunK is made with โค๏ธ with the โœจ RedPipe (Vert.x based)

โš ๏ธ don't use FunK in production: for now, it's a proof of concept

FunK is a Bots.Garden production

At the end of POC, Funk will move there: https://github.com/funk-platform

Prerequisites

  • Java 8
  • Redis database
  • Maven

Run it

Simple way (locally): :wave: Funk uses a Java SecurityManager to avoid some "malicious" funKtion

# you need to start `redis-server` before
# you need to define a token

FUNK_TOKEN="panda" \
MAVEN_OPTS="-Djava.security.manager -Djava.security.policy=./funk.policy" \
mvn install exec:java

Start with an other http port:

FUNK_TOKEN="panda" \
PORT=8080 \
MAVEN_OPTS="-Djava.security.manager -Djava.security.policy=./funk.policy" \
mvn install exec:java

Change the Redis information:

FUNK_TOKEN="panda" \
PORT=8080 \
REDIS_PORT=6379 \
REDIS_HOST="localhost" \
REDIS_PASSWORD="password" \
MAVEN_OPTS="-Djava.security.manager -Djava.security.policy=./funk.policy" \
mvn install exec:java

On a cloud provider, inside a virtual machine or a container:

  • if the FunK server is listening on 8080
  • and you are forwarding on 80 you need to use this:
  • PORT=8080
  • SERVICE_PORT=80
  • SERVICE_HOST="your.domain.name"

you will access to your FunK server like that: http://your.domain.name

# if the server is listening on 8080, but 80 is exposed
FUNK_TOKEN="panda" \
PORT=8080 \
REDIS_PORT=6379 \
REDIS_HOST="localhost" \
REDIS_PASSWORD="password" \
SERVICE_HOST="localhost" \
SERVICE_PORT=80 \
mvn install exec:java

Functions

Each function, for a language, has a unique identifier: its name, so

  • โš ๏ธ you can create only one hello JavaScript function
    • ๐Ÿ‘‹ btw, it's convenient if you want to call various versions from an other function
  • but you can create one hello JavaScript function and one hello Kotlin function
  • if you need several version use something like that: hello_v_101

โš ๏ธ ๐Ÿ‘‹ Now you can use the Funk CLI: funkli: https://github.com/k33g/funkli

JavaScript functions

Create a JavaScript function

curl --header "funk-token: panda" -H "Content-Type: application/json" -X POST http://localhost:8080/funk/js \
-d @- <<'EOF'
{
  "description":"yo function",
  "name":"yo",
  "code":"function yo(options){
    return {result: options.message};
  }"
}
EOF

Remarks:

  • the FunK JavaScript functions take only one parameter: options, this is an object (eg: {a:40, b:2})
  • you need to return a JavaScript object ({}) with a result member
  • this is a POST request
  • you need to provide the token in the header: --header "funk-token: panda"
  • โš ๏ธ the name and the name of the function in the body have to be the same
  • โš ๏ธ note the end of the url: /funk/js

Run a JavaScript function

curl --header "funk-token: panda" -H "Content-Type: application/json" -X POST http://localhost:8080/funk/js/run \
-d @- <<'EOF'
{
  "name":"yo",
  "parameters":{
    "message": "hello world"
  }
}
EOF

you'll get: {"result":"hello world"}

Remarks:

  • you need to pass the parameters thanks to an object using parameters, eg: parameters:{a:40, b:2}
  • this is a POST request

Update a JavaScript function

curl --header "funk-token: panda" -H "Content-Type: application/json" -X PUT http://localhost:8080/funk/js \
-d @- <<'EOF'
{
  "description":"yo function",
  "name":"yo",
  "code":"function yo(options){
    return {result: options.message};
  }"
}
EOF

Remarks:

  • this is a PUT request

Get the list of the JavaScript function

curl --header "funk-token: panda" -H "Content-Type: application/json" -X GET http://localhost:8080/funk/js

Kotlin functions

Create a Kotlin function

curl --header "funk-token: panda" -H "Content-Type: application/json" -X POST http://localhost:8080/funk/kt \
-d @- <<'EOF'
{
  "description":"sum function",
  "name":"sum",
  "code":"import io.vertx.core.json.JsonObject\n
    fun sum(options: JsonObject): JsonObject {\n
      val res = options.get(\"a\") as Int + options.get(\"b\") as Int\n
      return JsonObject().put(\"result\", res)\n
    }
  "
}
EOF

Remarks:

  • the FunK Kotlin functions take only one parameter: options, this is a Map<String, Object>
  • you need to return a JsonObject with a result member
    • so you need to import this: io.vertx.core.json.JsonObject
  • this is a POST request
  • you need to provide the token in the header: --header "funk-token: panda"
  • โš ๏ธ the name and the name of the function in the body have to be the same
  • โš ๏ธ note the end of the url: /funk/kt

Run a Kotlin function

curl --header "funk-token: panda" -H "Content-Type: application/json" -X POST http://localhost:8080/funk/kt/run \
-d @- <<'EOF'
{
  "name":"sum",
  "parameters":{
    "a": 38,
    "b": 4
  }
}
EOF

Update a Kotlin function

curl --header "funk-token: panda" -H "Content-Type: application/json" -X PUT http://localhost:8080/funk/kt \
-d @- <<'EOF'
{
  "description":"sum function",
  "name":"sum",
  "code":"import io.vertx.core.json.JsonObject\n
    fun sum(options: JsonObject): JsonObject {\n
      val res = options.get(\"a\") as Int + options.get(\"b\") as Int\n
      return JsonObject().put(\"result\", res)\n
    }
  "
}
EOF

Get the list of the Kotlin function

curl --header "funk-token: panda" -H "Content-Type: application/json" -X GET http://localhost:8080/funk/kt

Function call Functions

Calling JavaScript and Kotlin functions from JavaScript

var Funk = Java.type('funk.Funk');
var JsonObject = Java.type('io.vertx.core.json.JsonObject');


var sumParameters = new JsonObject()
sumParameters.put("a", 40)
sumParameters.put("b", 2)
var sumJS = Funk.js("sum").call(sumParameters)
    
print("SUM JS: " + sumJS) // SUM JS: {"result":42.0}
    
var sumKT = Funk.kt("sum").call(sumParameters)
    
print("SUM KT: " + sumKT)  // SUM KT: {"result":42.0}

Calling JavaScript and Kotlin functions from Kotlin

import io.vertx.core.json.JsonObject
import funk.Funk
    

val sumParameters = JsonObject()
sumParameters.put("a", 40)
sumParameters.put("b", 2)

val sumJS = Funk.js("sum").call(sumParameters)
val sumKT = Funk.kt("sum").call(sumParameters)

TODO

  • JavaScript Client
  • JavaClient
  • Kotlin Client
  • other clients
  • security
  • administration console
  • backup management
  • add the ability to use files locally and in an object storage
  • add the ability to use files from a source control management system
  • https
  • logs management
  • function deletion
  • ...

funk's People

Contributors

k33g avatar remicaumette avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

funk's Issues

serve html

  • GET request on a funKtion that returns html

Add tests

  • add unit tests
  • automatize(?) test of creation, update, run ...

NPE when calling a function without parameters

NPE when running this:

#!/usr/bin/env node

const fetch = require('node-fetch');

// run
fetch("http://localhost:8080/funk/kt/run", {
  body: JSON.stringify({
    name: "hello" //parameters:null
  }),
  headers: {
    'funk-token': 'panda',
    'content-type': 'application/json'
  },
  method: 'POST'
})
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.log(err));

Because there is no parameters

compilation error after restart, when calling a function using another function

  • I have 2 functions yo and hi, hi uses/calls yo
curl --header "funk-token: pandasareawesome" -H "Content-Type: application/json" -X POST http://funk.cleverapps.io/funk/js \
-d @- <<'EOF'
{
  "description":"yo function",
  "name":"yo",
  "code":"function yo(options){
    return {result: 'yo'};
  }"
}
EOF

curl --header "funk-token: pandasareawesome" -H "Content-Type: application/json" -X PUT http://funk.cleverapps.io/funk/js \
-d @- <<'EOF'
{
  "description":"hi function",
  "name":"hi",
  "code":"function hi(options){
    return {result: yo().result + ' hi'};
  }"
}
EOF
  • If I run hi I'll get {"result":"yo hi"}
  • If I restart FunK, and I call hi again, I'll get {"error":"ReferenceError: \"yo\" is not defined"}
    • yo is not compiled in memory after restart because FunK compiles again at the first call
    • I need to call first yo, then hi, and it will be ok

TODO:

  • preparation: 462e17f
  • implementation

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.