cantemo-portal-agent 1.0.9 → 1.1.0
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/exe/cantemo-portal-agent +8 -6
- data/lib/cantemo/portal/agent/WatchFolderUtility/foreman.rb +59 -0
- data/lib/cantemo/portal/agent/cli/commands/watch_folders-working.rb +237 -0
- data/lib/cantemo/portal/agent/cli/commands/watch_folders.rb +63 -0
- data/lib/cantemo/portal/agent/version.rb +1 -1
- data/lib/envoi/aspera/watch_service/client.rb +397 -0
- data/lib/envoi/aspera/watch_service/snapshot.rb +11 -0
- data/lib/envoi/aspera/watch_service/subscription.rb +0 -0
- data/lib/envoi/aspera/watch_service/watch_folder.rb +322 -0
- data/lib/envoi/mam/agent/cli/commands/cantemo-agent.rb +62 -0
- data/lib/envoi/mam/agent/cli/commands/cantemo-watch_folders.rb +41 -0
- data/lib/envoi/mam/agent/cli/commands/cantemo.rb +5 -0
- data/lib/envoi/mam/agent/cli/commands/iconik.rb +21 -11
- data/lib/envoi/mam/agent/cli/commands/mediasilo.rb +1 -1
- data/lib/envoi/mam/agent/cli/commands/vidispine.rb +7 -4
- data/lib/envoi/mam/agent/cli/commands/wiredrive.rb +15 -2
- data/lib/envoi/mam/agent/cli/commands.rb +4 -4
- data/lib/envoi/mam/agent/cli.rb +3 -3
- data/lib/envoi/mam/agent/transfer_client/aspera.rb +145 -7
- data/lib/envoi/mam/agent/version.rb +1 -1
- data/lib/envoi/mam/agent/watch_folder_utility/foreman.rb +76 -0
- data/lib/envoi/mam/agent.rb +6 -1
- data/lib/envoi/mam/cantemo/agent/watch_folder_handler-working.rb +111 -0
- data/lib/envoi/mam/cantemo/agent/watch_folder_handler.rb +176 -0
- data/lib/envoi/mam/cantemo/agent/watch_folder_handler_aspera.rb +112 -0
- data/lib/envoi/mam/cantemo/agent.rb +288 -0
- data/lib/envoi/mam/iconik/agent.rb +15 -3
- data/lib/envoi/mam/vidispine/agent.rb +6 -1
- data/lib/envoi/watch_folder_utility/watch_folder/handler/listen.rb +189 -0
- metadata +48 -4
@@ -0,0 +1,397 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'logger'
|
3
|
+
require 'open3'
|
4
|
+
require 'shellwords'
|
5
|
+
|
6
|
+
module Envoi
|
7
|
+
module Aspera
|
8
|
+
module WatchService
|
9
|
+
|
10
|
+
class Client
|
11
|
+
|
12
|
+
attr_accessor :logger, :initial_args, :config
|
13
|
+
|
14
|
+
attr_accessor :aswatchadmin_executable_path, :default_username
|
15
|
+
|
16
|
+
DEFAULT_ASWATCHADMIN_EXECUTABLE_PATH = '/Library/Aspera/bin/aswatchadmin'
|
17
|
+
|
18
|
+
DAEMON_NAME_FIELD_NAME = 'name'
|
19
|
+
DAEMON_CONFIGURATION_FIELD_NAME = 'configuration'
|
20
|
+
|
21
|
+
DAEMONS_QUERY_LINE_PART_TO_SUB = 'configuration: '
|
22
|
+
DAEMONS_QUERY_LINE_START = "#{DAEMONS_QUERY_LINE_PART_TO_SUB} {"
|
23
|
+
|
24
|
+
class Expressions
|
25
|
+
SNAPSHOT_CREATE_VERSION_PARSE = /(?<version>\d*)\.$/
|
26
|
+
SNAPSHOT_PRINT_PARSE = /^\s{2}(?<path>.*), (?<stat_as_json>\{"ino":\d+,.*})$/
|
27
|
+
SUBSCRIPTION_CREATE_PARSE = /(?<json>\{.*\})\s*$/
|
28
|
+
SUBSCRIPTION_RESUBSCRIBE_SUCCESS_PARSE = /^\[aswatchadmin resubscribe\] Successfully resubscribed subscription '[^']*'\.$/
|
29
|
+
SNAPSHOT_DIFFERENTIAL_PARSE = /^event\=(?<event>[^\,]*),path\=(?<path>.*),stat\=\[type\=(?<stat_type>[A-Z_]*),(?<change>[^\]]*)\]$/
|
30
|
+
end
|
31
|
+
|
32
|
+
class SnapshotEntry < Hash
|
33
|
+
|
34
|
+
def initialize(data)
|
35
|
+
# @attributes = data.is_a?(MatchData) ? { path: data[:path], stat_as_json: data[:stat_as_json] } : data
|
36
|
+
merge! data
|
37
|
+
end
|
38
|
+
|
39
|
+
def path; self[:path] end
|
40
|
+
|
41
|
+
def stat
|
42
|
+
self[:stat] ||= begin
|
43
|
+
json = self[:stat_as_json]
|
44
|
+
JSON.parse(json) if json
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def stat_as_json; self[:stat_as_json] end
|
49
|
+
|
50
|
+
if MatchData.method_defined?(:named_captures)
|
51
|
+
def self.new_from_match_data(match_data)
|
52
|
+
new(match_data.named_captures)
|
53
|
+
end
|
54
|
+
else
|
55
|
+
def self.new_from_match_data(match_data)
|
56
|
+
new(Hash[match_data.names.map(&:to_sym).zip(match_data.captures)])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.current_os_type
|
62
|
+
case RUBY_PLATFORM
|
63
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
64
|
+
return :windows
|
65
|
+
when /darwin|mac os/
|
66
|
+
return :mac
|
67
|
+
else # unix family
|
68
|
+
return :unix
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.detect_executable
|
73
|
+
executable_name = 'aswatchadmin'
|
74
|
+
paths = case current_os_type
|
75
|
+
when :windows
|
76
|
+
executable_name += '.exe'
|
77
|
+
[
|
78
|
+
File.join(ENV['LOCALAPPDATA'], 'Aspera', 'bin', executable_name)
|
79
|
+
]
|
80
|
+
when :mac
|
81
|
+
[
|
82
|
+
"/Library/Aspera/bin/#{executable_name}",
|
83
|
+
]
|
84
|
+
else
|
85
|
+
[
|
86
|
+
File.join("/opt/aspera/bin/#{executable_name}")
|
87
|
+
]
|
88
|
+
end
|
89
|
+
paths.find { |p| File.executable?(p) }
|
90
|
+
end
|
91
|
+
|
92
|
+
def initialize(args = {})
|
93
|
+
@initial_args = args.clone
|
94
|
+
initialize_logger(args)
|
95
|
+
|
96
|
+
@config = args[:config]
|
97
|
+
|
98
|
+
@aswatchadmin_executable_path = args[:aswatchadmin_executable_path] ||
|
99
|
+
self.class.detect_executable ||
|
100
|
+
DEFAULT_ASWATCHADMIN_EXECUTABLE_PATH
|
101
|
+
@default_daemon_name = args[:default_daemon_name] || args[:daemon_name] || default_daemon_name_get
|
102
|
+
@dry_run = args.fetch(:dry_run, false)
|
103
|
+
end
|
104
|
+
|
105
|
+
def initialize_logger(args = {})
|
106
|
+
@logger = args[:logger] || Logger.new(STDOUT)
|
107
|
+
end
|
108
|
+
|
109
|
+
def dry_run?;
|
110
|
+
@dry_run
|
111
|
+
end
|
112
|
+
|
113
|
+
def shell_execute(command, dry_run = @dry_run)
|
114
|
+
command = command.shelljoin if command.is_a?(Array)
|
115
|
+
if dry_run
|
116
|
+
logger.debug { "Skipping Execution of Command: '#{command}' " }
|
117
|
+
return
|
118
|
+
end
|
119
|
+
logger.debug { "Executing Command: '#{command}'" }
|
120
|
+
|
121
|
+
response = ''
|
122
|
+
Open3.popen3(command) do |stdin, stdout, stderr, thread|
|
123
|
+
# stdin.sync = true
|
124
|
+
# stdout.sync = true
|
125
|
+
# stderr.sync = true
|
126
|
+
output = ''
|
127
|
+
loop do
|
128
|
+
output << stdout.read #rescue nil
|
129
|
+
output << stderr.read # rescue nil
|
130
|
+
unless output.empty?
|
131
|
+
# print output
|
132
|
+
response << output.dup
|
133
|
+
output.clear
|
134
|
+
end
|
135
|
+
break if thread.stop?
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
logger.debug { "RESPONSE: #{response.empty? ? '' : "\n#{response}"}" }
|
140
|
+
response
|
141
|
+
end
|
142
|
+
|
143
|
+
# @return [Hash]
|
144
|
+
def default_daemon_get
|
145
|
+
daemons = daemons_query
|
146
|
+
return nil unless daemons.length == 1
|
147
|
+
default_daemon = daemons.first
|
148
|
+
end
|
149
|
+
|
150
|
+
# @return [String|nil]
|
151
|
+
def default_daemon_name_get
|
152
|
+
_default_daemon = default_daemon_get
|
153
|
+
return nil unless _default_daemon
|
154
|
+
_default_daemon[DAEMON_NAME_FIELD_NAME]
|
155
|
+
end
|
156
|
+
|
157
|
+
# @return [Array]
|
158
|
+
def daemons_query(args = {})
|
159
|
+
command = [aswatchadmin_executable_path, 'query-daemons']
|
160
|
+
response = shell_execute(command)
|
161
|
+
|
162
|
+
return response unless args.fetch(:parse_response, true)
|
163
|
+
|
164
|
+
daemons_query_response_parse(response)
|
165
|
+
end
|
166
|
+
|
167
|
+
# @return [Array[Hash]]
|
168
|
+
def daemons_query_response_parse(response)
|
169
|
+
response_ary = response.split("\n")
|
170
|
+
first_line = response_ary.shift
|
171
|
+
daemon = nil
|
172
|
+
daemons = response_ary.each_with_object([]) do |line, _daemons|
|
173
|
+
_line = line.strip
|
174
|
+
|
175
|
+
if _line.start_with?(DAEMONS_QUERY_LINE_START)
|
176
|
+
configuration_json = _line.sub(DAEMONS_QUERY_LINE_PART_TO_SUB, '')
|
177
|
+
configuration = JSON.parse(configuration_json)
|
178
|
+
daemon[DAEMON_CONFIGURATION_FIELD_NAME] = configuration
|
179
|
+
else
|
180
|
+
_daemons << daemon if daemon
|
181
|
+
daemon_name = _line
|
182
|
+
daemon = { DAEMON_NAME_FIELD_NAME => daemon_name }
|
183
|
+
end
|
184
|
+
end
|
185
|
+
daemons << daemon if daemon
|
186
|
+
end
|
187
|
+
|
188
|
+
def subscription_create(args = {})
|
189
|
+
daemon_name = args[:daemon_name] || args[:daemon] || @default_daemon_name
|
190
|
+
raise ArgumentError, 'Missing argument for required parameter daemon_name' unless daemon_name
|
191
|
+
|
192
|
+
watch_folder_path = args[:watch_folder_path]
|
193
|
+
raise ArgumentError, 'Missing argument for required parameter watch_folder_path' unless watch_folder_path
|
194
|
+
|
195
|
+
scan_period = args[:scan_period]
|
196
|
+
expire_in = args[:expire_in]
|
197
|
+
|
198
|
+
command = [aswatchadmin_executable_path, 'subscribe', daemon_name, watch_folder_path]
|
199
|
+
command << '--scan-period' << scan_period if scan_period
|
200
|
+
command << '--expire_in' << expire_in if expire_in
|
201
|
+
response = shell_execute(command)
|
202
|
+
|
203
|
+
return response unless args.fetch(:parse_response, true)
|
204
|
+
|
205
|
+
subscription_create_response_parse(response)
|
206
|
+
end
|
207
|
+
|
208
|
+
# @param [Object] response
|
209
|
+
# @return [Object]
|
210
|
+
def subscription_create_response_parse(response)
|
211
|
+
subscription_json_match = Expressions::SUBSCRIPTION_CREATE_PARSE.match(response)
|
212
|
+
raise "Failed to parse new subscription information from response. '#{response}'" unless subscription_json_match
|
213
|
+
subscription_json = subscription_json_match.to_s
|
214
|
+
subscription = JSON.parse(subscription_json)
|
215
|
+
end
|
216
|
+
|
217
|
+
def subscription_resubscribe(args = {})
|
218
|
+
daemon_name = args[:daemon_name] || args[:daemon] || @default_daemon_name
|
219
|
+
raise ArgumentError, 'Missing argument for required parameter daemon_name' unless daemon_name
|
220
|
+
|
221
|
+
subscription_id = args[:subscription_id]
|
222
|
+
raise ArgumentError, 'Missing argument for required parameter subscription_id' unless subscription_id
|
223
|
+
|
224
|
+
command = [aswatchadmin_executable_path, 'resubscribe', daemon_name, subscription_id]
|
225
|
+
response = shell_execute(command)
|
226
|
+
|
227
|
+
return response unless args.fetch(:parse_response, true)
|
228
|
+
|
229
|
+
subscription_resubscribe_parse_response(response)
|
230
|
+
end
|
231
|
+
|
232
|
+
def subscription_resubscribe_parse_response(response)
|
233
|
+
raise response unless Expressions::SUBSCRIPTION_RESUBSCRIBE_SUCCESS_PARSE.match(response)
|
234
|
+
true
|
235
|
+
end
|
236
|
+
|
237
|
+
# Create a snapshot using the subscription
|
238
|
+
#
|
239
|
+
# ```
|
240
|
+
# $ /Library/Aspera/bin/aswatchadmin create-snapshot jw f090e8b5-d9e2-474b-acb1-68c4f76c8c53
|
241
|
+
# [aswatchadmin create-snapshot] Successfully created snapshot 0.
|
242
|
+
# ```
|
243
|
+
def subscription_snapshot_create(args = {})
|
244
|
+
daemon_name = args[:daemon_name] || args[:daemon] || @default_daemon_name
|
245
|
+
raise ArgumentError, 'Missing argument for required parameter daemon_name' unless daemon_name
|
246
|
+
|
247
|
+
subscription_id = args[:subscription_id]
|
248
|
+
raise ArgumentError, 'Missing argument for required parameter subscription_id' unless subscription_id
|
249
|
+
|
250
|
+
command = [aswatchadmin_executable_path, 'create-snapshot', daemon_name, subscription_id]
|
251
|
+
response = shell_execute(command)
|
252
|
+
|
253
|
+
return response unless args.fetch(:parse_response, true)
|
254
|
+
|
255
|
+
subscription_snapshot_create_response_parse(response)
|
256
|
+
end
|
257
|
+
|
258
|
+
def subscription_snapshot_create_response_parse(response)
|
259
|
+
snapshot_version = Expressions::SNAPSHOT_CREATE_VERSION_PARSE.match(response)
|
260
|
+
raise "Failed to parse snapshot version from response. '#{response}'" unless snapshot_version
|
261
|
+
snapshot_version
|
262
|
+
end
|
263
|
+
|
264
|
+
def subscription_snapshot_differential(args = {})
|
265
|
+
daemon_name = args[:daemon_name] || args[:daemon] || @default_daemon_name
|
266
|
+
raise ArgumentError, 'Missing argument for required parameter daemon_name' unless daemon_name
|
267
|
+
|
268
|
+
subscription_id = args[:subscription_id]
|
269
|
+
raise ArgumentError, 'Missing argument for required parameter subscription_id' unless subscription_id
|
270
|
+
|
271
|
+
from = args[:from]
|
272
|
+
|
273
|
+
to = args[:to]
|
274
|
+
|
275
|
+
path = args[:path]
|
276
|
+
identifier = args[:identifier]
|
277
|
+
format = args[:format]
|
278
|
+
escape = args[:escape]
|
279
|
+
exclude_create = args[:exclude_create]
|
280
|
+
exclude_modify = args[:exclude_modify]
|
281
|
+
exclude_remove = args[:exclude_remove]
|
282
|
+
leafs_only = args[:leafs_only]
|
283
|
+
|
284
|
+
command = [aswatchadmin_executable_path, 'snapshot-differential', daemon_name, subscription_id]
|
285
|
+
command << from if from
|
286
|
+
command << to if to
|
287
|
+
command << '--path' << path if path && !path.empty?
|
288
|
+
command << '--identifier' << identifier if identifier && !identifier.empty?
|
289
|
+
command << '--format' << format if format && !format.empty?
|
290
|
+
command << '--escape' << escape if escape && !escape.empty?
|
291
|
+
command << '--exclude_create' if exclude_create
|
292
|
+
command << '--exclude_modify' if exclude_modify
|
293
|
+
command << '--exclude-remove' if exclude_remove
|
294
|
+
command << '--leafs-only' if leafs_only
|
295
|
+
response = shell_execute(command)
|
296
|
+
|
297
|
+
return response unless args.fetch(:parse_response, true)
|
298
|
+
|
299
|
+
subscription_snapshot_differential_response_parse(response)
|
300
|
+
end
|
301
|
+
|
302
|
+
def subscription_snapshot_differential_response_parse(response)
|
303
|
+
response.split.map do |v|
|
304
|
+
m = v.match(Expressions::SNAPSHOT_DIFFERENTIAL_PARSE)
|
305
|
+
m ? Hash[m.names.zip(m.captures)] : v
|
306
|
+
end.join('\n')
|
307
|
+
end
|
308
|
+
|
309
|
+
def subscription_snapshot_print(args = {})
|
310
|
+
daemon_name = args[:daemon_name] || args[:daemon] || @default_daemon_name
|
311
|
+
raise ArgumentError, 'Missing argument for required parameter daemon_name' unless daemon_name
|
312
|
+
|
313
|
+
subscription_id = args[:subscription_id]
|
314
|
+
raise ArgumentError, 'Missing argument for required parameter subscription_id' unless subscription_id
|
315
|
+
|
316
|
+
snapshot_version = args[:snapshot_version]
|
317
|
+
command = [aswatchadmin_executable_path, 'print-snapshot', daemon_name, subscription_id]
|
318
|
+
command << '--snapshot' << snapshot_version if snapshot_version
|
319
|
+
|
320
|
+
response = shell_execute(command)
|
321
|
+
|
322
|
+
return response unless args.fetch(:parse_response, false)
|
323
|
+
|
324
|
+
subscription_snapshot_print_response_parse(response)
|
325
|
+
end
|
326
|
+
|
327
|
+
def subscription_snapshot_print_response_parse(response)
|
328
|
+
response
|
329
|
+
.to_enum(:scan, Expressions::SNAPSHOT_PRINT_PARSE)
|
330
|
+
.map { SnapshotEntry.new_from_match_data(Regexp.last_match) }
|
331
|
+
end
|
332
|
+
|
333
|
+
def subscription_snapshot_entries_get(args = { })
|
334
|
+
response = subscription_snapshot_print(args)
|
335
|
+
subscription_snapshot_print_response_parse(response)
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
# List subscriptions for a specific daemon
|
340
|
+
# @see https://download.asperasoft.com/download/docs/entsrv/3.8.1/cs_admin_osx/webhelp/index.html#dita-watchfolder/watchd_subscriptions.html
|
341
|
+
def subscriptions_get(args = {})
|
342
|
+
daemon_name = args[:daemon_name] || args[:daemon] || @default_daemon_name
|
343
|
+
raise ArgumentError, 'Missing argument for required parameter daemon_name' unless daemon_name
|
344
|
+
|
345
|
+
command = [aswatchadmin_executable_path, 'query-subscriptions', daemon_name]
|
346
|
+
response = shell_execute(command)
|
347
|
+
|
348
|
+
return response unless args.fetch(:parse_response, true)
|
349
|
+
|
350
|
+
subscriptions_get_response_parse(response)
|
351
|
+
end
|
352
|
+
|
353
|
+
def subscriptions_get_response_parse(response)
|
354
|
+
response_json = "[#{response.split.join(",\n")}]"
|
355
|
+
subscriptions = JSON.parse(response_json)
|
356
|
+
end
|
357
|
+
|
358
|
+
# Unsubscribe from a watch
|
359
|
+
#
|
360
|
+
# $ /Library/Aspera/bin/aswatchadmin unsubscribe daemonname 3b758f2d-97f9-4054-80d5-ed67dcaa8daa
|
361
|
+
# [aswatchadmin unsubscribe] Successfully unsubscribed subscription '3b758f2d-97f9-4054-80d5-ed67dcaa8daa' from daemon 'daemonname'.
|
362
|
+
#
|
363
|
+
# @see https://download.asperasoft.com/download/docs/entsrv/3.8.1/cs_admin_osx/webhelp/index.html#dita-watchfolder/watchd_subscriptions.html
|
364
|
+
def subscription_unsubscribe(args = {})
|
365
|
+
daemon_name = args[:daemon_name] || args[:daemon] || @default_daemon_name
|
366
|
+
raise ArgumentError, 'Missing argument for required parameter daemon_name' unless daemon_name
|
367
|
+
|
368
|
+
subscription_id = args[:subscription_id]
|
369
|
+
raise ArgumentError, 'Missing argument for required parameter subscription_id' unless subscription_id
|
370
|
+
|
371
|
+
command = [aswatchadmin_executable_path, 'unsubscribe', daemon_name, subscription_id]
|
372
|
+
response = shell_execute(command)
|
373
|
+
end
|
374
|
+
|
375
|
+
def subscriptions_unsubscribe_all(args = {})
|
376
|
+
subscriptions = subscriptions_get(args)
|
377
|
+
args_out = args.dup
|
378
|
+
path = args[:path]
|
379
|
+
subscriptions.each do |subscription|
|
380
|
+
next unless subscription['path'] == path if path
|
381
|
+
subscription_id = subscription['identifier']
|
382
|
+
args_out[:subscription_id] = subscription_id
|
383
|
+
subscription_unsubscribe(args_out)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
def subscription_find_for_path(args = {})
|
388
|
+
path = args[:path]
|
389
|
+
subscriptions = args[:subscriptions] || subscriptions_get(args)
|
390
|
+
subscriptions.keep_if { |s| s['path'] =~ /(?:\w|-)*:\/{2,3}#{Regexp.escape(path)}/ }
|
391
|
+
end
|
392
|
+
|
393
|
+
end
|
394
|
+
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
File without changes
|