fdk 0.0.8 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +23 -6
- data/lib/fdk/context.rb +41 -37
- data/lib/fdk/runner.rb +63 -112
- data/lib/fdk/version.rb +2 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aac4d4c8971ca0678bd3e99b95be2c87fc4aea50b9419535aee57bb09d4c0b73
|
4
|
+
data.tar.gz: 3fdf4848e9e940facde5a247ffdaf8b418079e65dbb0ac23ae3ed7c622c1f41e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 021b616d4b4cfd8c49b45f4d6c97d52fc04aaa2dab3756c5d927f76f54dbce304f32cf4a2bdba2ef43462fe0038e3bcab0ddbec53d12a3217fdba7a77c0baaf2
|
7
|
+
data.tar.gz: c07e62e577f503dc5ca974be179dc878aac12306fde3603c6623709d68c46fea09811ed3606a949123dc14be2110f653f1682650568c05e85bea00abe4e6253c
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ require 'fdk`
|
|
13
13
|
Then create a function with with the following syntax:
|
14
14
|
|
15
15
|
```ruby
|
16
|
-
def myfunc(context, input)
|
16
|
+
def myfunc(context, input)
|
17
17
|
# Do some work here
|
18
18
|
return output
|
19
19
|
end
|
@@ -28,7 +28,7 @@ end
|
|
28
28
|
Then simply pass that function to the FDK:
|
29
29
|
|
30
30
|
```ruby
|
31
|
-
FDK.
|
31
|
+
FDK.handle(myfunction)
|
32
32
|
```
|
33
33
|
|
34
34
|
## Full Example
|
@@ -36,22 +36,39 @@ FDK.call(myfunc)
|
|
36
36
|
```ruby
|
37
37
|
require 'fdk'
|
38
38
|
|
39
|
-
def
|
39
|
+
def myfunction(context:, input:)
|
40
40
|
STDERR.puts "request_url: " + context.protocol['request_url']
|
41
41
|
STDERR.puts "call_id: " + context.call_id
|
42
42
|
STDERR.puts "input: " + input.to_s
|
43
|
-
|
43
|
+
{ message: "Hello #{input['name']}!" }
|
44
44
|
end
|
45
45
|
|
46
|
-
FDK.handle(:
|
46
|
+
FDK.handle(:myfunction)
|
47
47
|
```
|
48
48
|
|
49
49
|
## Running the example that is in the root directory of this repo
|
50
50
|
|
51
51
|
```sh
|
52
|
-
echo '{"name":"coolio"}' | fn run
|
52
|
+
$ echo '{"name":"coolio"}' | fn run
|
53
|
+
{"message":"Hello coolio!"}
|
53
54
|
```
|
54
55
|
|
56
|
+
You can also specify the format (the default is JSON)
|
57
|
+
|
58
|
+
```sh
|
59
|
+
$ echo '{"name":"coolio"}' | fn run --format json
|
60
|
+
{"message":"Hello coolio!"}
|
61
|
+
```
|
62
|
+
|
63
|
+
If you want to just pass plain text to the function, specify a format of __default__:
|
64
|
+
|
65
|
+
```sh
|
66
|
+
$ echo 'coolio' | fn run --format default
|
67
|
+
{"message":"Hello coolio!"}
|
68
|
+
```
|
69
|
+
|
70
|
+
Deploy:
|
71
|
+
|
55
72
|
```sh
|
56
73
|
fn deploy --app myapp --local && echo '{"name":"coolio"}' | fn call myapp /fdk-ruby
|
57
74
|
```
|
data/lib/fdk/context.rb
CHANGED
@@ -1,52 +1,56 @@
|
|
1
1
|
module FDK
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
end
|
3
|
+
# Config looks up values in the env vars
|
4
|
+
class Config
|
5
|
+
def [](key)
|
6
|
+
ENV[key.upcase]
|
8
7
|
end
|
8
|
+
end
|
9
9
|
|
10
|
-
|
10
|
+
class Context
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
# TODO: Rethink FN_PATH, if it's a reference to the route, maybe it should be FN_ROUTE? eg: if it's a dynamic path, this env var would
|
13
|
+
# show the route's path (ie: route identifier), eg: /users/:name, not the actual path.
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
15
|
+
# FN_REQUEST_URL - the full URL for the request (parsing example)
|
16
|
+
# FN_APP_NAME - the name of the application that matched this route, eg: myapp
|
17
|
+
# FN_PATH - the matched route, eg: /hello
|
18
|
+
# FN_METHOD - the HTTP method for the request, eg: GET or POST
|
19
|
+
# FN_CALL_ID - a unique ID for each function execution.
|
20
|
+
# FN_FORMAT - a string representing one of the function formats, currently either default or http. Default is default.
|
21
|
+
# FN_MEMORY - a number representing the amount of memory available to the call, in MB
|
22
|
+
# FN_TYPE - the type for this call, currently 'sync' or 'async'
|
23
|
+
# FN_HEADER_$X - the HTTP headers that were set for this request. Replace $X with the upper cased name of the header and replace dashes in the header with underscores.
|
24
|
+
# $X - any configuration values you've set for the Application or the Route. Replace X with the upper cased name of the config variable you set. Ex: minio_secret=secret will be exposed via MINIO_SECRET env var.
|
25
|
+
# FN_PARAM_$Y
|
26
26
|
|
27
|
-
|
27
|
+
# CloudEvent format: https://github.com/cloudevents/spec/blob/master/serialization.md#json
|
28
28
|
|
29
|
-
|
30
|
-
@payload = payload
|
31
|
-
end
|
29
|
+
attr_reader :event
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
def initialize(event)
|
32
|
+
@event = event
|
33
|
+
end
|
34
|
+
|
35
|
+
# If it's a CNCF CloudEvent
|
36
|
+
def cloud_event?
|
37
|
+
ENV['FN_FORMAT'] == "cloudevent"
|
38
|
+
end
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
def config
|
41
|
+
@config ||= Config.new
|
42
|
+
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
def call_id
|
45
|
+
cloud_event? ? event['eventID'] : event['call_id']
|
46
|
+
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
def content_type
|
49
|
+
cloud_event? ? event['contentType'] : event['content_type']
|
50
|
+
end
|
50
51
|
|
52
|
+
def protocol
|
53
|
+
cloud_event? ? event['extensions']['protocol'] : event['protocol']
|
51
54
|
end
|
55
|
+
end
|
52
56
|
end
|
data/lib/fdk/runner.rb
CHANGED
@@ -3,123 +3,74 @@
|
|
3
3
|
# Responds with output
|
4
4
|
|
5
5
|
require 'json'
|
6
|
+
require 'yajl'
|
6
7
|
|
7
8
|
module FDK
|
9
|
+
def self.handle(func)
|
10
|
+
format = ENV['FN_FORMAT']
|
11
|
+
if format == 'cloudevent'
|
12
|
+
parser = Yajl::Parser.new
|
8
13
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
first_bracket = false
|
15
|
-
# end_bracket=false
|
16
|
-
stack_count = 0
|
17
|
-
STDIN.each_char do |c|
|
18
|
-
# STDERR.puts "c: #{c}"
|
19
|
-
if c == '{'
|
20
|
-
if !first_bracket
|
21
|
-
# STDERR.puts "setting first_bracket"
|
22
|
-
first_bracket = true
|
23
|
-
end
|
24
|
-
stack_count += 1
|
25
|
-
elsif c == '}'
|
26
|
-
stack_count -= 1
|
27
|
-
end
|
28
|
-
if first_bracket
|
29
|
-
# STDERR.puts "in first_bracket stack_count: #{stack_count}"
|
30
|
-
obs += c
|
31
|
-
if stack_count == 0 # found last bracket, so close this out
|
32
|
-
# STDERR.puts "OBJECT: #{obs}"
|
33
|
-
payload = JSON.parse(obs)
|
34
|
-
# STDERR.puts "payload: #{payload.inspect}"
|
35
|
-
ctx = Context.new(payload)
|
36
|
-
# STDERR.puts "context: " + ctx.inspect
|
37
|
-
# STDERR.flush
|
38
|
-
body = payload['body']
|
39
|
-
if ctx.content_type == 'application/json' && body != ""
|
40
|
-
body = JSON.parse(body)
|
41
|
-
end
|
42
|
-
# TODO: begin/rescue so we can respond with proper error response and code
|
43
|
-
se = FDK.single_event(func, ctx, body)
|
44
|
-
response = {
|
45
|
-
headers: {
|
46
|
-
'Content-Type' => 'application/json'
|
47
|
-
},
|
48
|
-
'status_code' => 200,
|
49
|
-
body: se.to_json,
|
50
|
-
}
|
51
|
-
STDOUT.puts response.to_json
|
52
|
-
STDOUT.puts
|
53
|
-
STDOUT.flush
|
54
|
-
first_bracket = false
|
55
|
-
obs = ""
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
14
|
+
parser.on_parse_complete = lambda do |event|
|
15
|
+
context = Context.new(event)
|
16
|
+
body = event['data']
|
17
|
+
# Skipping json parsing of body because it would already be a parsed map according to the format spec defined here: https://github.com/cloudevents/spec/blob/master/serialization.md#json
|
18
|
+
se = FDK.single_event(function: func, context: context, input: body)
|
59
19
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
# headers: {
|
84
|
-
# 'Content-Type' => 'application/json'
|
85
|
-
# },
|
86
|
-
# 'status_code' => 200,
|
87
|
-
# body: s.to_json,
|
88
|
-
# }
|
89
|
-
# STDOUT.puts response.to_json
|
90
|
-
# STDOUT.puts
|
91
|
-
# STDOUT.flush
|
92
|
-
# obs = ""
|
93
|
-
# next
|
94
|
-
# else
|
95
|
-
# endbracket = false
|
96
|
-
# end
|
97
|
-
# obs += line
|
98
|
-
# end
|
99
|
-
elsif format == "default"
|
100
|
-
# TODO: check if content type json, and if so, parse it before passing it in
|
101
|
-
body = STDIN.read
|
102
|
-
payload = {}
|
103
|
-
payload['call_id'] = ENV['FN_CALL_ID']
|
104
|
-
payload['content_type'] = ENV['FN_HEADER_Content_Type']
|
105
|
-
payload['protocol'] = {
|
106
|
-
'type' => 'http',
|
107
|
-
'request_url' => ENV['FN_REQUEST_URL']
|
108
|
-
}
|
109
|
-
# STDERR.puts "payload: #{payload}"
|
110
|
-
c = Context.new(payload)
|
111
|
-
if c.content_type == "application/json"
|
112
|
-
# STDERR.puts "parsing json"
|
113
|
-
body = JSON.parse(body)
|
114
|
-
end
|
115
|
-
puts FDK.single_event(func, c, body).to_json
|
116
|
-
else
|
117
|
-
raise "Format '#{format}' not supported in Ruby FDK."
|
20
|
+
# Respond with modified event
|
21
|
+
event['data'] = se
|
22
|
+
event['extensions']['protocol'] = {
|
23
|
+
headers: {
|
24
|
+
'Content-Type' => ['application/json']
|
25
|
+
},
|
26
|
+
'status_code' => 200,
|
27
|
+
}
|
28
|
+
STDOUT.puts event.to_json
|
29
|
+
STDOUT.puts
|
30
|
+
STDOUT.flush
|
31
|
+
end
|
32
|
+
|
33
|
+
STDIN.each_line { |line| parser.parse_chunk(line) }
|
34
|
+
|
35
|
+
elsif format == 'json'
|
36
|
+
parser = Yajl::Parser.new
|
37
|
+
|
38
|
+
parser.on_parse_complete = lambda do |event|
|
39
|
+
context = Context.new(event)
|
40
|
+
body = event['body']
|
41
|
+
if context.content_type == 'application/json' && body != ''
|
42
|
+
body = Yajl::Parser.parse(body)
|
118
43
|
end
|
119
|
-
|
44
|
+
se = FDK.single_event(function: func, context: context, input: body)
|
45
|
+
response = {
|
46
|
+
headers: {
|
47
|
+
'Content-Type' => ['application/json']
|
48
|
+
},
|
49
|
+
'status_code' => 200,
|
50
|
+
body: se.to_json
|
51
|
+
}
|
52
|
+
STDOUT.puts response.to_json
|
53
|
+
STDOUT.puts
|
54
|
+
STDOUT.flush
|
55
|
+
end
|
56
|
+
|
57
|
+
STDIN.each_line { |line| parser.parse_chunk(line) }
|
120
58
|
|
121
|
-
|
122
|
-
|
123
|
-
|
59
|
+
elsif format == 'default'
|
60
|
+
event = {}
|
61
|
+
event['call_id'] = ENV['FN_CALL_ID']
|
62
|
+
event['protocol'] = {
|
63
|
+
'type' => 'http',
|
64
|
+
'request_url' => ENV['FN_REQUEST_URL']
|
65
|
+
}
|
66
|
+
c = Context.new(event)
|
67
|
+
puts FDK.single_event(function: func, context: c, input: STDIN.read).to_json
|
68
|
+
else
|
69
|
+
raise "Format '#{format}' not supported in Ruby FDK."
|
124
70
|
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.single_event(function:, context:, input:)
|
74
|
+
send function, context: context, input: input
|
75
|
+
end
|
125
76
|
end
|
data/lib/fdk/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Travis Reeder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|