cantemo-portal-agent 1.1.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e52bfb1fe0a32298dab4b64bf2aca6f18fe0f6ab
4
- data.tar.gz: 3d442e6e485752b2dba2c7bcdaef210dd9398163
3
+ metadata.gz: b1a098feb7ef559fc883d25d942ee7f501599684
4
+ data.tar.gz: 2b90e43a0ccdd4ad7e2283b8ddb09495a15998e8
5
5
  SHA512:
6
- metadata.gz: 9bd60ea14fba7a17e322228e074e948165aebb750a264e035cf2728d68d8690158674754040ffd5e1dcf26dd4a2d89df69259b138d52f802798999b8d63f6060
7
- data.tar.gz: 9db178a801b0656b6a3e737cc904a46ec21ac2d0bc1d30380ed1ff85daa0e753ea1e66aec7309f7f32f9512000ce59f97171e569a2f4a7117e66e830550dff76
6
+ metadata.gz: 853bd438e02b10f756fb8524671c2bfa3884bf6d8fe4cfde3b189117d8681deb5f230b290ca28df524b1ce7e9ede16d07ce13044a38ac97d1ac611beea1c57f6
7
+ data.tar.gz: '078cc907795490344fa612380e21fc4f240ab6edbbf4118d7d2063ea438796564e908352c525106e865cd215d3d011e5efc7763b78d990793fb503ad2269a855'
@@ -226,10 +226,10 @@ class Watcher
226
226
  w.run
227
227
  end
228
228
 
229
- def self.run_as_daemon(args)
229
+ def self.run_as_daemon(args, options = { })
230
230
  # ARGV.unshift 'run' unless %w(start stop restart run zap killall status).include? ARGV.first
231
231
  require 'daemons'
232
- Daemons.run_proc('cantemo-portal-agent-watch-folders') { self.run(args) }
232
+ Daemons.run_proc('cantemo-portal-agent-watch-folders', options) { self.run(args) }
233
233
  end
234
234
 
235
235
  end
@@ -10,7 +10,7 @@ require 'pp'
10
10
  require 'envoi/mam/agent/cli'
11
11
  require 'envoi/mam/cantemo/agent'
12
12
  # require 'envoi/aspera/watch_service/watch_folder'
13
- require 'envoi/mam/cantemo/agent/watch_folder_handler'
13
+ require 'envoi/mam/cantemo/agent/watch_folder_manager'
14
14
 
15
15
  Envoi::Mam::Agent::CLI::CONFIG_FILE_PATHS.clear
16
16
  Envoi::Mam::Agent::CLI::CONFIG_FILE_PATHS.concat [
@@ -32,7 +32,7 @@ ARGV << 'run' if ARGV.empty?
32
32
  :config_file_path => default_config_file_paths,
33
33
  :dry_run => false,
34
34
  :operation => :upload,
35
- :preserve_path => true,
35
+ :preserve_path => false,
36
36
  :transfer_type => '',
37
37
  }
38
38
  def args; @args end
@@ -49,15 +49,31 @@ op.parse!
49
49
  config_file_path = args[:config_file_path]
50
50
  args[:config_file_path].map! { |v| File.expand_path(v) } if config_file_path.is_a?(Array)
51
51
 
52
- control_command_present = %w(start stop restart run zap killall status).include? ARGV.first
52
+ command = ARGV.first.dup
53
53
 
54
- daemonize = control_command_present || begin
55
- _d = args[:daemonize]
54
+ control_command_present = command && begin
55
+ command.downcase!
56
+ %w(start stop restart run zap killall status).include?(command)
56
57
  end
57
58
 
59
+ if command
60
+ case command
61
+ when 'install'
62
+ puts
63
+ when 'uninstall'
64
+ puts
65
+ else
66
+ puts
67
+ end
68
+ end
69
+
70
+
71
+ daemonize = (control_command_present && %(start restart).include?(command)) || args[:daemonize]
72
+
58
73
  # puts "#{__FILE__}:#{__LINE__ } #{args}"
59
74
  # next_command = ARGV.shift
60
75
  # puts "COMMAND: #{next_command}"
61
76
 
62
- class Watcher < Envoi::Mam::Cantemo::Agent::WatchFolderHandler; end
63
- daemonize ? Watcher.run_as_daemon(args) : Watcher.run(args)
77
+ class Watcher < Envoi::Mam::Cantemo::Agent::WatchFolderManager; end
78
+ # daemonize ? Watcher.run_as_daemon(args, { force: true }) : Watcher.run(args)
79
+ daemonize ? Watcher.run_as_daemon(args) : Watcher.run(args)
@@ -1,7 +1,7 @@
1
1
  module Cantemo
2
2
  module Portal
3
3
  class Agent
4
- VERSION = '1.1.0'.freeze
4
+ VERSION = '1.1.1'.freeze
5
5
  end
6
6
  end
7
7
  end
@@ -48,10 +48,13 @@ module Envoi
48
48
  end
49
49
  end
50
50
 
51
+ # @param [String] command
52
+ # @param [Boolean] dry_run
53
+ # @return [Hash]
51
54
  def shell_execute(command, dry_run = @dry_run)
52
55
  if dry_run
53
56
  logger.debug { "Skipping Execution of Command: '#{command}' " }
54
- return
57
+ return { }
55
58
  end
56
59
  logger.debug { "Executing Command: '#{command}'" }
57
60
 
@@ -74,7 +77,7 @@ module Envoi
74
77
  success = thread.value == 0 ? true : false
75
78
  end
76
79
 
77
- success
80
+ { success: success }
78
81
  end
79
82
 
80
83
  def self.load_from_config_file(args)
@@ -105,6 +105,14 @@ module Envoi
105
105
  end
106
106
 
107
107
  aspera_token = config['aspera_transfer_token'] || config['aspera_token'] || config['token'] || config['transfer_token']
108
+ if aspera_username && aspera_password && (aspera_token.nil? || aspera_token.empty?)
109
+ _token_string = %(Basic #{["#{aspera_username}:#{aspera_password}"]
110
+ .pack('m')
111
+ .delete("\r\n")})
112
+ aspera_token = _token_string
113
+ aspera_password = nil
114
+ aspera_username = 'xfer'
115
+ end
108
116
 
109
117
  # @ascp_path = config['ascp_path'] || default_ascp_path
110
118
  # @ascp_path = File.expand_path(@ascp_path)
@@ -112,11 +120,12 @@ module Envoi
112
120
 
113
121
  env_vars = { }
114
122
  env_vars['ASPERA_SCP_PASS'] = aspera_password if aspera_password
123
+ # env_vars['ASPERA_SCP_TOKEN'] = aspera_token if aspera_token
115
124
 
116
125
  ascp_args = config['ascp_args'] || default_ascp_args || agent.default_ascp_args
117
126
 
118
- tags = config['tags'] || { }
119
- aspera_tags = tags['aspera'] || { }
127
+ tags = config['tags'] ||= { }
128
+ aspera_tags = tags['aspera'] ||= { }
120
129
  aspera_tags['xfer_id'] ||= SecureRandom.uuid
121
130
 
122
131
  cmdline_args = [
@@ -127,7 +136,9 @@ module Envoi
127
136
  ]
128
137
  cmdline_args.concat [ '-P', aspera_ssh_port ] if aspera_ssh_port
129
138
  cmdline_args.concat ascp_args.is_a?(Array) ? ascp_args : ascp_args.split(' ') if ascp_args && !ascp_args.empty?
130
- cmdline_args.concat [ '-W', aspera_token ] if aspera_token && !aspera_token.empty?
139
+ if aspera_token && !aspera_token.empty?
140
+ cmdline_args.concat ['-W', aspera_token, '-i', 'asperaweb_id_dsa.openssh' ]
141
+ end
131
142
  cmdline_args.concat [ source_path.gsub('"', '\"'), target_path.gsub('"', '\"') ]
132
143
 
133
144
  { env: env_vars, args: cmdline_args, ascp_version: :ascp }
@@ -150,7 +161,12 @@ module Envoi
150
161
  end
151
162
 
152
163
  aspera_token = config['aspera_transfer_token'] || config['aspera_token'] || config['token'] || config['transfer_token']
153
-
164
+ if aspera_username && aspera_password && (aspera_token.nil? || aspera_token.empty?)
165
+ _token_string = %(Basic #{["#{aspera_username}:#{aspera_password}"]
166
+ .pack('m')
167
+ .delete("\r\n")})
168
+ aspera_username = 'xfer'
169
+ end
154
170
  @ascp_path = config['ascp_path'] || default_ascp_path
155
171
  @ascp_path = File.expand_path(@ascp_path)
156
172
 
@@ -169,14 +185,16 @@ module Envoi
169
185
  command << %("#{aspera_ascp_path}" --mode=#{mode} --host="#{aspera_host_address}" --user="#{aspera_username}")
170
186
  command << %( -P #{aspera_ssh_port}) if aspera_ssh_port
171
187
  command << %(--tags64 #{Base64.strict_encode64(JSON.generate(tags))}) if tags && !tags.empty?
172
- command << %( #{ascp_args}) if ascp_args && !ascp_args.empty?
188
+ if ascp_args && !ascp_args.empty?
189
+ command << (ascp_args.is_a?(Array)) ? ascp_args.join(' ') : ascp_args
190
+ end
173
191
  command << %( -W "#{aspera_token}") if aspera_token && !aspera_token.empty?
174
192
  command << %( "#{source_path.gsub('"', '\"')}" "#{target_path.gsub('"', '\"')}")
175
193
  end
176
194
 
177
195
  def download(config, path, destination_path = DEFAULT_DESTINATION_PATH)
178
196
  aspera_base_path = config['base_path'] || ''
179
- source_path = File.join(aspera_base_path, path)
197
+ source_path = aspera_base_path.empty? ? path : File.join(aspera_base_path, path)
180
198
 
181
199
  mode = 'recv'
182
200
  transfer(config, mode, source_path, destination_path)
@@ -192,7 +210,7 @@ module Envoi
192
210
  end
193
211
 
194
212
  def transfer(config, mode, source_path, destination_path)
195
- if false
213
+ if true
196
214
  transfer_using_asperala(config, mode, source_path, destination_path)
197
215
  else
198
216
  transfer_using_shell_execute(config, mode, source_path, destination_path)
@@ -201,21 +219,30 @@ module Envoi
201
219
 
202
220
  def transfer_using_asperala(config, mode, source_path, destination_path)
203
221
  args_out = build_asperala_transfer_args(config, mode, source_path, destination_path)
204
- fasp = Asperalm::Fasp::Local.instance
205
- Asperalm::Log.instance.level = :debug
206
- fasp.start_transfer_with_args_env(args_out, {})
222
+ @fasp ||= Asperalm::Fasp::Local.instance
223
+ Asperalm::Log.instance.level = :debug #logger.level
224
+ @fasp.start_transfer_with_args_env(args_out, {})
225
+ { success: true }
207
226
  end
208
227
 
209
228
  def transfer_using_shell_execute(config, mode, source_path, destination_path)
210
229
  command = build_ascp_command(config, mode, source_path, destination_path)
211
230
 
212
231
  unless ascp_path_exists?
213
- warn "ASCP not found. '#{ascp_path}'"
214
- return false
232
+ msg = "ASCP not found. '#{ascp_path}'"
233
+ warn msg
234
+ return { message: msg, success: false }
215
235
  end
236
+
216
237
  agent.shell_execute(command)
217
238
  end
218
239
 
240
+ def shutdown(graceful = true)
241
+ if @fasp && @fasp.respond_to?(:shutdown)
242
+ @fasp.shutdown(graceful)
243
+ end
244
+ end
245
+
219
246
  # AsperaTransferClient
220
247
  end
221
248
 
@@ -13,15 +13,18 @@ module Envoi
13
13
 
14
14
  DEFAULT_SHAPE_TAG = 'original'
15
15
  DEFAULT_DESTINATION_PATH = '.'
16
+ DEFAULT_PRESERVE_FILE_PATH = true
16
17
 
17
18
  attr_accessor :default_aspera_ascp_args,
18
19
  :default_aspera_ascp_path,
19
- :default_vidispine_shape_tag
20
+ :default_vidispine_shape_tag,
21
+ :default_preserve_file_path
20
22
 
21
23
  def after_initialize
22
24
  args = initial_args
23
- @default_aspera_ascp_path = args[:default_aspera_ascp_path]
24
- @default_aspera_args = args[:default_ascp_args] || Envoi::Mam::Agent::TransferClient::Aspera::DEFAULT_ASCP_ARGS
25
+ @default_aspera_ascp_path = args[:default_aspera_ascp_path]
26
+ @default_aspera_args = args.fetch(:default_ascp_args, Envoi::Mam::Agent::TransferClient::Aspera::DEFAULT_ASCP_ARGS)
27
+ @default_preserve_file_path = args.fetch(:default_preserve_file_path, DEFAULT_PRESERVE_FILE_PATH)
25
28
  end
26
29
 
27
30
  def dry_run?; @dry_run end
@@ -35,8 +38,8 @@ module Envoi
35
38
  @api_client = args[:api_client] || begin
36
39
 
37
40
  api_host = api_config['host']
38
- api_host_use_ssl = api_config['use_ssl']
39
41
  api_port = api_config['port']
42
+ api_host_use_ssl = api_config['ssl']
40
43
  api_username = api_config['username']
41
44
  api_password = api_config['password']
42
45
  api_auth_token = api_config['api_auth_token']
@@ -54,13 +57,17 @@ module Envoi
54
57
  api_username ||= _api_username
55
58
  api_password ||= _api_password
56
59
  end
60
+ api_host_use_ssl = api_uri.scheme == 'https' if api_host_use_ssl.nil?
57
61
  api_uri_query = api_uri.query
58
62
  api_default_query_data ||= Hash[api_uri_query.split('&').map { |kp| kp.split('=') }]
59
63
  api_base_path ||= api_uri.path
60
64
  end
61
65
 
62
66
  api_port ||= (api_host_use_ssl ? 443 : 80)
63
- api_base_path ||= 'VSAPI/'
67
+ api_base_path ||= '/'
68
+
69
+ api_endpoint_prefix = 'VSAPI'
70
+ api_noauth_endpoint_prefix = 'APInoauth'
64
71
 
65
72
  client_args = { }
66
73
  client_args[:http_host_address] = api_host if api_host
@@ -70,6 +77,8 @@ module Envoi
70
77
  client_args[:password] = api_password if api_password
71
78
  client_args[:default_base_path] = api_base_path if api_base_path
72
79
  client_args[:default_query_data] = api_default_query_data if api_default_query_data
80
+ client_args[:api_endpoint_prefix] = api_endpoint_prefix
81
+ client_args[:api_noauth_endpoint_prefix] = api_noauth_endpoint_prefix
73
82
 
74
83
  if api_auth_token
75
84
  # Cantemo Portal supports an auth token for authentication, replace basic auth with auth-token
@@ -78,10 +87,16 @@ module Envoi
78
87
  end
79
88
 
80
89
  _client = ::Vidispine::API::Utilities.new(client_args)
81
- _client
82
- end
83
90
 
91
+ begin
92
+ _client.version
93
+ rescue => e
94
+ e.message = "Error connecting to Portal: #{e.message}"
95
+ raise e
96
+ end
84
97
 
98
+ _client
99
+ end
85
100
 
86
101
  @default_vidispine_shape_tag = args[:default_shape_tag] || api_config['default_shape_tag'] || api_config['shape_tag'] || DEFAULT_SHAPE_TAG
87
102
 
@@ -133,7 +148,7 @@ module Envoi
133
148
  end
134
149
 
135
150
  logger.info { "Transferring File Path: '#{file_path}'" }
136
- preserve_path = args.fetch(:preserve_path, file_storage_config.fetch('preserve_path', true))
151
+ preserve_path = args.fetch(:preserve_path, file_storage_config.fetch('preserve_path', default_preserve_file_path))
137
152
 
138
153
  destination_path = args[:destination_path] || file_storage_config['destination_path'] || DEFAULT_DESTINATION_PATH
139
154
  relative_path = preserve_path ? File.dirname(file_path) : nil
@@ -161,6 +176,8 @@ module Envoi
161
176
  end
162
177
 
163
178
  def upload(args = { })
179
+ _response = { }
180
+
164
181
  file_path = args[:file_path]
165
182
  raise ArgumentError, "Path not found: '#{file_path}'" unless File.exists?(file_path)
166
183
 
@@ -183,7 +200,7 @@ module Envoi
183
200
 
184
201
  should_import_file = args.fetch(:import_file, vidispine_storage_config.fetch('import', true))
185
202
 
186
- should_preserve_path = args.fetch(:preserve_path, vidispine_storage_config.fetch('preserve_path', true))
203
+ should_preserve_path = args.fetch(:preserve_path, vidispine_storage_config.fetch('preserve_path', default_preserve_file_path))
187
204
 
188
205
  destination_path = args[:destination_path] || vidispine_storage_config['destination_path'] || '/'
189
206
  relative_path = should_preserve_path ? File.dirname(file_path) : nil
@@ -194,7 +211,7 @@ module Envoi
194
211
 
195
212
 
196
213
  # upload file
197
-
214
+
198
215
  transfer_response = begin
199
216
  response = nil
200
217
  aspera_config = vidispine_storage_config['aspera']
@@ -204,7 +221,7 @@ module Envoi
204
221
  response = client.upload(aspera_config, file_path, target_path)
205
222
  end
206
223
  rescue => e
207
- logger.error { "Aspera Transfer Failed. '#{e.message}'" }
224
+ logger.error { "Aspera Transfer Failed. '#{e.message}'\n#{e.backtrace.first}" }
208
225
  end
209
226
 
210
227
  s3_config = vidispine_storage_config['s3']
@@ -222,28 +239,95 @@ module Envoi
222
239
 
223
240
  response
224
241
  end
225
-
226
- logger.warn { "No supported TransferClient configuration#{transfer_type && !transfer_type.empty? ? " for transfer type '#{transfer_type}' " : ''}found in storage configuration." } unless transfer_response != nil
242
+ transfer_response = { success: transfer_response } if transfer_response == true || transfer_response == false
243
+
244
+ logger.debug { "Transfer Response: #{transfer_response}" }
245
+ _response[:transfer_response] = transfer_response
227
246
 
228
- _response = { transfer_response: transfer_response }
247
+ if transfer_response.nil?
248
+ logger.warn { "No supported TransferClient configuration#{transfer_type && !transfer_type.empty? ? " for transfer type '#{transfer_type}' " : ''}found in storage configuration." }
249
+ _response[:success] = false
250
+ return _response
251
+ end
252
+
253
+ unless transfer_response[:success]
254
+ logger.error { "Error transferring file." }
255
+ _response[:success] = false
256
+ return _response
257
+ end
229
258
 
230
- return _response unless should_import_file
259
+ unless should_import_file
260
+ _response[:success] = transfer_response[:success]
261
+ return _response
262
+ end
263
+
264
+
265
+ ### IMPORT - START
266
+ import_file_args = args.dup
267
+ import_file_args[:response_object] = _response
268
+ import_file_args[:target_path] = target_path
269
+ import_file(import_file_args)
270
+ _response[:success] = true unless _response[:success] === false
271
+ ### IMPORT - END
272
+
273
+ _response
274
+ rescue => e
275
+ logger.error { "Exception: #{e.message}" }
276
+ _response[:exception] = e
277
+ return _response
278
+ end
279
+
280
+ def import_file(args = { })
281
+ _response = args[:response_object] || { }
282
+
283
+ file_path = args[:file_path]
284
+ storage_id = args[:storage_id]
285
+
286
+ target_path = args[:target_path]
231
287
 
232
288
  item_id = args[:item_id]
233
289
  shape_tag = args[:shape_tag] || default_vidispine_shape_tag
234
290
 
235
291
  # attach file to item as shape
236
292
  path_on_storage = File.join(target_path, File.basename(file_path))
237
- file_create_response = api_client.storage_file_create storage_id: storage_id, path: path_on_storage, state: 'CLOSED'
238
- file_id = file_create_response['id']
293
+ path_on_storage = path_on_storage[1..-1] if path_on_storage.start_with?('/')
294
+ # file_create_response = api_client.storage_file_create(storage_id: storage_id,
295
+ # path: path_on_storage, state: 'CLOSED')
296
+ file_create_response = api_client.storage_file_get_or_create(storage_id, path_on_storage, { :extended_response => true })
297
+ _response[:file_create_response] = file_create_response
298
+ file = file_create_response[:file]
299
+
300
+ file_id = file['id']
301
+
302
+ unless file_id
303
+ _file = file.dup
304
+ _file.keep_if { |k,v| v }
305
+ logger.error { "Failed to create file. #{_file}" }
306
+ _response[:success] = false
307
+ return _response
308
+ end
309
+
310
+ item = (file['item'] || []).first
311
+
312
+ if item
313
+ shape = (item['shape'] || []).first
314
+ msg = "File already exist and is associated to item #{item['id']} as shape #{shape['id']}."
315
+ logger.warn { "#{msg} #{file}" }
316
+ _response[:error] = { :message => msg }
317
+ _response[:success] = false
318
+ return _response
319
+ end
239
320
 
240
321
  if item_id
241
- item_shape_import_response = api_client.item_shape_import item_id: item_id, tag: shape_tag, fileId: file_id
322
+ item_shape_import_response = api_client.item_shape_import(item_id: item_id,
323
+ tag: shape_tag, fileId: file_id)
324
+
325
+
242
326
  else
243
- item_shape_import_response = api_client.item_add_using_file_path storage_id: storage_id,
244
- file_path: file_path,
245
- file_id: file_id,
246
- storage_path_map: { '/' => storage_id }
327
+ item_shape_import_response = api_client.item_add_using_file_path(storage_id: storage_id,
328
+ file_path: path_on_storage,
329
+ fileId: file_id,
330
+ storage_path_map: { '/' => storage_id })
247
331
  end
248
332
  _response[:import_response] = item_shape_import_response
249
333