@@ -3,7 +3,7 @@ Fn is a lightweight Docker-based serverless functions platform you can run on
33your laptop, server, or cloud. In this introductory tutorial we'll walk through
44developing a function using the Ruby programming language (without installing
55any Ruby tools!) and deploying that function to a local Fn server. We'll also
6- learn about the core Fn concepts like applications and triggers .
6+ learn about the core Fn concepts like applications and invoke endpoints .
77
88### Before you Begin
99* Set aside about 15 minutes to complete this tutorial.
@@ -15,8 +15,8 @@ learn about the core Fn concepts like applications and triggers.
1515perform an action.
1616
1717## Your First Function
18- Now that Fn server is up and running, let's start with a very simple "hello
19- world " function written in [ Ruby] ( https://www.ruby-lang.org/ ) . Don't worry, you
18+ Now that Fn server is up and running, let's start with a very simple "Hello
19+ World! " function written in [ Ruby] ( https://www.ruby-lang.org/ ) . Don't worry, you
2020don't need to know Ruby! as Fn provides the necessary Ruby compiler and tools as
2121a Docker container. Let's walk through your first function to become familiar
2222with the process and how Fn supports development.
@@ -27,7 +27,7 @@ In the terminal type the following.
2727
2828![ user input] ( images/userinput.png )
2929> ``` sh
30- > fn init --runtime ruby --trigger http rubyfn
30+ > fn init --runtime ruby rubyfn
3131> ` ` `
3232
3333The output will be
@@ -41,7 +41,7 @@ func.yaml created.
4141The ` fn init ` command creates an simple function with a bit of boilerplate to
4242get you started. The ` --runtime ` option is used to indicate that the function
4343we're going to develop is written in Ruby. A number of other runtimes are
44- also supported. The ` --trigger ` option creates a URL for HTTP access to the function. Fn creates the simple function along with several supporting
44+ also supported. Fn creates the simple function along with several supporting
4545files in the ` /rubyfn ` directory.
4646
4747### Review your Function File
@@ -103,10 +103,6 @@ name: rubyfn
103103version: 0.0.1
104104runtime: ruby
105105entrypoint: ruby func.rb
106- triggers:
107- - name: rubyfn-trigger
108- type: http
109- source: /rubyfn-trigger
110106```
111107
112108The generated `func.yaml` file contains metadata about your function and
@@ -119,10 +115,6 @@ declares a number of properties including:
119115in `--runtime`.
120116* entrypoint--the name of the executable to invoke when your function is called,
121117in this case `ruby func.rb`.
122- * triggers--identifies the automatically generated trigger name and source. For
123- example, this function would be executed from the URL
124- <http://localhost:8080/t/appname/rubyfn-trigger>. Where appname is the name of
125- the app chosen for your function when it is deployed.
126118
127119There are other user specifiable properties but these will suffice for
128120this example. Note that the name of your function is taken from the containing
@@ -162,7 +154,7 @@ Next, functions are grouped together into an application. The application acts a
162154! [user input](images/userinput.png)
163155> ` ` ` sh
164156> fn create app rubyapp
165- > ` ` `
157+ > ` ` `
166158
167159A confirmation is returned:
168160
@@ -191,71 +183,71 @@ You should see output similar to:
191183` ` ` yaml
192184Deploying rubyfn to app: rubyapp
193185Bumped to version 0.0.2
194- Building image fndemouser/rubyfn:0.0.2
186+ Building image fndemouser/rubyfn:0.0.2
195187FN_REGISTRY: fndemouser
196188Current Context: default
197189Sending build context to Docker daemon 5.12kB
198190Step 1/9 : FROM fnproject/ruby:dev as build-stage
199191dev: Pulling from fnproject/ruby
200- cd784148e348: Already exists
201- dc557ec385e9: Pull complete
202- 1da25603bb9b: Pull complete
203- 4b4f9165fe22: Pull complete
204- cb19460a63ec: Pull complete
205- Digest: sha256:1d810dd09525d7d5c7c98b60e8138bfda26dc227c68e8861a34c5fb3a1918ac8
192+ 8e402f1a9c57: Pull complete
193+ 130243e17afe: Pull complete
194+ 6c9c3bad0e4b: Pull complete
195+ 975485ddf10f: Pull complete
196+ ff91390ffeaa: Pull complete
197+ e131fd4f74d4: Pull complete
198+ Digest: sha256:5ac41003591b935641de791945fdbf15bcb926cecf6ecdb1daf2158b5de7e6d5
206199Status: Downloaded newer image for fnproject/ruby:dev
207- ---> 8f015ef7f730
200+ ---> 37ecabff3a24
208201Step 2/9 : WORKDIR /function
209- ---> Running in 05a9394fd0c3
210- Removing intermediate container 05a9394fd0c3
211- ---> a6ede4bf3e4a
202+ ---> Running in d950c6c534e2
203+ Removing intermediate container d950c6c534e2
204+ ---> 823a90c41257
212205Step 3/9 : ADD Gemfile* /function/
213- ---> be0ac9361ac2
206+ ---> 316c7eab8ab6
214207Step 4/9 : RUN bundle install
215- ---> Running in 7cf6c166509e
208+ ---> Running in 1cd8c41d3863
216209Don' t run Bundler as root. Bundler can ask for sudo if it is needed, and
217210installing your bundle as root will break this application for all non-root
218211users on this machine.
219212Fetching gem metadata from https://rubygems.org/..
220213Resolving dependencies...
221214Using bundler 2.0.1
222- Fetching json 2.1 .0
223- Installing json 2.1 .0 with native extensions
215+ Fetching json 2.2 .0
216+ Installing json 2.2 .0 with native extensions
224217Fetching webrick 1.4.2
225218Installing webrick 1.4.2
226- Fetching fdk 0.0.18
227- Installing fdk 0.0.18
219+ Fetching fdk 0.0.20
220+ Installing fdk 0.0.20
228221Bundle complete! 1 Gemfile dependency, 4 gems now installed.
229222Use `bundle info [gemname]` to see where a bundled gem is installed.
230- Removing intermediate container 7cf6c166509e
231- ---> a40fd74b7b33
223+ Removing intermediate container 1cd8c41d3863
224+ ---> 9bf1d44c3c3f
232225Step 5/9 : FROM fnproject/ruby
233226latest: Pulling from fnproject/ruby
234- cd784148e348: Already exists
235- dc557ec385e9: Already exists
236- 1da25603bb9b: Already exists
237- Digest: sha256:c7a22b37d040361c43d91ec11a86a787454bea9f6ff58840ab6c6187c0e7417d
227+ 8e402f1a9c57: Already exists
228+ 130243e17afe: Already exists
229+ 6c9c3bad0e4b: Already exists
230+ 975485ddf10f: Already exists
231+ Digest: sha256:46e981c2e093a87b98c05f21d4a7701d5c53f5e1aed1be64eea8ab0a935c9ddb
238232Status: Downloaded newer image for fnproject/ruby:latest
239- ---> b8ffc8f5dd00
233+ ---> f5452b336752
240234Step 6/9 : WORKDIR /function
241- ---> Running in a102b7cb5e02
242- Removing intermediate container a102b7cb5e02
243- ---> c585eaa8237c
235+ ---> Running in f1a2c9206a03
236+ Removing intermediate container f1a2c9206a03
237+ ---> 88a1389a388e
244238Step 7/9 : COPY --from=build-stage /usr/lib/ruby/gems/ /usr/lib/ruby/gems/
245- ---> c35bc61d347b
239+ ---> 0cdd932b123a
246240Step 8/9 : ADD . /function/
247- ---> 8e27331240a0
241+ ---> 51f09786d6b2
248242Step 9/9 : ENTRYPOINT ["ruby", "func.rb"]
249- ---> Running in aa073542028b
250- Removing intermediate container aa073542028b
251- ---> 661255862190
252- Successfully built 661255862190
243+ ---> Running in 19e5cf8f4523
244+ Removing intermediate container 19e5cf8f4523
245+ ---> 43d04792b080
246+ Successfully built 43d04792b080
253247Successfully tagged fndemouser/rubyfn:0.0.2
254248
255249Updating function rubyfn using image fndemouser/rubyfn:0.0.2...
256250Successfully created function: rubyfn with fndemouser/rubyfn:0.0.2
257- Successfully created trigger: rubyfn-trigger
258- Trigger Endpoint: http://localhost:8080/t/rubyapp/rubyfn-trigger
259251```
260252
261253All the steps to load the current language Docker image are displayed.
@@ -271,48 +263,10 @@ The output message
271263let' s us know that the function packaged in the image
272264` fndemouser/rubyfn:0.0.2` .
273265
274- Note that the containing folder name ` rubyfn` was used as the name of the generated Docker container and used as the name of the function that container was bound to. By convention it is also used to create the trigger name ` rubyfn-trigger ` .
266+ Note that the containing folder name ` rubyfn` was used as the name of the generated Docker container and used as the name of the function that container was bound to.
275267
276268Normally you deploy an application without the ` --verbose` option. If you rerun the command a new image and version is created and loaded.
277269
278- # # Invoke your Deployed Function
279- There are two ways to call your deployed function.
280-
281- # ## Invoke with the CLI
282- The first is using the Fn CLI which makes invoking your function relatively
283- easy. Type the following:
284-
285- ! [user input](images/userinput.png)
286- > ` ` ` sh
287- > fn invoke rubyapp rubyfn
288- > ` ` `
289-
290- which results in:
291-
292- ` ` ` js
293- {" message" :" Hello World!" }
294- ` ` `
295-
296- When you invoked ` rubyapp rubyfn` the Fn server looked up the ` rubyapp`
297- application and then looked for the Docker container image bound to the
298- ` rubyfn` function and executed the code. Fn ` invoke` invokes your function
299- directly and independently of any associated triggers. You can always invoke a
300- function even without it having any triggers bound to it. Note the content type was specified as well.
301-
302- You can also pass data to the invoke command. For example:
303-
304- ! [user input](images/userinput.png)
305- > ` ` ` sh
306- > echo -n ' {"name":"Bob"}' | fn invoke rubyapp rubyfn --content-type application/json
307- > ` ` `
308-
309- ` ` ` js
310- {" message" :" Hello Bob!" }
311- ` ` `
312-
313- The JSON data was parsed and since ` name` was set to ` Bob` , that value is passed
314- in the output.
315-
316270# ## Understand Fn deploy
317271If you have used Docker before the output of ` fn --verbose deploy` should look
318272familiar--it looks like the output you see when running ` docker build`
@@ -359,37 +313,106 @@ The Fn CLI provides a couple of commands to let us see what we've deployed.
359313Which, in our case, returns the name of the application we created when we
360314deployed our ` rubyfn` function:
361315
362- ` ` ` sh
316+ ` ` ` txt
363317NAME ID
364- rubyapp 01CT433P8VNG8G00GZJ000001A
318+ rubyapp 01DKA1TFRQNG8G00GZJ000000K
365319` ` `
366320
367- We can also see the functions that are defined by an application. Since functions are exposed via triggers, the ` fn list triggers < appname > ` command is used. To list the functions included in " rubyapp " we can type:
321+ The ` fn list functions < app-name > ` command lists all the functions associated with and app.
368322
369- ! [User Input Icon ](images/userinput.png)
323+ ! [user input ](images/userinput.png)
370324> ` ` ` sh
371- > fn list triggers rubyapp
325+ > fn list functions rubyapp
372326> ` ` `
373327
374- ` ` ` sh
375- FUNCTION NAME ID TYPE SOURCE ENDPOINT
376- rubyfn rubyfn-trigger 01D46F1SZANG8G00GZJ0000003 http /rubyfn-trigger http://localhost:8080/t/rubyapp/rubyfn-trigger
328+ The returns all the functions associated with the ` nodeapp` .
329+
330+ ` ` ` txt
331+ NAME IMAGE ID
332+ rubyfn fndemouser/rubyfn:0.0.2 01DKA1TFRQNG8G00GZJ000000K
377333` ` `
378334
379- The output confirms that ` rubyapp` contains a ` rubyfn` function that is
380- implemented by the Docker container ` fndemouser/rubyfn:0.0.2` which may be
381- invoked via the specified URL.
335+
336+ # # Invoke your Deployed Function
337+ There are two ways to call your deployed function.
338+
339+ # ## Invoke with the CLI
340+ The first is using the Fn CLI which makes invoking your function relatively
341+ easy. Type the following:
342+
343+ ! [user input](images/userinput.png)
344+ > ` ` ` sh
345+ > fn invoke rubyapp rubyfn
346+ > ` ` `
347+
348+ which results in:
349+
350+ ` ` ` js
351+ {" message" :" Hello World!" }
352+ ` ` `
353+
354+ When you invoked ` rubyapp rubyfn` the Fn server looked up the ` rubyapp`
355+ application and then looked for the Docker container image bound to the
356+ ` rubyfn` function and executed the code.
357+
358+ You can also pass data to the invoke command. For example:
359+
360+ ! [user input](images/userinput.png)
361+ > ` ` ` sh
362+ > echo -n ' {"name":"Bob"}' | fn invoke rubyapp rubyfn --content-type application/json
363+ > ` ` `
364+
365+ ` ` ` js
366+ {" message" :" Hello Bob!" }
367+ ` ` `
368+
369+ The JSON data was parsed and since ` name` was set to ` Bob` , that value is passed
370+ in the output.
371+
372+ # ## Getting a Function's Invoke Endpoint
373+
374+ In addition to using the Fn ` invoke` command, we can call a function by using a
375+ URL. To do this, we must get the function' s invoke endpoint. Use the command
376+ `fn inspect function <appname> <function-name>`. To list the `nodefn` function' s
377+ invoke endpoint we can type:
378+
379+ ! [user input](images/userinput.png)
380+ > ` ` ` sh
381+ > fn inspect function rubyapp rubyfn
382+ > ` ` `
383+
384+ ` ` ` js
385+ {
386+ " annotations" : {
387+ " fnproject.io/fn/invokeEndpoint" : " http://localhost:8080/invoke/01DKA1TFRQNG8G00GZJ000000K"
388+ },
389+ " app_id" : " 01DKA1S0N3NG8G00GZJ000000J" ,
390+ " created_at" : " 2019-08-27T17:26:22.231Z" ,
391+ " id" : " 01DKA1TFRQNG8G00GZJ000000K" ,
392+ " idle_timeout" : 30,
393+ " image" : " fndemouser/rubyfn:0.0.2" ,
394+ " memory" : 128,
395+ " name" : " rubyfn" ,
396+ " timeout" : 30,
397+ " updated_at" : " 2019-08-27T17:26:22.231Z"
398+ }
399+ ` ` `
400+
401+ The output confirms that ` rubyfn` functions invoke endpoint is:
402+ ` http://localhost:8080/invoke/01DKA1TFRQNG8G00GZJ000000K` . We can use this URL
403+ to call the function.
382404
383405# ## Invoke with Curl
384- The other way to invoke your function is via HTTP. The Fn server exposes our
385- deployed function at ` http://localhost:8080/t/rubyapp/rubyfn-trigger` , a URL
386- that incorporates our application and function trigger as path elements.
406+
407+ Once we have the invoke endpoint, the second method for invoking our function
408+ can be used, HTTP. The Fn server exposes our deployed function at
409+ ` http://localhost:8080/invoke/01DKA1TFRQNG8G00GZJ000000K` .
387410
388411Use ` curl` to invoke the function:
389412
390413! [user input](images/userinput.png)
391414> ` ` ` sh
392- > curl -H " Content-Type: application/json" http://localhost:8080/t/rubyapp/rubyfn-trigger
415+ > curl -X " POST " - H " Content-Type: application/json" http://localhost:8080/invoke/01DKA1TFRQNG8G00GZJ000000K
393416> ` ` `
394417
395418The result is once again the same.
@@ -402,8 +425,8 @@ We can again pass JSON data to our function and get the value of name passed to
402425the function back.
403426
404427! [user input](images/userinput.png)
405- > ` ` `
406- > curl -H " Content-Type: application/json" -d ' {"name":"Bob"}' http://localhost:8080/t/rubyapp/rubyfn-trigger
428+ > ` ` ` sh
429+ > curl -X " POST " - H " Content-Type: application/json" -d ' {"name":"Bob"}' http://localhost:8080/invoke/01DKA1TFRQNG8G00GZJ000000K
407430> ` ` `
408431
409432The result is once again the same.
0 commit comments