etna 0.1.52 → 0.2.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/bin/etna +2 -2
  3. data/lib/commands.rb +10 -8
  4. data/lib/etna/application.rb +33 -0
  5. data/lib/etna/auth.rb +5 -2
  6. data/lib/etna/client.rb +7 -12
  7. data/lib/etna/clients/base_client.rb +10 -2
  8. data/lib/etna/clients/gnomon/client.rb +20 -0
  9. data/lib/etna/clients/gnomon/models.rb +33 -0
  10. data/lib/etna/clients/gnomon.rb +2 -0
  11. data/lib/etna/clients/janus/client.rb +26 -0
  12. data/lib/etna/clients/janus/models.rb +16 -0
  13. data/lib/etna/clients/janus/workflows/generate_token_workflow.rb +1 -1
  14. data/lib/etna/clients/magma/client.rb +126 -6
  15. data/lib/etna/clients/magma/models.rb +64 -22
  16. data/lib/etna/clients/magma/workflows/model_synchronization_workflow.rb +2 -4
  17. data/lib/etna/clients/metis/client.rb +66 -2
  18. data/lib/etna/clients/metis/models.rb +138 -85
  19. data/lib/etna/clients/metis/workflows/ingest_metis_data_workflow.rb +15 -5
  20. data/lib/etna/clients/metis/workflows/metis_upload_workflow.rb +1 -0
  21. data/lib/etna/clients/models.rb +19 -0
  22. data/lib/etna/clients/polyphemus/client.rb +96 -0
  23. data/lib/etna/clients.rb +2 -0
  24. data/lib/etna/controller.rb +31 -6
  25. data/lib/etna/cross_origin.rb +1 -1
  26. data/lib/etna/cwl.rb +1 -1
  27. data/lib/etna/errors.rb +8 -0
  28. data/lib/etna/filesystem.rb +5 -170
  29. data/lib/etna/hmac.rb +4 -4
  30. data/lib/etna/instrumentation.rb +6 -6
  31. data/lib/etna/redirect.rb +1 -1
  32. data/lib/etna/remote.rb +18 -2
  33. data/lib/etna/route.rb +3 -0
  34. data/lib/etna/spec/event_log.rb +16 -0
  35. data/lib/etna/spec/vcr.rb +3 -3
  36. data/lib/etna/test_auth.rb +1 -1
  37. data/lib/etna/user.rb +0 -4
  38. data/lib/helpers.rb +8 -0
  39. metadata +8 -5
@@ -13,8 +13,8 @@ module Etna
13
13
  class RetrievalRequest < Struct.new(:model_name, :attribute_names, :record_names, :project_name, :page, :page_size, :order, :filter, :hide_templates, keyword_init: true)
14
14
  include JsonSerializableStruct
15
15
 
16
- def initialize(**params)
17
- super({model_name: 'all', attribute_names: 'all', record_names: []}.update(params))
16
+ def initialize(params = {}, **kwds)
17
+ super(**{model_name: 'all', attribute_names: 'all', record_names: []}.update(params).update(kwds))
18
18
  end
19
19
  end
20
20
 
@@ -22,12 +22,12 @@ module Etna
22
22
  include JsonSerializableStruct
23
23
  end
24
24
 
25
- class UpdateRequest < Struct.new(:revisions, :project_name, :dry_run, keyword_init: true)
25
+ class UpdateRequest < Struct.new(:revisions, :project_name, :dry_run, :autolink, keyword_init: true)
26
26
  include JsonSerializableStruct
27
27
  include MultipartSerializableNestedHash
28
28
 
29
- def initialize(**params)
30
- super({revisions: {}, dry_run: false}.update(params))
29
+ def initialize(params = {}, **kwds)
30
+ super(**{revisions: {}, dry_run: false}.update(params).update(kwds))
31
31
  end
32
32
 
33
33
  def update_revision(model_name, record_name, attrs)
@@ -49,8 +49,8 @@ module Etna
49
49
  class UpdateModelRequest < Struct.new(:project_name, :actions, keyword_init: true)
50
50
  include JsonSerializableStruct
51
51
 
52
- def initialize(**params)
53
- super({actions: []}.update(params))
52
+ def initialize(params = {}, **kwds)
53
+ super(**{actions: []}.update(params).update(kwds))
54
54
  end
55
55
 
56
56
  def add_action(action)
@@ -58,27 +58,35 @@ module Etna
58
58
  end
59
59
  end
60
60
 
61
- class AddModelAction < Struct.new(:action_name, :model_name, :parent_model_name, :parent_link_type, :identifier, :date_shift_root, keyword_init: true)
61
+ class AddModelAction < Struct.new(:action_name, :model_name, :parent_model_name, :parent_link_type, :identifier, :date_shift_root, :template_project_name, :template_model_name, keyword_init: true)
62
62
  include JsonSerializableStruct
63
63
 
64
- def initialize(**args)
65
- super({action_name: 'add_model', date_shift_root: false}.update(args))
64
+ def initialize(args = {}, **kwds)
65
+ super(**{action_name: 'add_model', date_shift_root: false}.update(args).update(kwds))
66
66
  end
67
67
  end
68
68
 
69
69
  class SetDateShiftRootAction < Struct.new(:action_name, :model_name, :date_shift_root, keyword_init: true)
70
70
  include JsonSerializableStruct
71
71
 
72
+ def initialize(args = {}, **kwds)
73
+ super(**{action_name: 'set_date_shift_root'}.update(args).update(kwds))
74
+ end
75
+ end
76
+
77
+ class SetModelTemplateAction < Struct.new(:action_name, :model_name, :template_project_name, :template_model_name, :clear_template, keyword_init: true)
78
+ include JsonSerializableStruct
79
+
72
80
  def initialize(**args)
73
- super({action_name: 'set_date_shift_root'}.update(args))
81
+ super({action_name: 'set_model_template', clear_template: false}.update(args))
74
82
  end
75
83
  end
76
84
 
77
85
  class AddAttributeAction < Struct.new(:action_name, :model_name, :attribute_name, :type, :description, :display_name, :format_hint, :hidden, :index, :link_model_name, :read_only, :attribute_group, :restricted, :unique, :validation, keyword_init: true)
78
86
  include JsonSerializableStruct
79
87
 
80
- def initialize(**args)
81
- super({action_name: 'add_attribute'}.update(args))
88
+ def initialize(args = {}, **kwds)
89
+ super(**{action_name: 'add_attribute'}.update(args).update(kwds))
82
90
  end
83
91
 
84
92
  def attribute_type=(val)
@@ -101,8 +109,8 @@ module Etna
101
109
  class AddLinkAction < Struct.new(:action_name, :links, keyword_init: true)
102
110
  include JsonSerializableStruct
103
111
 
104
- def initialize(**args)
105
- super({action_name: 'add_link', links: []}.update(args))
112
+ def initialize(args = {}, **kwds)
113
+ super(**{action_name: 'add_link', links: []}.update(args).update(kwds))
106
114
  end
107
115
  end
108
116
 
@@ -113,16 +121,16 @@ module Etna
113
121
  class AddProjectAction < Struct.new(:action_name, :no_metis_bucket, keyword_init: true)
114
122
  include JsonSerializableStruct
115
123
 
116
- def initialize(**args)
117
- super({action_name: 'add_project'}.update(args))
124
+ def initialize(args = {}, **kwds)
125
+ super(**{action_name: 'add_project'}.update(args).update(kwds))
118
126
  end
119
127
  end
120
128
 
121
129
  class UpdateAttributeAction < Struct.new(:action_name, :model_name, :attribute_name, :description, :display_name, :format_hint, :hidden, :index, :link_model_name, :read_only, :attribute_group, :restricted, :unique, :validation, keyword_init: true)
122
130
  include JsonSerializableStruct
123
131
 
124
- def initialize(**args)
125
- super({action_name: 'update_attribute'}.update(args))
132
+ def initialize(args = {}, **kwds)
133
+ super(**{action_name: 'update_attribute'}.update(args).update(kwds))
126
134
  end
127
135
 
128
136
  def as_json
@@ -133,8 +141,8 @@ module Etna
133
141
  class RenameAttributeAction < Struct.new(:action_name, :model_name, :attribute_name, :new_attribute_name, keyword_init: true)
134
142
  include JsonSerializableStruct
135
143
 
136
- def initialize(**args)
137
- super({action_name: 'rename_attribute'}.update(args))
144
+ def initialize(args = {}, **kwds)
145
+ super(**{action_name: 'rename_attribute'}.update(args).update(kwds))
138
146
  end
139
147
  end
140
148
 
@@ -159,6 +167,12 @@ module Etna
159
167
  def models
160
168
  Models.new(raw['models'])
161
169
  end
170
+
171
+ def update(response)
172
+ response.models.each do |model_name, model|
173
+ models.update( model_name, model )
174
+ end
175
+ end
162
176
  end
163
177
 
164
178
  class UpdateModelResponse < RetrievalResponse
@@ -219,6 +233,12 @@ module Etna
219
233
  Model.new(raw[model_key.to_s])
220
234
  end
221
235
 
236
+ def each
237
+ model_keys.each do |model_key|
238
+ yield model_key, model(model_key)
239
+ end
240
+ end
241
+
222
242
  def all
223
243
  raw.values.map { |r| Model.new(r) }
224
244
  end
@@ -229,6 +249,20 @@ module Etna
229
249
  Models.new({}.update(raw).update(raw_update))
230
250
  end
231
251
 
252
+ def update(model_name, model)
253
+ raw[ model_name.to_s ] ||= {}
254
+ raw[ model_name.to_s ]["template"] = model.template.raw
255
+ raw[ model_name.to_s ]["documents"] ||= {}
256
+ raw[ model_name.to_s ]["documents"].update(model.documents.raw)
257
+ end
258
+
259
+ def is_table?(model_name)
260
+ parent_model_name = self.model(model_name)&.template&.parent
261
+ parent_model = self.model(parent_model_name)
262
+ parent_attribute = parent_model&.template&.attributes&.attribute(model_name)
263
+ parent_attribute&.attribute_type == 'table'
264
+ end
265
+
232
266
  # Can look up reciprocal links by many means. At minimum, a source model or model name must be provided,
233
267
  # and either a link_attribute_name, attribute, or link_model.
234
268
  def find_reciprocal(
@@ -238,7 +272,7 @@ module Etna
238
272
  attribute: model&.template&.attributes&.attribute(link_attribute_name),
239
273
  link_model: self.model(attribute&.link_model_name)
240
274
  )
241
- return nil if model.nil? || model.name.nil?
275
+ return nil if model.nil?
242
276
 
243
277
  return link_model&.template&.attributes&.all&.find { |a| a.name == link_attribute_name } if link_attribute_name
244
278
 
@@ -371,6 +405,14 @@ module Etna
371
405
  Attributes.new(raw['attributes'] ||= {})
372
406
  end
373
407
 
408
+ def template_project_name
409
+ raw['template_project_name']
410
+ end
411
+
412
+ def template_model_name
413
+ raw['template_model_name']
414
+ end
415
+
374
416
  def build_attributes
375
417
  Attributes.new(raw['attributes'] ||= {})
376
418
  end
@@ -249,10 +249,8 @@ module Etna
249
249
  template = source_model.template
250
250
 
251
251
  add_model_action = AddModelAction.new(
252
- {
253
- model_name: target_model_name,
254
- identifier: template.identifier,
255
- }
252
+ model_name: target_model_name,
253
+ identifier: template.identifier,
256
254
  )
257
255
 
258
256
  parents = template.attributes.all.select { |a| a.attribute_type == AttributeType::PARENT }
@@ -23,6 +23,16 @@ module Etna
23
23
  @etna_client.folder_list_all_folders(list_all_folders_request.to_h))
24
24
  end
25
25
 
26
+ def tail_bucket(tail_bucket_request = TailBucketRequest.new)
27
+ TailResponse.new(
28
+ tail_bucket_request.project_name,
29
+ tail_bucket_request.bucket_name,
30
+ @etna_client.bucket_tail(tail_bucket_request.to_h).split("\n").map do |line|
31
+ JSON.parse(line, symbolize_names: true)
32
+ end
33
+ )
34
+ end
35
+
26
36
  def list_folder(list_folder_request = ListFolderRequest.new)
27
37
  if list_folder_request.folder_path != ''
28
38
  FoldersAndFilesResponse.new(
@@ -101,16 +111,36 @@ module Etna
101
111
 
102
112
  def download_file(file_or_url = File.new, &block)
103
113
  if file_or_url.instance_of?(File)
104
- download_path = file_or_url.download_path
114
+ download_url = file_or_url.download_url
115
+
116
+ if !download_url.present?
117
+ download = authorize_download(AuthorizeDownloadRequest.new(
118
+ project_name: file_or_url.project_name,
119
+ bucket_name: file_or_url.bucket_name,
120
+ file_path: file_or_url.file_path
121
+ ))
122
+ download_url = download.download_url
123
+ end
105
124
  else
106
- download_path = file_or_url.sub(%r!^https://[^/]*?/!, '/')
125
+ download_url = file_or_url
107
126
  end
108
127
 
128
+ download_path = download_url.sub(%r!^https://[^/]*?/!, '/')
129
+
109
130
  @etna_client.get(download_path) do |response|
110
131
  response.read_body(&block)
111
132
  end
112
133
  end
113
134
 
135
+ def authorize_download(authorize_download_request = AuthorizeDownloadRequest.new)
136
+ json = nil
137
+ @etna_client.post("/authorize/download", authorize_download_request) do |res|
138
+ json = JSON.parse(res.body)
139
+ end
140
+
141
+ DownloadResponse.new(json)
142
+ end
143
+
114
144
  def file_metadata(file_or_url = File.new)
115
145
  if file_or_url.instance_of?(File)
116
146
  download_path = file_or_url.download_path
@@ -329,11 +359,45 @@ module Etna
329
359
  ))
330
360
  end
331
361
 
362
+ def get_file_count_by_project(get_file_count_by_project_request = GetFileCountByProjectRequest.new)
363
+ query = ""
364
+ unless get_file_count_by_project_request.project_names.nil?
365
+ query = "?#{create_query_list_str('projects', get_file_count_by_project_request.project_names)}"
366
+ end
367
+
368
+ json = nil
369
+ @etna_client.get("/api/stats/files#{query}") do |res|
370
+ json = JSON.parse(res.body, symbolize_names: true)
371
+ end
372
+
373
+ json
374
+ end
375
+
376
+ def get_byte_count_by_project(get_byte_count_by_project_request = GetByteCountByProjectRequest.new)
377
+ query = ""
378
+ unless get_byte_count_by_project_request.project_names.nil?
379
+ query = "?#{create_query_list_str('projects', get_byte_count_by_project_request.project_names)}"
380
+ end
381
+
382
+ json = nil
383
+ @etna_client.get("/api/stats/bytes#{query}") do |res|
384
+ json = JSON.parse(res.body, symbolize_names: true)
385
+ end
386
+
387
+ json
388
+ end
389
+
332
390
  private
333
391
 
334
392
  def parent_folder_path(folder_path)
335
393
  folder_path.split('/')[0..-2].join('/')
336
394
  end
395
+
396
+ def create_query_list_str(name, values)
397
+ values.map do |val|
398
+ "#{name}[]=#{val}"
399
+ end.join('&')
400
+ end
337
401
  end
338
402
  end
339
403
  end
@@ -158,6 +158,21 @@ module Etna
158
158
  end
159
159
  end
160
160
 
161
+ class TailBucketRequest < Struct.new(:project_name, :bucket_name, :type, :folder_id, :batch_start, :batch_end, keyword_init: true)
162
+ include JsonSerializableStruct
163
+
164
+ def initialize(**params)
165
+ super({}.update(params))
166
+ end
167
+
168
+ def to_h
169
+ # The :project_name comes in from Polyphemus as a symbol value,
170
+ # we need to make sure it's a string because it's going
171
+ # in the URL.
172
+ super().compact.transform_values(&:to_s)
173
+ end
174
+ end
175
+
161
176
  class FindRequest < Struct.new(:project_name, :bucket_name, :limit, :offset, :params, :hide_paths, keyword_init: true)
162
177
  include JsonSerializableStruct
163
178
 
@@ -219,25 +234,99 @@ module Etna
219
234
  end
220
235
  end
221
236
 
222
- class FoldersResponse
223
- attr_reader :raw
237
+ class TailNode < Etna::Clients::Response
238
+ def initialize(tail, raw = {})
239
+ super(raw)
240
+ @tail = tail
241
+ end
224
242
 
225
- def initialize(raw = {})
226
- @raw = raw
243
+ def parent?
244
+ @raw[:type] == 'parent'
227
245
  end
228
246
 
229
- def folders
230
- Folders.new(raw[:folders])
247
+ def folder?
248
+ @raw[:type] == 'folder'
249
+ end
250
+
251
+ def file?
252
+ @raw[:type] == 'file'
253
+ end
254
+
255
+ params :id, :node_name, :parent_id, :file_hash, :updated_at
256
+
257
+ def as_file
258
+ {
259
+ file_name: node_name,
260
+ file_hash: file_hash,
261
+ updated_at: updated_at,
262
+ file_path: file_path,
263
+ folder_id: parent_id,
264
+ project_name: @tail.project_name,
265
+ bucket_name: @tail.bucket_name,
266
+ }
267
+ end
268
+
269
+ def parent_path
270
+ return nil if !parent_id
271
+
272
+ if !@tail.paths[parent_id]
273
+ parent = @tail.parents[parent_id]
274
+ @tail.paths[parent_id] = parent.file_path
275
+ end
276
+
277
+ return @tail.paths[parent_id]
278
+ end
279
+
280
+ def file_path
281
+ [ parent_path, node_name ].compact.join('/')
231
282
  end
232
283
  end
233
284
 
234
- class FilesResponse
235
- attr_reader :raw
285
+ class TailResponse < Etna::Clients::Response
286
+ attr_reader :project_name, :bucket_name, :paths, :parents
287
+
288
+
289
+ def initialize(project_name, bucket_name, raw = {})
290
+ super(raw)
291
+
292
+ @paths = {}
293
+
294
+ @parents = {}
295
+
296
+ @project_name = project_name
297
+ @bucket_name = bucket_name
298
+
299
+ @nodes = []
300
+ raw.each do |raw_node|
301
+ node = TailNode.new(self, raw_node)
302
+ if node.parent?
303
+ @parents[node.id] = node
304
+ else
305
+ @nodes.push(node)
306
+ end
307
+ end
308
+ end
309
+
310
+ def folders
311
+ @nodes.filter_map do |node|
312
+ Folder.new(node.as_folder) if node.folder?
313
+ end
314
+ end
315
+
316
+ def files
317
+ @nodes.filter_map do |node|
318
+ File.new(node.as_file) if node.file?
319
+ end
320
+ end
321
+ end
236
322
 
237
- def initialize(raw = {})
238
- @raw = raw
323
+ class FoldersResponse < Etna::Clients::Response
324
+ def folders
325
+ Folders.new(raw[:folders])
239
326
  end
327
+ end
240
328
 
329
+ class FilesResponse < Etna::Clients::Response
241
330
  def files
242
331
  Files.new(raw[:files])
243
332
  end
@@ -253,37 +342,19 @@ module Etna
253
342
  end
254
343
  end
255
344
 
256
- class Files
257
- attr_reader :raw
258
-
259
- def initialize(raw = {})
260
- @raw = raw
261
- end
262
-
345
+ class Files < Etna::Clients::Response
263
346
  def all
264
347
  raw.map { |file| File.new(file) }
265
348
  end
266
349
  end
267
350
 
268
- class Folders
269
- attr_reader :raw
270
-
271
- def initialize(raw = {})
272
- @raw = raw
273
- end
274
-
351
+ class Folders < Etna::Clients::Response
275
352
  def all
276
353
  raw.map { |folder| Folder.new(folder) }
277
354
  end
278
355
  end
279
356
 
280
- class File
281
- attr_reader :raw
282
-
283
- def initialize(raw = {})
284
- @raw = raw
285
- end
286
-
357
+ class File < Etna::Clients::Response
287
358
  def with_containing_folder(folder)
288
359
  folder_path = folder.is_a?(Folder) ? folder.folder_path : folder
289
360
  File.new({}.update(self.raw).update({
@@ -291,17 +362,7 @@ module Etna
291
362
  }))
292
363
  end
293
364
 
294
- def file_path
295
- raw[:file_path]
296
- end
297
-
298
- def project_name
299
- raw[:project_name]
300
- end
301
-
302
- def bucket_name
303
- raw[:bucket_name]
304
- end
365
+ params :file_path, :project_name, :bucket_name, :file_name, :size, :file_hash, :folder_id
305
366
 
306
367
  def download_path
307
368
  raw[:download_url].nil? ?
@@ -313,65 +374,40 @@ module Etna
313
374
  raw[:download_url] || ''
314
375
  end
315
376
 
316
- def file_name
317
- raw[:file_name]
318
- end
319
-
320
377
  def updated_at
321
378
  time = raw[:updated_at]
322
379
  time.nil? ? nil : Time.parse(time)
323
380
  end
324
381
 
325
- def size
326
- raw[:size]
382
+ def as_magma_file_attribute
383
+ {
384
+ path: as_metis_url,
385
+ original_filename: file_name || ::File.basename(file_path)
386
+ }
327
387
  end
328
388
 
329
- def file_hash
330
- raw[:file_hash]
331
- end
332
-
333
- def folder_id
334
- raw[:folder_id]
389
+ def as_metis_url
390
+ "metis://#{project_name}/#{bucket_name}/#{file_path}"
335
391
  end
336
392
  end
337
393
 
338
- class Folder
339
- attr_reader :raw
340
-
341
- def initialize(raw = {})
342
- @raw = raw
343
- end
344
-
345
- def folder_path
346
- raw[:folder_path]
347
- end
348
-
349
- def folder_name
350
- raw[:folder_name]
351
- end
352
-
353
- def bucket_name
354
- raw[:bucket_name]
355
- end
356
-
357
- def project_name
358
- raw[:project_name]
359
- end
394
+ class Folder < Etna::Clients::Response
395
+ params :folder_path, :folder_name, :bucket_name, :project_name, :id
360
396
 
361
397
  def updated_at
362
398
  time = raw[:updated_at]
363
399
  time.nil? ? nil : Time.parse(time)
364
400
  end
365
-
366
- def id
367
- raw[:id]
368
- end
369
401
  end
370
402
 
371
403
  class AuthorizeUploadRequest < Struct.new(:project_name, :bucket_name, :file_path, keyword_init: true)
372
404
  include JsonSerializableStruct
373
405
  end
374
406
 
407
+ class AuthorizeDownloadRequest < Struct.new(:project_name, :bucket_name, :file_path, keyword_init: true)
408
+ include JsonSerializableStruct
409
+ end
410
+
375
411
  class UploadStartRequest < Struct.new(:file_size, :action, :metis_uid, :next_blob_size, :upload_path, :next_blob_hash, :reset, keyword_init: true)
376
412
  include JsonSerializableStruct
377
413
 
@@ -392,12 +428,13 @@ module Etna
392
428
  end
393
429
  end
394
430
 
395
- class UploadResponse
396
- attr_reader :raw
397
- def initialize(raw = {})
398
- @raw = raw
431
+ class DownloadResponse < Etna::Clients::Response
432
+ def download_url
433
+ raw['download_url']
399
434
  end
435
+ end
400
436
 
437
+ class UploadResponse < Etna::Clients::Response
401
438
  def current_byte_position
402
439
  raw['current_byte_position'].to_i
403
440
  end
@@ -419,6 +456,22 @@ module Etna
419
456
  START = UploadAction.new("start")
420
457
  BLOB = UploadAction.new("blob")
421
458
  end
459
+
460
+ class GetFileCountByProjectRequest < Struct.new(:project_names, keyword_init: true)
461
+ include JsonSerializableStruct
462
+
463
+ def initialize(**params)
464
+ super({}.update(params))
465
+ end
466
+ end
467
+
468
+ class GetByteCountByProjectRequest < Struct.new(:project_names, keyword_init: true)
469
+ include JsonSerializableStruct
470
+
471
+ def initialize(**params)
472
+ super({}.update(params))
473
+ end
474
+ end
422
475
  end
423
476
  end
424
- end
477
+ end
@@ -9,24 +9,34 @@ module Etna
9
9
  # Since we are doing manual triage of files,
10
10
  # do not automatically copy directory trees.
11
11
  # srcs must be a list of full paths to files.
12
- def copy_files(srcs, &block)
13
- srcs.each do |src|
12
+ def copy_files(files, &block)
13
+ files.each do |file|
14
+ if file.is_a?(Array)
15
+ src, dest = file
16
+ else
17
+ src = dest = file
18
+ end
19
+
14
20
  if !ingest_filesystem.exist?(src)
15
21
  logger&.warn("#{src} does not exist on source filesystem. Skipping.")
22
+ yield src, false if block_given?
16
23
  next
17
24
  end
18
25
 
19
26
  logger&.info("Copying file #{src} (#{Etna::Formatting.as_size(ingest_filesystem.stat(src).size)})")
20
27
 
21
- # For ingestion triage, just copy over the exact path + filename.
22
- copy_file(dest: src, src: src, &block)
28
+ begin
29
+ copy_file(dest: dest, src: src, &block)
30
+ rescue Exception => e
31
+ yield src, false if block_given?
32
+ end
23
33
  end
24
34
  end
25
35
 
26
36
  def copy_file(dest:, src:, &block)
27
37
  ingest_filesystem.with_readable(src, "r") do |io|
28
38
  metis_filesystem.do_streaming_upload(io, dest, ingest_filesystem.stat(src).size)
29
- yield src if block_given?
39
+ yield src, true if block_given?
30
40
  end
31
41
  end
32
42
  end
@@ -197,6 +197,7 @@ module Etna
197
197
  end
198
198
  end
199
199
  end
200
+ @last_bytes
200
201
  end
201
202
  end
202
203
  end
@@ -0,0 +1,19 @@
1
+ module Etna
2
+ module Clients
3
+ class Response
4
+ attr_reader :raw
5
+
6
+ def self.params(*params)
7
+ params.each do |param|
8
+ self.define_method param do
9
+ @raw[param]
10
+ end
11
+ end
12
+ end
13
+
14
+ def initialize(raw = {})
15
+ @raw = raw || {}
16
+ end
17
+ end
18
+ end
19
+ end