fdk 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|