meshx-plugin-sdk 0.0.1
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 +7 -0
- data/lib/sdk.rb +363 -0
- metadata +43 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9cafe1eb2bf825349ca1f92b832762ada2f7b8b0d6b28a667f5289705424670e
|
4
|
+
data.tar.gz: 50379ac299320c243787b63d10fa468161e93ba1c22b0b17f0bb408fd1e105eb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 454eff71a88b624b3f368c45a2f0a22a5cf2c85faa0614ba3269ff04ef15ae504915c20111766e62e3d5c46ee94170992e812db6355d276caf25d209c73ffba2
|
7
|
+
data.tar.gz: d2a84168b1f70e0f451743bbe14d0398530d31c386784919c6103b77f7c804e71fa05c6697b427c615cb1f3ab1cbe487dde06375621d421da398d45b7a3f7394
|
data/lib/sdk.rb
ADDED
@@ -0,0 +1,363 @@
|
|
1
|
+
require "ffi"
|
2
|
+
require "base64"
|
3
|
+
require "json"
|
4
|
+
require "logger"
|
5
|
+
require "base64"
|
6
|
+
require "uri"
|
7
|
+
require "open3"
|
8
|
+
|
9
|
+
### sdk start
|
10
|
+
module GoApi
|
11
|
+
extend FFI::Library
|
12
|
+
ffi_lib "./foundation-api.so"
|
13
|
+
|
14
|
+
class Example < FFI::Struct
|
15
|
+
# This must be completely in sync with the C struct defined in Go code.
|
16
|
+
layout :id, :int, :prefix, :pointer
|
17
|
+
|
18
|
+
def initialize(prefix, id)
|
19
|
+
self[:prefix] = FFI::MemoryPointer.from_string(prefix)
|
20
|
+
self[:id] = id
|
21
|
+
end
|
22
|
+
|
23
|
+
# This feels convoluted, but it hides the fact that our function is loaded
|
24
|
+
# outside of the "struct mirror" class.
|
25
|
+
def greet
|
26
|
+
Portal.greet(self)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
attach_function :send_file_event, [:string, :string, :string, :string], :strptr
|
31
|
+
attach_function :get_messages, [], :strptr
|
32
|
+
attach_function :send_message, [:string], :strptr
|
33
|
+
attach_function :file_cache_write, [:string], :strptr
|
34
|
+
attach_function :file_cache_read, [:string, :string], :strptr
|
35
|
+
attach_function :file_cache_read, [:string, :string], :strptr
|
36
|
+
attach_function :send_complete_events, [], :strptr
|
37
|
+
attach_function :send_folder_event, [:string, :string, :string, :string], :strptr
|
38
|
+
end
|
39
|
+
|
40
|
+
module Utils
|
41
|
+
class Subprocess
|
42
|
+
def initialize(cmd, &block)
|
43
|
+
Open3.popen3(cmd) do |stdin, stdout, stderr, thread|
|
44
|
+
{ :out => stdout, :err => stderr }.each do |key, stream|
|
45
|
+
Thread.new do
|
46
|
+
until (line = stream.gets).nil?
|
47
|
+
if key == :out
|
48
|
+
yield line, nil, thread if block_given?
|
49
|
+
else
|
50
|
+
yield nil, line, thread if block_given?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
thread.join # don't exit until the external process is done
|
56
|
+
exit_code = thread.value
|
57
|
+
if (exit_code != 0)
|
58
|
+
puts("Failed to execute_cmd #{cmd} exit code: #{exit_code}")
|
59
|
+
Kernel.exit(false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Helper
|
67
|
+
def self.run(cmd, chdir = File.dirname(__FILE__))
|
68
|
+
puts("run: #{cmd}")
|
69
|
+
Utils::Subprocess.new cmd do |stdout, stderr, thread|
|
70
|
+
puts "\t#{stdout}"
|
71
|
+
if (stderr.nil? == false)
|
72
|
+
puts "\t#{stderr}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.get_env(name, default)
|
78
|
+
if "#{ENV[name]}" == ""
|
79
|
+
return default
|
80
|
+
end
|
81
|
+
return ENV[name]
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.get_env_or_fail(name)
|
85
|
+
val = Helper.get_env(name, "")
|
86
|
+
if val == ""
|
87
|
+
puts("expected environment variable not set: #{name}")
|
88
|
+
exit(1)
|
89
|
+
end
|
90
|
+
return val
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.valid_json?(json)
|
94
|
+
JSON.parse(json)
|
95
|
+
true
|
96
|
+
rescue JSON::ParserError, TypeError => e
|
97
|
+
false
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.make_events_hash(b64event)
|
101
|
+
if "#{b64event}" == ""
|
102
|
+
puts("missing event data")
|
103
|
+
exit(1)
|
104
|
+
end
|
105
|
+
events = Base64.decode64(b64event)
|
106
|
+
|
107
|
+
if Helper.valid_json?(events) == false
|
108
|
+
puts("invalid event data")
|
109
|
+
exit(1)
|
110
|
+
end
|
111
|
+
eventsHash = JSON.parse(events)
|
112
|
+
return eventsHash
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class Controller
|
117
|
+
def initialize(plugin)
|
118
|
+
@api = FoundationApi.new()
|
119
|
+
@log = Logger.new(STDOUT)
|
120
|
+
@config = Config.new()
|
121
|
+
@plugin = Plugin.new(@api, @log, @config)
|
122
|
+
end
|
123
|
+
|
124
|
+
def run()
|
125
|
+
keep_reading = true
|
126
|
+
@log.info("starting controller loop")
|
127
|
+
while keep_reading
|
128
|
+
rtn = @api.get_messages()
|
129
|
+
@log.info("rtn: #{rtn.message} #{rtn.error} #{rtn.exit_code}")
|
130
|
+
# convert message to fileevent
|
131
|
+
hash = JSON.parse(rtn.message)
|
132
|
+
hash["items"].each do |item|
|
133
|
+
@log.info("message kind: #{item["kind"]}")
|
134
|
+
case item["kind"]
|
135
|
+
when "FileEvent"
|
136
|
+
@log.info("FileEvent")
|
137
|
+
event = FileEvent.new(item)
|
138
|
+
@plugin.on_file_event(event)
|
139
|
+
when "FolderEvent"
|
140
|
+
@log.info("FolderEvent")
|
141
|
+
event = FolderEvent.new(item)
|
142
|
+
@plugin.on_folder_event(event)
|
143
|
+
when "CompleteEvent"
|
144
|
+
@log.info("CompleteEvent")
|
145
|
+
event = CompleteEvent.new(item)
|
146
|
+
@plugin.on_complete_event(event)
|
147
|
+
keep_reading = false
|
148
|
+
else
|
149
|
+
@log.info("unknown event kind: #{item["kind"]}")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
@log.info("ending controller loop sending complete event")
|
154
|
+
res2 = @api.send_complete_events()
|
155
|
+
if res2.exit_code != 0
|
156
|
+
@log.error("failed to send complete event: #{res2.error} #{res2.exit_code}")
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class Response
|
162
|
+
attr_accessor :payload, :error, :exit_code
|
163
|
+
|
164
|
+
def initialize(payload, error, exit_code)
|
165
|
+
@payload = payload
|
166
|
+
@error = error
|
167
|
+
@exit_code = exit_code
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class FileWriteResult
|
172
|
+
attr_accessor :destination, :error, :exit_code
|
173
|
+
|
174
|
+
def initialize(response)
|
175
|
+
@error = response.error
|
176
|
+
@exit_code = response.exit_code
|
177
|
+
hash = JSON.parse(response.payload)
|
178
|
+
@destination = hash["destination"]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
class MetaData
|
183
|
+
attr_accessor :name, :created, :id, :runid, :tags, :label
|
184
|
+
|
185
|
+
def initialize(hash)
|
186
|
+
@name = hash["name"]
|
187
|
+
@created = hash["created"]
|
188
|
+
@id = hash["id"]
|
189
|
+
@runid = hash["runid"]
|
190
|
+
@tags = hash["tags"]
|
191
|
+
@label = hash["label"]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
class FolderEvent
|
196
|
+
attr_accessor :kind, :version, :metadata, :origin, :path, :folder, :originalpath, :origin
|
197
|
+
|
198
|
+
def initialize(hash)
|
199
|
+
@kind = hash["kind"]
|
200
|
+
@version = hash["version"]
|
201
|
+
@metadata = MetaData.new(hash["metadata"])
|
202
|
+
@origin = hash["origin"]
|
203
|
+
@path = hash["path"]
|
204
|
+
@folder = hash["folder"]
|
205
|
+
@originalpath = hash["originalpath"]
|
206
|
+
@origin = hash["origin"]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
class FileEvent
|
211
|
+
attr_accessor :kind, :version, :metadata, :origin, :path, :filename, :originalpath, :origin
|
212
|
+
|
213
|
+
def initialize(hash)
|
214
|
+
@kind = hash["kind"]
|
215
|
+
@version = hash["version"]
|
216
|
+
@metadata = MetaData.new(hash["metadata"])
|
217
|
+
@origin = hash["origin"]
|
218
|
+
@path = hash["path"]
|
219
|
+
@filename = hash["filename"]
|
220
|
+
@originalpath = hash["originalpath"]
|
221
|
+
@origin = hash["origin"]
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
class FileReadResult
|
226
|
+
attr_accessor :error, :exit_code
|
227
|
+
|
228
|
+
def initialize(response)
|
229
|
+
@error = response.error
|
230
|
+
@exit_code = response.exit_code
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
class GetMessageResult
|
235
|
+
attr_accessor :message, :error, :exit_code
|
236
|
+
|
237
|
+
def initialize(response)
|
238
|
+
@error = response.error
|
239
|
+
@exit_code = response.exit_code
|
240
|
+
@message = response.payload
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
class SendMessageResult
|
245
|
+
attr_accessor :message, :error, :exit_code
|
246
|
+
|
247
|
+
def initialize(response)
|
248
|
+
@error = response.error
|
249
|
+
@exit_code = response.exit_code
|
250
|
+
@message = response.payload
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
class SendFolderResult
|
255
|
+
attr_accessor :message, :error, :exit_code
|
256
|
+
|
257
|
+
def initialize(response)
|
258
|
+
@error = response.error
|
259
|
+
@exit_code = response.exit_code
|
260
|
+
@message = response.payload
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
class SendCompleteResult
|
265
|
+
attr_accessor :message, :error, :exit_code
|
266
|
+
|
267
|
+
def initialize(response)
|
268
|
+
@error = response.error
|
269
|
+
@exit_code = response.exit_code
|
270
|
+
@message = response.payload
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
class Config
|
275
|
+
def initialize()
|
276
|
+
@config_path = Helper.get_env("X_CONFIG", "/etc/plugin/config.json")
|
277
|
+
@config = load()
|
278
|
+
end
|
279
|
+
|
280
|
+
def load()
|
281
|
+
file = File.read(@config_path)
|
282
|
+
config = JSON.parse(file)
|
283
|
+
return config
|
284
|
+
end
|
285
|
+
|
286
|
+
def get(name)
|
287
|
+
rtn = @config[name]
|
288
|
+
if rtn == ""
|
289
|
+
puts("plugin configuration is not valid, missing: #{name}")
|
290
|
+
exit(2)
|
291
|
+
end
|
292
|
+
return rtn
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
class FoundationApi
|
297
|
+
def initialize()
|
298
|
+
end
|
299
|
+
|
300
|
+
def pase_response(response)
|
301
|
+
data = JSON.parse(response)
|
302
|
+
|
303
|
+
rtn = Response.new(data["payload"], data["error"], data["exit_code"])
|
304
|
+
return rtn
|
305
|
+
end
|
306
|
+
|
307
|
+
def display_response(response)
|
308
|
+
puts("payload: #{response.payload}")
|
309
|
+
puts("error: #{response.error}")
|
310
|
+
puts("exit_code: #{response.exit_code}")
|
311
|
+
end
|
312
|
+
|
313
|
+
def get_messages()
|
314
|
+
d, e = GoApi.get_messages()
|
315
|
+
parsed = pase_response(d)
|
316
|
+
display_response(parsed)
|
317
|
+
return GetMessageResult.new(parsed)
|
318
|
+
end
|
319
|
+
|
320
|
+
def send_message(data)
|
321
|
+
d, e = GoApi.send_message(data)
|
322
|
+
parsed = pase_response(d)
|
323
|
+
display_response(parsed)
|
324
|
+
return SendMessageResult.new(parsed)
|
325
|
+
end
|
326
|
+
|
327
|
+
def send_file_event(path, filename, originalpath, origin)
|
328
|
+
d, e = GoApi.send_file_event(path, filename, originalpath, origin)
|
329
|
+
parsed = pase_response(d)
|
330
|
+
display_response(parsed)
|
331
|
+
return SendMessageResult.new(parsed)
|
332
|
+
end
|
333
|
+
|
334
|
+
def send_folder_event(path, folder, originalpath, origin)
|
335
|
+
d, e = GoApi.send_folder_event(path, folder, originalpath, origin)
|
336
|
+
parsed = pase_response(d)
|
337
|
+
display_response(parsed)
|
338
|
+
return SendFolderResult.new(parsed)
|
339
|
+
end
|
340
|
+
|
341
|
+
def file_cache_read(uri, destination)
|
342
|
+
d, e = GoApi.file_cache_read(uri, destination)
|
343
|
+
parsed = pase_response(d)
|
344
|
+
display_response(parsed)
|
345
|
+
return FileReadResult.new(parsed)
|
346
|
+
end
|
347
|
+
|
348
|
+
def file_cache_write(filename)
|
349
|
+
d, e = GoApi.file_cache_write(filename)
|
350
|
+
parsed = pase_response(d)
|
351
|
+
display_response(parsed)
|
352
|
+
return FileWriteResult.new(parsed)
|
353
|
+
end
|
354
|
+
|
355
|
+
def send_complete_events()
|
356
|
+
d, e = GoApi.send_complete_events()
|
357
|
+
parsed = pase_response(d)
|
358
|
+
display_response(parsed)
|
359
|
+
return SendCompleteResult.new(parsed)
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
### sdk end
|
metadata
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: meshx-plugin-sdk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Meshx
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2010-04-03 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: 'A '
|
14
|
+
email: owain@surfncode.io
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/sdk.rb
|
20
|
+
homepage: http://meshx
|
21
|
+
licenses:
|
22
|
+
- MIT
|
23
|
+
metadata: {}
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
requirements: []
|
39
|
+
rubygems_version: 3.3.26
|
40
|
+
signing_key:
|
41
|
+
specification_version: 3
|
42
|
+
summary: meshx-plugin-sdk
|
43
|
+
test_files: []
|