fdk 0.0.14 → 0.0.15
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 +5 -5
- data/README.md +2 -0
- data/Rakefile +6 -0
- data/lib/fdk/call.rb +61 -0
- data/lib/fdk/context.rb +40 -62
- data/lib/fdk/function.rb +22 -0
- data/lib/fdk/listener.rb +68 -0
- data/lib/fdk/runner.rb +3 -131
- data/lib/fdk/support_classes.rb +21 -0
- data/lib/fdk/version.rb +1 -1
- data/lib/fdk.rb +7 -3
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 54156518eff40553f0490bcf437fa82daf307ce4
|
4
|
+
data.tar.gz: 73e6aed064fa66529f22777f8788e9292828ff90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b47e349ed1fcc96d5ab2170ad2bafeddeba810246c4457149fd160cb164e4f1dae32b8172ddff9307a11707010a3657770417e6176fe058ba267ebe21431d1bb
|
7
|
+
data.tar.gz: dc5ba5aaadb49d99ee180098700970f36b8bb258086c723c058d4a8f0718077cf6dfc9898e704fd974c4aec649ef94a310ba8fcfb32591f3bd3ef41f902e199e
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Ruby Function Developer Kit (FDK)
|
2
2
|
This provides a Ruby framework for developing functions for use with [Fn](https://fnproject.github.io).
|
3
3
|
|
4
|
+
[](https://circleci.com/gh/fnproject/fdk-ruby)
|
5
|
+
|
4
6
|
## Function Handler
|
5
7
|
To use this FDK, you simply need to require this gem.
|
6
8
|
|
data/Rakefile
CHANGED
data/lib/fdk/call.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
module FDK
|
2
|
+
# Call represents a call to the target function or lambda
|
3
|
+
class Call
|
4
|
+
FILTER_HEADERS = ["content-length", "te", "transfer-encoding",
|
5
|
+
"upgrade", "trailer"].freeze
|
6
|
+
|
7
|
+
attr_reader :request, :response
|
8
|
+
attr_accessor :error
|
9
|
+
|
10
|
+
def initialize(request:, response:)
|
11
|
+
@request = request
|
12
|
+
@response = response
|
13
|
+
end
|
14
|
+
|
15
|
+
def context
|
16
|
+
@context ||= FDK::Context.new(headers_in, headers_out)
|
17
|
+
end
|
18
|
+
|
19
|
+
def input
|
20
|
+
@input ||= ParsedInput.new(raw_input: request.body.to_s)
|
21
|
+
end
|
22
|
+
|
23
|
+
def headers_out
|
24
|
+
@headers_out ||= FDK::OutHeaders.new({}, nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
def headers_in
|
28
|
+
@headers_in ||= FDK::InHeaders.new(filtered_request_header, nil)
|
29
|
+
end
|
30
|
+
|
31
|
+
def filtered_request_header
|
32
|
+
request.header.reject { |k| FILTER_HEADERS.include? k }
|
33
|
+
end
|
34
|
+
|
35
|
+
def process
|
36
|
+
format_response_body(fn_return: yield(context: context, input: input.parsed))
|
37
|
+
good_response
|
38
|
+
rescue StandardError => e
|
39
|
+
error_response(error: e)
|
40
|
+
end
|
41
|
+
|
42
|
+
def format_response_body(fn_return:)
|
43
|
+
return response.body = fn_return.to_s unless fn_return.respond_to?(:to_json)
|
44
|
+
|
45
|
+
response.body = fn_return.to_json
|
46
|
+
response["content-type"] = "application/json" unless response["content-type"]
|
47
|
+
end
|
48
|
+
|
49
|
+
def good_response
|
50
|
+
response.status = 200
|
51
|
+
headers_out.each { |k, v| response[k] = v.join(",") }
|
52
|
+
end
|
53
|
+
|
54
|
+
def error_response(error:)
|
55
|
+
response["content-type"] = "application/json"
|
56
|
+
response.status = 502
|
57
|
+
response.body = { message: "An error occurred in the function",
|
58
|
+
detail: error.to_s }.to_json
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/fdk/context.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "date"
|
2
2
|
|
3
3
|
module FDK
|
4
|
-
|
5
4
|
# Config looks up values in the env vars
|
6
5
|
class Config
|
7
6
|
def [](key)
|
@@ -9,67 +8,59 @@ module FDK
|
|
9
8
|
end
|
10
9
|
end
|
11
10
|
|
12
|
-
|
11
|
+
# Represents inbound HTTP headers
|
13
12
|
class InHeaders
|
14
|
-
def initialize
|
15
|
-
@headers =
|
13
|
+
def initialize(headers, key_fn)
|
14
|
+
@headers = headers
|
16
15
|
@key_fn = key_fn
|
17
|
-
|
18
16
|
end
|
19
17
|
|
20
|
-
def
|
21
|
-
if @key_fn
|
22
|
-
key = @key_fn.call(key)
|
23
|
-
end
|
18
|
+
def header_key(key)
|
19
|
+
key = @key_fn.call(key) if @key_fn
|
24
20
|
key.downcase
|
25
21
|
end
|
26
22
|
|
27
23
|
def [](key)
|
28
|
-
h = @headers[
|
29
|
-
unless h.nil?
|
30
|
-
return h[0]
|
31
|
-
end
|
32
|
-
nil
|
24
|
+
h = @headers[header_key(key)]
|
25
|
+
return h[0] unless h.nil?
|
33
26
|
end
|
34
27
|
|
35
|
-
def each
|
36
|
-
@headers.each
|
28
|
+
def each(&block)
|
29
|
+
@headers.each(&block)
|
37
30
|
end
|
38
31
|
end
|
39
32
|
|
33
|
+
# Represents outbound HTTP headers
|
40
34
|
class OutHeaders < InHeaders
|
41
|
-
|
42
|
-
|
43
|
-
super(h, key_in_fn)
|
35
|
+
def initialize(headers, key_in_fn)
|
36
|
+
super(headers, key_in_fn)
|
44
37
|
end
|
45
38
|
|
46
|
-
|
47
39
|
def []=(key, value)
|
48
40
|
if value.is_a? Array
|
49
41
|
h = []
|
50
|
-
value.each {|x| h.push(x.to_s)}
|
51
|
-
@headers[
|
42
|
+
value.each { |x| h.push(x.to_s) }
|
43
|
+
@headers[header_key(key)] = h
|
52
44
|
else
|
53
|
-
@headers[
|
45
|
+
@headers[header_key(key)] = [value.to_s]
|
54
46
|
end
|
55
47
|
end
|
56
48
|
|
57
49
|
def delete(key)
|
58
|
-
@headers.delete
|
50
|
+
@headers.delete header_key(key)
|
59
51
|
end
|
60
52
|
end
|
61
53
|
|
62
|
-
|
54
|
+
# Represents the Fn context for a function execution
|
63
55
|
class Context
|
64
|
-
|
56
|
+
# FN_APP_ID -the ID of the application that this function is a member of.
|
57
|
+
# FN_APP_NAME - the name of the application.
|
65
58
|
# FN_CALL_ID - a unique ID for each function execution.
|
66
|
-
#
|
67
|
-
# 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.
|
68
|
-
# $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.
|
69
|
-
# FN_APP_NAME - the name of the application that matched this route, eg: myapp
|
70
|
-
# FN_METHOD - the HTTP method for the request, eg: GET or POST
|
59
|
+
# FN_FN_ID - the ID of this function
|
71
60
|
# FN_MEMORY - a number representing the amount of memory available to the call, in MB
|
72
|
-
|
61
|
+
# $X - any configuration values you've set for the Application.
|
62
|
+
# Replace X with the upper cased name of the config variable you set.
|
63
|
+
# e.g. minio_secret=secret will be exposed via MINIO_SECRET env var.
|
73
64
|
|
74
65
|
attr_reader :headers
|
75
66
|
attr_reader :response_headers
|
@@ -80,31 +71,28 @@ module FDK
|
|
80
71
|
@config ||= Config.new
|
81
72
|
end
|
82
73
|
|
83
|
-
|
84
74
|
def call_id
|
85
|
-
@headers[
|
75
|
+
@headers["fn-call-id"]
|
86
76
|
end
|
87
77
|
|
88
|
-
|
89
78
|
def app_id
|
90
|
-
@config[
|
79
|
+
@config["FN_APP_ID"]
|
91
80
|
end
|
92
81
|
|
93
|
-
|
94
82
|
def fn_id
|
95
|
-
@config[
|
83
|
+
@config["FN_FN_ID"]
|
96
84
|
end
|
97
85
|
|
98
86
|
def deadline
|
99
|
-
DateTime.iso8601(@headers[
|
87
|
+
DateTime.iso8601(@headers["fn-deadline"])
|
100
88
|
end
|
101
89
|
|
102
90
|
def memory
|
103
|
-
@config[
|
91
|
+
@config["FN_MEMORY"].to_i
|
104
92
|
end
|
105
93
|
|
106
94
|
def content_type
|
107
|
-
@headers[
|
95
|
+
@headers["content-type"]
|
108
96
|
end
|
109
97
|
|
110
98
|
def http_context
|
@@ -112,43 +100,33 @@ module FDK
|
|
112
100
|
end
|
113
101
|
end
|
114
102
|
|
115
|
-
|
103
|
+
# Represents the context data (inbound && outbound)
|
104
|
+
# for the execution passed as HTTP headers
|
116
105
|
class HTTPContext
|
117
|
-
|
118
106
|
attr_reader :headers
|
119
107
|
attr_reader :response_headers
|
120
108
|
|
121
109
|
def initialize(ctx)
|
122
|
-
|
110
|
+
fn_http_h_ = "fn-http-h-"
|
123
111
|
@ctx = ctx
|
124
|
-
|
125
|
-
|
126
112
|
http_headers = {}
|
127
|
-
ctx.headers.each
|
128
|
-
if k.downcase.start_with?(
|
129
|
-
|
130
|
-
http_headers[new_key] = v
|
131
|
-
end
|
132
|
-
}
|
133
|
-
|
113
|
+
ctx.headers.each do |k, v|
|
114
|
+
http_headers[k.sub(fn_http_h_, "")] = v if k.downcase.start_with?(fn_http_h_)
|
115
|
+
end
|
134
116
|
@headers = InHeaders.new(http_headers, nil)
|
135
|
-
@response_headers = OutHeaders.new(ctx.response_headers,
|
117
|
+
@response_headers = OutHeaders.new(ctx.response_headers, ->(s) { fn_http_h_ + s })
|
136
118
|
end
|
137
119
|
|
138
|
-
|
139
120
|
def request_url
|
140
|
-
@ctx.headers[
|
121
|
+
@ctx.headers["fn-http-request-url"]
|
141
122
|
end
|
142
123
|
|
143
124
|
def method
|
144
|
-
@ctx.headers[
|
125
|
+
@ctx.headers["fn-http-method"]
|
145
126
|
end
|
146
127
|
|
147
|
-
|
148
128
|
def status_code=(val)
|
149
|
-
@ctx.response_headers[
|
129
|
+
@ctx.response_headers["fn-http-status"] = val.to_i
|
150
130
|
end
|
151
|
-
|
152
131
|
end
|
153
132
|
end
|
154
|
-
|
data/lib/fdk/function.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module FDK
|
2
|
+
# Function represents a function function or lambda
|
3
|
+
class Function
|
4
|
+
attr_reader :format, :function
|
5
|
+
def initialize(function:, format:)
|
6
|
+
raise "'#{format}' not supported in Ruby FDK." unless format == "http-stream"
|
7
|
+
|
8
|
+
@format = format
|
9
|
+
@function = function
|
10
|
+
end
|
11
|
+
|
12
|
+
def as_proc
|
13
|
+
return function if function.respond_to?(:call)
|
14
|
+
|
15
|
+
->(context:, input:) { send(function, context: context, input: input) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(request:, response:)
|
19
|
+
Call.new(request: request, response: response).process(&as_proc)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/fdk/listener.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
module FDK
|
2
|
+
# Represents the socket that Fn uses to communicate
|
3
|
+
# with the FDK (and thence the function)
|
4
|
+
# To avoid Fn trying to connect to the socket before
|
5
|
+
# it's ready, the Listener creates a socket on (private_socket_path).
|
6
|
+
#
|
7
|
+
# When the socket is ready to accept connections,
|
8
|
+
# the FDK links the private_socket_path to the socket_path.
|
9
|
+
#
|
10
|
+
# Fn waits for the socket_path to be created and then connects
|
11
|
+
class Listener
|
12
|
+
attr_reader :url, :private_socket
|
13
|
+
|
14
|
+
def initialize(url:)
|
15
|
+
if url.nil? || !url.start_with?("unix:/")
|
16
|
+
raise "Missing or invalid socket URL in FN_LISTENER."
|
17
|
+
end
|
18
|
+
|
19
|
+
@url = url
|
20
|
+
@private_socket = UNIXServer.open(private_socket_path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def socket
|
24
|
+
link_socket_file unless @socket
|
25
|
+
@socket ||= private_socket
|
26
|
+
end
|
27
|
+
|
28
|
+
def link_socket_file
|
29
|
+
File.chmod(0o666, private_socket_path)
|
30
|
+
FileUtils.ln_s(File.basename(private_socket_path), socket_path)
|
31
|
+
FDK.debug "listening on #{private_socket_path}->#{socket_path}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def listen(&block)
|
35
|
+
local_socket = socket.accept
|
36
|
+
begin
|
37
|
+
raise StandardError("No block given") unless block_given?
|
38
|
+
|
39
|
+
handle_requests(socket: local_socket, fn_block: block)
|
40
|
+
rescue StandardError => e
|
41
|
+
STDERR.puts "Error in request handling #{e}"
|
42
|
+
STDERR.puts e.backtrace
|
43
|
+
end
|
44
|
+
local_socket.close
|
45
|
+
end
|
46
|
+
|
47
|
+
def handle_requests(socket:, fn_block:)
|
48
|
+
loop do
|
49
|
+
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
|
50
|
+
resp = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
|
51
|
+
req.parse(socket)
|
52
|
+
FDK.debug "got request #{req}"
|
53
|
+
fn_block.call(req, resp)
|
54
|
+
resp.send_response(socket)
|
55
|
+
FDK.debug "sending resp #{resp.status}, #{resp.header}"
|
56
|
+
break unless req.keep_alive?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def socket_path
|
61
|
+
@socket_path ||= url[5..url.length]
|
62
|
+
end
|
63
|
+
|
64
|
+
def private_socket_path
|
65
|
+
socket_path + ".private"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/fdk/runner.rb
CHANGED
@@ -7,144 +7,16 @@ require "set"
|
|
7
7
|
# Executes it with input
|
8
8
|
# Responds with output
|
9
9
|
module FDK
|
10
|
-
@filter_headers = Set["content-length", "te", "transfer-encoding",
|
11
|
-
"upgrade", "trailer"]
|
12
|
-
|
13
|
-
def self.check_format
|
14
|
-
f = ENV["FN_FORMAT"]
|
15
|
-
raise "'#{f}' not supported in Ruby FDK." unless f == "http-stream"
|
16
|
-
|
17
|
-
f
|
18
|
-
end
|
19
|
-
private_class_method :check_format
|
20
|
-
|
21
|
-
def self.listener
|
22
|
-
l = ENV["FN_LISTENER"]
|
23
|
-
if l.nil? || !l.start_with?("unix:/")
|
24
|
-
raise "Missing or invalid socket URL in FN_LISTENER."
|
25
|
-
end
|
26
|
-
|
27
|
-
l
|
28
|
-
end
|
29
|
-
private_class_method :listener
|
30
|
-
|
31
10
|
@dbg = ENV["FDK_DEBUG"]
|
32
11
|
|
33
12
|
def self.debug(msg)
|
34
13
|
STDERR.puts(msg) if @dbg
|
35
14
|
end
|
36
|
-
private_class_method :debug
|
37
15
|
|
38
16
|
def self.handle(target:)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
# When the socket is ready to accept connections,
|
43
|
-
# the FDK links the tmp_file to the socket_file.
|
44
|
-
#
|
45
|
-
# Fn waits for the socket_file to be created and then connects
|
46
|
-
check_format
|
47
|
-
l = listener
|
48
|
-
socket_file = l[5..l.length]
|
49
|
-
tmp_file = socket_file + ".tmp"
|
50
|
-
|
51
|
-
debug tmp_file
|
52
|
-
debug socket_file
|
53
|
-
UNIXServer.open(tmp_file) do |serv|
|
54
|
-
File.chmod(0o666, tmp_file)
|
55
|
-
debug "listening on #{tmp_file}->#{socket_file}"
|
56
|
-
FileUtils.ln_s(File.basename(tmp_file), socket_file)
|
57
|
-
|
58
|
-
loop do
|
59
|
-
s = serv.accept
|
60
|
-
begin
|
61
|
-
loop do
|
62
|
-
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
|
63
|
-
req.parse s
|
64
|
-
debug "got request #{req}"
|
65
|
-
resp = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
|
66
|
-
resp.status = 200
|
67
|
-
handle_call(target, req, resp)
|
68
|
-
resp.send_response s
|
69
|
-
debug "sending resp #{resp.status}, #{resp.header}"
|
70
|
-
break unless req.keep_alive?
|
71
|
-
end
|
72
|
-
rescue StandardError => e
|
73
|
-
STDERR.puts "Error in request handling #{e}"
|
74
|
-
STDERR.puts e.backtrace
|
75
|
-
end
|
76
|
-
s.close
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.set_error(resp, error)
|
82
|
-
STDERR.puts "Error in function: \"#{error}\""
|
83
|
-
STDERR.puts error.backtrace
|
84
|
-
|
85
|
-
resp["content-type"] = "application/json"
|
86
|
-
resp.status = 502
|
87
|
-
resp.body = { message: "An error occurred in the function",
|
88
|
-
detail: error.to_s }.to_json
|
89
|
-
end
|
90
|
-
private_class_method :set_error
|
91
|
-
|
92
|
-
def self.handle_call(target, req, resp)
|
93
|
-
headers = {}
|
94
|
-
req.header.map do |k, v|
|
95
|
-
headers[k] = v unless @filter_headers.include? k
|
96
|
-
end
|
97
|
-
|
98
|
-
headers_out_hash = {}
|
99
|
-
headers_out = FDK::OutHeaders.new(headers_out_hash, nil)
|
100
|
-
headers_in = FDK::InHeaders.new(headers, nil)
|
101
|
-
context = FDK::Context.new(headers_in, headers_out)
|
102
|
-
input = ParsedInput.new(raw_input: req.body.to_s)
|
103
|
-
|
104
|
-
begin
|
105
|
-
rv = if target.respond_to? :call
|
106
|
-
target.call(context: context, input: input.parsed)
|
107
|
-
else
|
108
|
-
send(target, context: context, input: input.parsed)
|
109
|
-
end
|
110
|
-
rescue StandardError => e
|
111
|
-
set_error(resp, e)
|
112
|
-
return
|
113
|
-
end
|
114
|
-
|
115
|
-
resp.status = 200
|
116
|
-
headers_out_hash.map do |k, v|
|
117
|
-
resp[k] = v.join(",") unless @filter_headers.include? k
|
118
|
-
end
|
119
|
-
|
120
|
-
# TODO: gimme a bit me flexibility on response handling
|
121
|
-
# binary, streams etc
|
122
|
-
if !rv.nil? && rv.respond_to?("to_json")
|
123
|
-
resp.body = rv.to_json
|
124
|
-
# don't override content type if already set
|
125
|
-
resp["content-type"] = "application/json" unless resp["content-type"]
|
126
|
-
else
|
127
|
-
resp.body = rv.to_s
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
# Stores raw input and can parse it as
|
132
|
-
# JSON (add extra formats as required)
|
133
|
-
class ParsedInput
|
134
|
-
attr_reader :raw
|
135
|
-
|
136
|
-
def initialize(raw_input:)
|
137
|
-
@raw = raw_input
|
138
|
-
end
|
139
|
-
|
140
|
-
def as_json
|
141
|
-
@json ||= JSON.parse(raw)
|
142
|
-
rescue JSON::ParserError
|
143
|
-
@json = false
|
144
|
-
end
|
145
|
-
|
146
|
-
def parsed
|
147
|
-
as_json || raw
|
17
|
+
func = Function.new(function: target, format: ENV["FN_FORMAT"])
|
18
|
+
Listener.new(url: ENV["FN_LISTENER"]).listen do |req, resp|
|
19
|
+
func.call(request: req, response: resp)
|
148
20
|
end
|
149
21
|
end
|
150
22
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module FDK
|
2
|
+
# ParsedInput stores raw input and can parse it as
|
3
|
+
# JSON (add extra formats as required)
|
4
|
+
class ParsedInput
|
5
|
+
attr_reader :raw
|
6
|
+
|
7
|
+
def initialize(raw_input:)
|
8
|
+
@raw = raw_input
|
9
|
+
end
|
10
|
+
|
11
|
+
def as_json
|
12
|
+
@json ||= JSON.parse(raw)
|
13
|
+
rescue JSON::ParserError
|
14
|
+
@json = false
|
15
|
+
end
|
16
|
+
|
17
|
+
def parsed
|
18
|
+
as_json || raw
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/fdk/version.rb
CHANGED
data/lib/fdk.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative
|
3
|
-
require_relative
|
1
|
+
require_relative "fdk/version"
|
2
|
+
require_relative "fdk/runner"
|
3
|
+
require_relative "fdk/context"
|
4
|
+
require_relative "fdk/call"
|
5
|
+
require_relative "fdk/listener"
|
6
|
+
require_relative "fdk/function"
|
7
|
+
require_relative "fdk/support_classes"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Travis Reeder
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-10-
|
13
|
+
date: 2018-10-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -65,8 +65,12 @@ files:
|
|
65
65
|
- README.md
|
66
66
|
- Rakefile
|
67
67
|
- lib/fdk.rb
|
68
|
+
- lib/fdk/call.rb
|
68
69
|
- lib/fdk/context.rb
|
70
|
+
- lib/fdk/function.rb
|
71
|
+
- lib/fdk/listener.rb
|
69
72
|
- lib/fdk/runner.rb
|
73
|
+
- lib/fdk/support_classes.rb
|
70
74
|
- lib/fdk/version.rb
|
71
75
|
homepage: https://github.com/fnproject/fdk-ruby
|
72
76
|
licenses:
|
@@ -88,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
92
|
version: '0'
|
89
93
|
requirements: []
|
90
94
|
rubyforge_project:
|
91
|
-
rubygems_version: 2.
|
95
|
+
rubygems_version: 2.6.14.1
|
92
96
|
signing_key:
|
93
97
|
specification_version: 4
|
94
98
|
summary: Ruby FDK for Fn Project
|