1 | [![Build Status](https://travis-ci.org/backstage/functions.png?branch=master)](https://travis-ci.org/backstage/functions)
|
2 | [![Coverage Status](https://coveralls.io/repos/github/backstage/functions/badge.svg?branch=master)](https://coveralls.io/github/backstage/functions?branch=master)
|
3 |
|
4 | # Backstage Functions
|
5 | Backstage Functions is an Open Source [Serverless](http://martinfowler.com/articles/serverless.html) Platform able to store and execute code.
|
6 |
|
7 | ## Benefits
|
8 | - Your code will be executed in an isolated environment
|
9 | - You don't have to worry about infrastructure
|
10 | - Functions can be called at any time by any project
|
11 |
|
12 | ## FAQ
|
13 | - **Which languages are supported?**
|
14 | Currently, only Javascript.
|
15 |
|
16 | - **Is it based on events?**
|
17 | Not yet.
|
18 |
|
19 | - **How the code execution happens in an isolated way?**
|
20 | It uses the [Backstage Functions Sandbox](https://github.com/backstage/functions-sandbox).
|
21 |
|
22 | ## Running locally without Docker
|
23 | ### Requirements
|
24 | - Redis 3.0+
|
25 | - NodeJS 8.9.1
|
26 |
|
27 | ### Download the project
|
28 | ```bash
|
29 | git clone https://github.com/backstage/functions.git
|
30 | ```
|
31 |
|
32 | ### Setup
|
33 | ```bash
|
34 | make setup
|
35 | ```
|
36 |
|
37 | ### Run
|
38 | ```bash
|
39 | make run
|
40 | ```
|
41 |
|
42 | ## Running locally via Docker
|
43 | ### Requirements
|
44 | - Docker 1.12+
|
45 | - Docker compose 1.8+
|
46 |
|
47 | ### Download docker-compose.yml
|
48 | ```bash
|
49 | mkdir functions
|
50 | cd functions
|
51 | curl 'https://raw.githubusercontent.com/backstage/functions/master/docker-compose.yml' > docker-compose.yml
|
52 | ```
|
53 |
|
54 | ### Run
|
55 | ```bash
|
56 | docker-compose up
|
57 | ```
|
58 |
|
59 | ## How to use
|
60 | ### Function Structure
|
61 | Your function will have a file, which you define any name you want, and it has to have a function called `main`, with two parameters: `req` and `res`. Req represents the `Request` and Res represents the `Response`.
|
62 | At the end of your code, you'll have to use the `send` method.
|
63 |
|
64 | #### Example of a function
|
65 | ```javascript
|
66 | function main(req, res) {
|
67 | const name = (req.body && req.body.name) || "World"
|
68 | res.send({ say: `Hello ${name}!` })
|
69 | }
|
70 | ```
|
71 | ### Setting a function
|
72 |
|
73 | To set your function, you can make a `PUT` request to `/functions/:namespace/:name`:
|
74 | ```bash
|
75 | curl -i -X PUT http://localhost:8100/functions/example/hello-world \
|
76 | -H 'content-type: application/json' \
|
77 | -d '{"code":"function main(req, res) {\n const name = (req.body && req.body.name) || \"World\"\n res.send({ say: `Hello ${name}! Nice meeting you...` })\n}\n"}'
|
78 | ```
|
79 |
|
80 | *Ps: if it doesn't exists, it will be created*
|
81 |
|
82 | ### Deleting a function
|
83 | To delete your function, you can make a `DELETE` request to `/functions/:namespace/:name`:
|
84 | ```bash
|
85 | curl -i -X DELETE http://localhost:8100/functions/example/hello-world \
|
86 | -H 'content-type: application/json'
|
87 | ```
|
88 |
|
89 | ### Executing a function
|
90 | To execute a function, you can make a `PUT` request to `/functions/:namespace/:name/run`:
|
91 | ```bash
|
92 | curl -i -X PUT http://localhost:8100/functions/example/hello-world/run \
|
93 | -H 'content-type: application/json'
|
94 | ```
|
95 |
|
96 | The result will be something like:
|
97 | ```bash
|
98 | HTTP/1.1 200 OK
|
99 | Content-Type: application/json; charset=utf-8
|
100 | Content-Length: 22
|
101 | ETag: W/"16-soBGetwJPBLt8CqWpBQu+A"
|
102 | Date: Tue, 11 Oct 2016 16:51:04 GMT
|
103 | Connection: keep-alive
|
104 |
|
105 | {"say":"Hello World!"}
|
106 | ```
|
107 |
|
108 | If one needs to pass an object in the request, the payload is executed:
|
109 | ```bash
|
110 | curl -i -X PUT http://localhost:8100/functions/example/hello-world/run \
|
111 | -H 'content-type: application/json' \
|
112 | -d '{"name": "Pedro"}'
|
113 | ```
|
114 |
|
115 | The result will be something like:
|
116 | ```bash
|
117 | HTTP/1.1 200 OK
|
118 | Content-Type: application/json; charset=utf-8
|
119 | Content-Length: 22
|
120 | ETag: W/"16-Ino2/umXaZ3xVEhoqyS8aA"
|
121 | Date: Tue, 11 Oct 2016 17:13:11 GMT
|
122 | Connection: keep-alive
|
123 |
|
124 | {"say":"Hello Pedro!"}
|
125 | ```
|
126 |
|
127 | ### Executing functions in a pipeline
|
128 |
|
129 | To execute many functions in a pipeline, you can make a `PUT` request to `/functions/pipeline`:
|
130 | ```javascript
|
131 | // Function0
|
132 | function main(req, res) {\
|
133 | res.send({x: req.body.x * 10});
|
134 |
|
135 | }
|
136 |
|
137 | // Function1
|
138 | function main(req, res) {
|
139 | res.send({x: req.body.x * 20});
|
140 | }
|
141 | ```
|
142 |
|
143 | ```
|
144 | curl -g -i -X PUT 'http://localhost:8100/functions/pipeline?steps[0]=namespace/function0&steps[1]=namespace/function1' \
|
145 | -H 'content-type: application/json'
|
146 | -d '{"x": 1}'
|
147 | ```
|
148 |
|
149 | Considering the curl above, the pipeline result would be like this:
|
150 |
|
151 | ```bash
|
152 | HTTP/1.1 200 OK
|
153 | Content-Type: application/json; charset=utf-8
|
154 | Content-Length: 22
|
155 | ETag: W/"16-Ino2/umXaZ3xVEhoqyS8aA"
|
156 | Date: Tue, 11 Oct 2016 17:13:11 GMT
|
157 | Connection: keep-alive
|
158 |
|
159 | {"x": 200}
|
160 | ```
|