aspera-cli 4.9.0 → 4.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/BUGS.md +20 -0
  4. data/CHANGELOG.md +509 -0
  5. data/CONTRIBUTING.md +118 -0
  6. data/README.md +1241 -916
  7. data/bin/ascli +4 -4
  8. data/bin/asession +11 -11
  9. data/docs/test_env.conf +32 -21
  10. data/examples/aoc.rb +4 -4
  11. data/examples/dascli +16 -9
  12. data/examples/faspex4.rb +8 -8
  13. data/examples/node.rb +12 -12
  14. data/examples/server.rb +10 -10
  15. data/lib/aspera/aoc.rb +273 -266
  16. data/lib/aspera/ascmd.rb +56 -54
  17. data/lib/aspera/ats_api.rb +4 -4
  18. data/lib/aspera/cli/basic_auth_plugin.rb +15 -12
  19. data/lib/aspera/cli/extended_value.rb +5 -5
  20. data/lib/aspera/cli/formater.rb +64 -64
  21. data/lib/aspera/cli/info.rb +2 -2
  22. data/lib/aspera/cli/listener/line_dump.rb +1 -1
  23. data/lib/aspera/cli/listener/logger.rb +1 -1
  24. data/lib/aspera/cli/listener/progress.rb +5 -6
  25. data/lib/aspera/cli/listener/progress_multi.rb +14 -19
  26. data/lib/aspera/cli/main.rb +66 -67
  27. data/lib/aspera/cli/manager.rb +112 -110
  28. data/lib/aspera/cli/plugin.rb +57 -36
  29. data/lib/aspera/cli/plugins/alee.rb +4 -4
  30. data/lib/aspera/cli/plugins/aoc.rb +309 -670
  31. data/lib/aspera/cli/plugins/ats.rb +44 -46
  32. data/lib/aspera/cli/plugins/bss.rb +10 -10
  33. data/lib/aspera/cli/plugins/config.rb +497 -378
  34. data/lib/aspera/cli/plugins/console.rb +12 -12
  35. data/lib/aspera/cli/plugins/cos.rb +18 -20
  36. data/lib/aspera/cli/plugins/faspex.rb +112 -114
  37. data/lib/aspera/cli/plugins/faspex5.rb +71 -46
  38. data/lib/aspera/cli/plugins/node.rb +379 -283
  39. data/lib/aspera/cli/plugins/orchestrator.rb +46 -46
  40. data/lib/aspera/cli/plugins/preview.rb +122 -114
  41. data/lib/aspera/cli/plugins/server.rb +137 -83
  42. data/lib/aspera/cli/plugins/shares.rb +30 -29
  43. data/lib/aspera/cli/plugins/sync.rb +13 -33
  44. data/lib/aspera/cli/transfer_agent.rb +60 -59
  45. data/lib/aspera/cli/version.rb +1 -1
  46. data/lib/aspera/colors.rb +3 -3
  47. data/lib/aspera/command_line_builder.rb +27 -27
  48. data/lib/aspera/cos_node.rb +22 -20
  49. data/lib/aspera/data_repository.rb +1 -1
  50. data/lib/aspera/environment.rb +35 -15
  51. data/lib/aspera/fasp/agent_base.rb +15 -15
  52. data/lib/aspera/fasp/agent_connect.rb +23 -21
  53. data/lib/aspera/fasp/agent_direct.rb +66 -64
  54. data/lib/aspera/fasp/agent_httpgw.rb +141 -78
  55. data/lib/aspera/fasp/agent_node.rb +23 -21
  56. data/lib/aspera/fasp/agent_trsdk.rb +20 -20
  57. data/lib/aspera/fasp/error.rb +3 -2
  58. data/lib/aspera/fasp/error_info.rb +11 -8
  59. data/lib/aspera/fasp/installation.rb +79 -79
  60. data/lib/aspera/fasp/listener.rb +1 -1
  61. data/lib/aspera/fasp/parameters.rb +86 -71
  62. data/lib/aspera/fasp/parameters.yaml +7 -4
  63. data/lib/aspera/fasp/resume_policy.rb +8 -8
  64. data/lib/aspera/fasp/transfer_spec.rb +35 -2
  65. data/lib/aspera/fasp/uri.rb +7 -7
  66. data/lib/aspera/faspex_gw.rb +7 -5
  67. data/lib/aspera/hash_ext.rb +3 -3
  68. data/lib/aspera/id_generator.rb +5 -5
  69. data/lib/aspera/keychain/encrypted_hash.rb +38 -105
  70. data/lib/aspera/keychain/macos_security.rb +128 -57
  71. data/lib/aspera/log.rb +7 -7
  72. data/lib/aspera/nagios.rb +19 -18
  73. data/lib/aspera/node.rb +209 -35
  74. data/lib/aspera/oauth.rb +37 -36
  75. data/lib/aspera/open_application.rb +19 -11
  76. data/lib/aspera/persistency_action_once.rb +4 -4
  77. data/lib/aspera/persistency_folder.rb +16 -15
  78. data/lib/aspera/preview/file_types.rb +8 -8
  79. data/lib/aspera/preview/generator.rb +67 -67
  80. data/lib/aspera/preview/utils.rb +27 -27
  81. data/lib/aspera/proxy_auto_config.js +41 -41
  82. data/lib/aspera/proxy_auto_config.rb +21 -14
  83. data/lib/aspera/rest.rb +72 -67
  84. data/lib/aspera/rest_call_error.rb +2 -1
  85. data/lib/aspera/rest_error_analyzer.rb +18 -17
  86. data/lib/aspera/rest_errors_aspera.rb +16 -16
  87. data/lib/aspera/secret_hider.rb +15 -13
  88. data/lib/aspera/ssh.rb +11 -10
  89. data/lib/aspera/sync.rb +158 -44
  90. data/lib/aspera/temp_file_manager.rb +2 -2
  91. data/lib/aspera/uri_reader.rb +4 -4
  92. data/lib/aspera/web_auth.rb +14 -13
  93. data.tar.gz.sig +0 -0
  94. metadata +11 -36
  95. metadata.gz.sig +0 -0
@@ -3,6 +3,7 @@
3
3
  require 'aspera/fasp/transfer_spec'
4
4
  require 'aspera/cli/listener/logger'
5
5
  require 'aspera/cli/listener/progress_multi'
6
+ require 'aspera/cli/info'
6
7
 
7
8
  module Aspera
8
9
  module Cli
@@ -14,7 +15,7 @@ module Aspera
14
15
  FILE_LIST_FROM_ARGS = '@args'
15
16
  # special value for --sources : read file list from transfer spec (--ts)
16
17
  FILE_LIST_FROM_TRANSFER_SPEC = '@ts'
17
- FILE_LIST_OPTIONS=[FILE_LIST_FROM_ARGS,FILE_LIST_FROM_TRANSFER_SPEC,'Array'].freeze
18
+ FILE_LIST_OPTIONS = [FILE_LIST_FROM_ARGS, FILE_LIST_FROM_TRANSFER_SPEC, 'Array'].freeze
18
19
  DEFAULT_TRANSFER_NOTIF_TMPL = <<~END_OF_TEMPLATE
19
20
  From: <%=from_name%> <<%=from_email%>>
20
21
  To: <<%=to%>>
@@ -24,8 +25,10 @@ module Aspera
24
25
 
25
26
  <%=ts.to_yaml%>
26
27
  END_OF_TEMPLATE
27
- #% (formating bug in eclipse)
28
- private_constant :FILE_LIST_FROM_ARGS,:FILE_LIST_FROM_TRANSFER_SPEC,:FILE_LIST_OPTIONS,
28
+ # % (formating bug in eclipse)
29
+ private_constant :FILE_LIST_FROM_ARGS,
30
+ :FILE_LIST_FROM_TRANSFER_SPEC,
31
+ :FILE_LIST_OPTIONS,
29
32
  :DEFAULT_TRANSFER_NOTIF_TMPL
30
33
  TRANSFER_AGENTS = %i[direct node connect httpgw trsdk].freeze
31
34
 
@@ -39,8 +42,10 @@ module Aspera
39
42
  end
40
43
  end
41
44
 
45
+ attr_accessor :token_regenerator
46
+
42
47
  # @param env external objects: option manager, config file manager
43
- def initialize(opt_mgr,config)
48
+ def initialize(opt_mgr, config)
44
49
  @opt_mgr = opt_mgr
45
50
  @config = config
46
51
  # command line can override transfer spec
@@ -50,19 +55,22 @@ module Aspera
50
55
  @progress_listener = Listener::ProgressMulti.new
51
56
  # source/destination pair, like "paths" of transfer spec
52
57
  @transfer_paths = nil
53
- @opt_mgr.set_obj_attr(:ts,self,:option_transfer_spec)
54
- @opt_mgr.add_opt_simple(:ts,"override transfer spec values (Hash, use @json: prefix), current=#{@opt_mgr.get_option(:ts)}")
55
- @opt_mgr.add_opt_simple(:local_resume,"set resume policy (Hash, use @json: prefix), current=#{@opt_mgr.get_option(:local_resume)}")
56
- @opt_mgr.add_opt_simple(:to_folder,'destination folder for transfered files')
57
- @opt_mgr.add_opt_simple(:sources,"how list of transfered files is provided (#{FILE_LIST_OPTIONS.join(',')})")
58
- @opt_mgr.add_opt_list(:src_type,%i[list pair],'type of file list')
59
- @opt_mgr.add_opt_list(:transfer,TRANSFER_AGENTS,'type of transfer agent')
60
- @opt_mgr.add_opt_simple(:transfer_info,'parameters for transfer agent')
61
- @opt_mgr.add_opt_list(:progress,%i[none native multi],'type of progress bar')
62
- @opt_mgr.set_option(:transfer,:direct)
63
- @opt_mgr.set_option(:src_type,:list)
64
- @opt_mgr.set_option(:progress,:native) # use native ascp progress bar as it is more reliable
58
+ # only used with agent "direct" allows to regenerate the token if it is expired
59
+ @token_regenerator = nil
60
+ @opt_mgr.set_obj_attr(:ts, self, :option_transfer_spec)
61
+ @opt_mgr.add_opt_simple(:ts, "Override transfer spec values (Hash, e.g. use @json: prefix), current=#{@opt_mgr.get_option(:ts)}")
62
+ @opt_mgr.add_opt_simple(:to_folder, 'Destination folder for transfered files')
63
+ @opt_mgr.add_opt_simple(:sources, "How list of transfered files is provided (#{FILE_LIST_OPTIONS.join(',')})")
64
+ @opt_mgr.add_opt_simple(:ascp_opts, 'Options for ascp in its native format')
65
+ @opt_mgr.add_opt_list(:src_type, %i[list pair], 'Type of file list')
66
+ @opt_mgr.add_opt_list(:transfer, TRANSFER_AGENTS, 'Type of transfer agent')
67
+ @opt_mgr.add_opt_simple(:transfer_info, 'Parameters for transfer agent')
68
+ @opt_mgr.add_opt_list(:progress, %i[none native multi], 'Type of progress bar')
69
+ @opt_mgr.set_option(:transfer, :direct)
70
+ @opt_mgr.set_option(:src_type, :list)
71
+ @opt_mgr.set_option(:progress, :native) # use native ascp progress bar as it is more reliable
65
72
  @opt_mgr.parse_options!
73
+ Fasp::TransferSpec.ascp_opts_to_ts(@transfer_spec_cmdline, @opt_mgr.get_option(:ascp_opts))
66
74
  end
67
75
 
68
76
  def option_transfer_spec; @transfer_spec_cmdline; end
@@ -76,8 +84,8 @@ module Aspera
76
84
  @agent = instance
77
85
  @agent.add_listener(Listener::Logger.new)
78
86
  # use local progress bar if asked so, or if native and non local ascp (because only local ascp has native progress bar)
79
- if @opt_mgr.get_option(:progress,is_type: :mandatory).eql?(:multi) ||
80
- (@opt_mgr.get_option(:progress,is_type: :mandatory).eql?(:native) && !instance.class.to_s.eql?('Aspera::Fasp::AgentDirect'))
87
+ if @opt_mgr.get_option(:progress, is_type: :mandatory).eql?(:multi) ||
88
+ (@opt_mgr.get_option(:progress, is_type: :mandatory).eql?(:native) && !instance.class.to_s.eql?('Aspera::Fasp::AgentDirect'))
81
89
  @agent.add_listener(@progress_listener)
82
90
  end
83
91
  end
@@ -85,20 +93,20 @@ module Aspera
85
93
  # analyze options and create new agent if not already created or set
86
94
  def set_agent_by_options
87
95
  return nil unless @agent.nil?
88
- agent_type = @opt_mgr.get_option(:transfer,is_type: :mandatory)
96
+ agent_type = @opt_mgr.get_option(:transfer, is_type: :mandatory)
89
97
  # agent plugin is loaded on demand to avoid loading unnecessary dependencies
90
98
  require "aspera/fasp/agent_#{agent_type}"
91
99
  agent_options = @opt_mgr.get_option(:transfer_info)
92
- raise CliBadArgument,"the transfer agent configuration shall be Hash, not #{agent_options.class} (#{agent_options}), "\
93
- 'use either @json:<json> or @preset:<parameter set name>' unless [Hash,NilClass].include?(agent_options.class)
100
+ raise CliBadArgument, "the transfer agent configuration shall be Hash, not #{agent_options.class} (#{agent_options}), "\
101
+ 'use either @json:<json> or @preset:<parameter set name>' unless [Hash, NilClass].include?(agent_options.class)
94
102
  # special case
95
103
  if agent_type.eql?(:node) && agent_options.nil?
96
104
  param_set_name = @config.get_plugin_default_config_name(:node)
97
- raise CliBadArgument,"No default node configured, Please specify --#{:transfer_info.to_s.tr('_','-')}" if param_set_name.nil?
105
+ raise CliBadArgument, "No default node configured, Please specify --#{:transfer_info.to_s.tr('_', '-')}" if param_set_name.nil?
98
106
  agent_options = @config.preset_by_name(param_set_name)
99
107
  end
100
108
  # special case
101
- if agent_type.eql?(:direct) && @opt_mgr.get_option(:progress,is_type: :mandatory).eql?(:native)
109
+ if agent_type.eql?(:direct) && @opt_mgr.get_option(:progress, is_type: :mandatory).eql?(:native)
102
110
  agent_options = {} if agent_options.nil?
103
111
  agent_options[:quiet] = false
104
112
  end
@@ -135,106 +143,99 @@ module Aspera
135
143
  # return cache if set
136
144
  return @transfer_paths unless @transfer_paths.nil?
137
145
  # start with lower priority : get paths from transfer spec on command line
138
- @transfer_paths = @transfer_spec_cmdline['paths'] if @transfer_spec_cmdline.has_key?('paths')
146
+ @transfer_paths = @transfer_spec_cmdline['paths'] if @transfer_spec_cmdline.key?('paths')
139
147
  # is there a source list option ?
140
148
  file_list = @opt_mgr.get_option(:sources)
141
149
  case file_list
142
- when nil,FILE_LIST_FROM_ARGS
150
+ when nil, FILE_LIST_FROM_ARGS
143
151
  Log.log.debug('getting file list as parameters')
144
152
  # get remaining arguments
145
- file_list = @opt_mgr.get_next_argument('source file list',expected: :multiple)
146
- raise CliBadArgument,'specify at least one file on command line or use '\
153
+ file_list = @opt_mgr.get_next_argument('source file list', expected: :multiple)
154
+ raise CliBadArgument, 'specify at least one file on command line or use '\
147
155
  "--sources=#{FILE_LIST_FROM_TRANSFER_SPEC} to use transfer spec" if !file_list.is_a?(Array) || file_list.empty?
148
156
  when FILE_LIST_FROM_TRANSFER_SPEC
149
157
  Log.log.debug('assume list provided in transfer spec')
150
158
  special_case_direct_with_list =
151
- @opt_mgr.get_option(:transfer,is_type: :mandatory).eql?(:direct) &&
159
+ @opt_mgr.get_option(:transfer, is_type: :mandatory).eql?(:direct) &&
152
160
  Fasp::Parameters.ts_has_ascp_file_list(@transfer_spec_cmdline)
153
- raise CliBadArgument,'transfer spec on command line must have sources' if @transfer_paths.nil? && !special_case_direct_with_list
161
+ raise CliBadArgument, 'transfer spec on command line must have sources' if @transfer_paths.nil? && !special_case_direct_with_list
154
162
  # here we assume check of sources is made in transfer agent
155
163
  return @transfer_paths
156
164
  when Array
157
165
  Log.log.debug('getting file list as extended value')
158
- raise CliBadArgument,'sources must be a Array of String' if !file_list.reject{|f|f.is_a?(String)}.empty?
166
+ raise CliBadArgument, 'sources must be a Array of String' if !file_list.reject{|f|f.is_a?(String)}.empty?
159
167
  else
160
- raise CliBadArgument,"sources must be a Array, not #{file_list.class}"
168
+ raise CliBadArgument, "sources must be a Array, not #{file_list.class}"
161
169
  end
162
170
  # here, file_list is an Array or String
163
171
  if !@transfer_paths.nil?
164
172
  Log.log.warn('--sources overrides paths from --ts')
165
173
  end
166
- case @opt_mgr.get_option(:src_type,is_type: :mandatory)
174
+ case @opt_mgr.get_option(:src_type, is_type: :mandatory)
167
175
  when :list
168
176
  # when providing a list, just specify source
169
177
  @transfer_paths = file_list.map{|i|{'source' => i}}
170
178
  when :pair
171
- raise CliBadArgument,"When using pair, provide an even number of paths: #{file_list.length}" unless file_list.length.even?
172
- @transfer_paths = file_list.each_slice(2).to_a.map{|s,d|{'source' => s,'destination' => d}}
179
+ raise CliBadArgument, "When using pair, provide an even number of paths: #{file_list.length}" unless file_list.length.even?
180
+ @transfer_paths = file_list.each_slice(2).to_a.map{|s, d|{'source' => s, 'destination' => d}}
173
181
  else raise 'Unsupported src_type'
174
182
  end
175
- Log.log.debug("paths=#{@transfer_paths}")
183
+ Log.log.debug{"paths=#{@transfer_paths}"}
176
184
  return @transfer_paths
177
185
  end
178
186
 
179
187
  # start a transfer and wait for completion, plugins shall use this method
180
188
  # @param transfer_spec
181
- # @param tr_opts specific options for the transfer_agent
182
- # tr_opts[:src] specifies how destination_root is set (how transfer spec was generated)
183
- # other options are carried to specific agent
184
- def start(transfer_spec,tr_opts)
189
+ def start(transfer_spec)
185
190
  # check parameters
186
191
  raise 'transfer_spec must be hash' unless transfer_spec.is_a?(Hash)
187
- raise 'tr_opts must be hash' unless tr_opts.is_a?(Hash)
188
192
  # process :src option
189
193
  case transfer_spec['direction']
190
194
  when Fasp::TransferSpec::DIRECTION_RECEIVE
191
195
  # init default if required in any case
192
196
  @transfer_spec_cmdline['destination_root'] ||= destination_folder(transfer_spec['direction'])
193
197
  when Fasp::TransferSpec::DIRECTION_SEND
194
- case tr_opts[:src]
195
- when :direct
196
- # init default if required
197
- @transfer_spec_cmdline['destination_root'] ||= destination_folder(transfer_spec['direction'])
198
- when :node_gen3
198
+ if transfer_spec.dig('tags', 'aspera', 'node', 'access_key')
199
+ # gen4
200
+ @transfer_spec_cmdline.delete('destination_root') if @transfer_spec_cmdline.key?('destination_root_id')
201
+ elsif transfer_spec.key?('token')
202
+ # gen3
199
203
  # in that case, destination is set in return by application (API/upload_setup)
200
204
  # but to_folder was used in initial API call
201
205
  @transfer_spec_cmdline.delete('destination_root')
202
- when :node_gen4
203
- @transfer_spec_cmdline.delete('destination_root') if @transfer_spec_cmdline.has_key?('destination_root_id')
204
206
  else
205
- raise StandardError,"InternalError: unsupported value: #{tr_opts[:src]}"
207
+ # init default if required
208
+ @transfer_spec_cmdline['destination_root'] ||= destination_folder(transfer_spec['direction'])
206
209
  end
207
210
  end
208
-
209
- # only used here
210
- tr_opts.delete(:src)
211
-
212
211
  # update command line paths, unless destination already has one
213
212
  @transfer_spec_cmdline['paths'] = transfer_spec['paths'] || ts_source_paths
214
-
215
213
  transfer_spec.merge!(@transfer_spec_cmdline)
214
+ # remove values that are nil (user wants to delete)
215
+ transfer_spec.delete_if { |_key, value| value.nil? }
216
216
  # create transfer agent
217
217
  set_agent_by_options
218
- Log.log.debug("transfer agent is a #{@agent.class}")
219
- @agent.start_transfer(transfer_spec,tr_opts)
218
+ Log.log.debug{"transfer agent is a #{@agent.class}"}
219
+ @agent.token_regenerator = @token_regenerator if @agent.respond_to?(:token_regenerator=)
220
+ @agent.start_transfer(transfer_spec)
220
221
  # list of : :success or error message
221
222
  result = @agent.wait_for_transfers_completion
222
223
  @progress_listener.reset
223
224
  Fasp::AgentBase.validate_status_list(result)
224
- send_email_transfer_notification(transfer_spec,result)
225
+ send_email_transfer_notification(transfer_spec, result)
225
226
  return result
226
227
  end
227
228
 
228
- def send_email_transfer_notification(transfer_spec,statuses)
229
+ def send_email_transfer_notification(transfer_spec, statuses)
229
230
  return if @opt_mgr.get_option(:notif_to).nil?
230
231
  global_status = self.class.session_status(statuses)
231
232
  email_vars = {
232
233
  global_transfer_status: global_status,
233
- subject: "ascli transfer: #{global_status}",
234
+ subject: "#{PROGRAM_NAME} transfer: #{global_status}",
234
235
  body: "Transfer is: #{global_status}",
235
236
  ts: transfer_spec
236
237
  }
237
- @config.send_email_template(email_vars,DEFAULT_TRANSFER_NOTIF_TMPL)
238
+ @config.send_email_template(email_template_default: DEFAULT_TRANSFER_NOTIF_TMPL, values: email_vars)
238
239
  end
239
240
 
240
241
  # shut down if agent requires it
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Aspera
4
4
  module Cli
5
- VERSION = '4.9.0'
5
+ VERSION = '4.11.0'
6
6
  end
7
7
  end
data/lib/aspera/colors.rb CHANGED
@@ -5,7 +5,7 @@ class String
5
5
  class << self
6
6
  private
7
7
 
8
- def vtcmd(code);"\e[#{code}m";end
8
+ def vtcmd(code); "\e[#{code}m"; end
9
9
  end
10
10
  # see https://en.wikipedia.org/wiki/ANSI_escape_code
11
11
  # symbol is the method name added to String
@@ -35,11 +35,11 @@ class String
35
35
  }.freeze
36
36
  private_constant :VTSTYLES
37
37
  # defines methods to String, one per entry in VTSTYLES
38
- VTSTYLES.each do |name,code|
38
+ VTSTYLES.each do |name, code|
39
39
  if $stderr.tty?
40
40
  begin_seq = vtcmd(code)
41
41
  end_code = 0 # by default reset all
42
- if code <= 7 then 20 + code
42
+ if code <= 7 then code + 20
43
43
  elsif code <= 37 then 39
44
44
  elsif code <= 47 then 49
45
45
  end
@@ -7,8 +7,8 @@ module Aspera
7
7
  # add_env_args is called to get resulting param list and env var (also checks that all params were used)
8
8
  class CommandLineBuilder
9
9
  # parameter with onne of those tags is an ascp command line option with --
10
- CLTYPE_OPTIONS=%i[opt_without_arg opt_with_arg].freeze
11
- class<<self
10
+ CLTYPE_OPTIONS = %i[opt_without_arg opt_with_arg].freeze
11
+ class << self
12
12
  # transform yes/no to true/false
13
13
  def yes_to_true(value)
14
14
  case value
@@ -20,21 +20,21 @@ module Aspera
20
20
 
21
21
  # Called by provider of definition before constructor of this class so that params_definition has all mandatory fields
22
22
  def normalize_description(d)
23
- d.each do |param_name,options|
23
+ d.each do |param_name, options|
24
24
  raise "Expecting Hash, but have #{options.class} in #{param_name}" unless options.is_a?(Hash)
25
- #options[:accepted_types]=:bool if options[:cltype].eql?(:envvar) and !options.has_key?(:accepted_types)
25
+ # options[:accepted_types]=:bool if options[:cltype].eql?(:envvar) and !options.has_key?(:accepted_types)
26
26
  # by default : not mandatory
27
27
  options[:mandatory] ||= false
28
28
  options[:desc] ||= ''
29
29
  # by default : string, unless it's without arg
30
- if !options.has_key?(:accepted_types)
30
+ if !options.key?(:accepted_types)
31
31
  options[:accepted_types] = options[:cltype].eql?(:opt_without_arg) ? :bool : :string
32
32
  end
33
33
  # single type is placed in array
34
34
  options[:accepted_types] = [options[:accepted_types]] unless options[:accepted_types].is_a?(Array)
35
35
  # add default switch name if not present
36
- if !options.has_key?(:clswitch) && options.has_key?(:cltype) && CLTYPE_OPTIONS.include?(options[:cltype])
37
- options[:clswitch] = '--' + param_name.to_s.tr('_','-')
36
+ if !options.key?(:clswitch) && options.key?(:cltype) && CLTYPE_OPTIONS.include?(options[:cltype])
37
+ options[:clswitch] = '--' + param_name.to_s.tr('_', '-')
38
38
  end
39
39
  end
40
40
  end
@@ -43,7 +43,7 @@ module Aspera
43
43
  private
44
44
 
45
45
  # clvarname : command line variable name
46
- def env_name(_param_name,options)
46
+ def env_name(_param_name, options)
47
47
  return options[:clvarname]
48
48
  end
49
49
 
@@ -52,7 +52,7 @@ module Aspera
52
52
  attr_reader :params_definition
53
53
 
54
54
  # @param param_hash
55
- def initialize(param_hash,params_definition)
55
+ def initialize(param_hash, params_definition)
56
56
  @param_hash = param_hash # keep reference so that it can be modified by caller before calling `process_params`
57
57
  @params_definition = params_definition
58
58
  @result_env = {}
@@ -62,13 +62,13 @@ module Aspera
62
62
 
63
63
  def warn_unrecognized_params
64
64
  # warn about non translated arguments
65
- @param_hash.each_pair{|key,val|Log.log.warn("unrecognized parameter: #{key} = \"#{val}\"") if !@used_param_names.include?(key)}
65
+ @param_hash.each_pair{|key, val|Log.log.warn{"unrecognized parameter: #{key} = \"#{val}\""} if !@used_param_names.include?(key)}
66
66
  end
67
67
 
68
68
  # adds keys :env :args with resulting values after processing
69
69
  # warns if some parameters were not used
70
- def add_env_args(env,args)
71
- Log.log.debug("ENV=#{@result_env}, ARGS=#{@result_args}")
70
+ def add_env_args(env, args)
71
+ Log.log.debug{"ENV=#{@result_env}, ARGS=#{@result_args}"}
72
72
  warn_unrecognized_params
73
73
  env.merge!(@result_env)
74
74
  args.push(*@result_args)
@@ -82,7 +82,7 @@ module Aspera
82
82
  end
83
83
 
84
84
  def process_params
85
- @params_definition.keys.each do |k|
85
+ @params_definition.each_key do |k|
86
86
  process_param(k)
87
87
  end
88
88
  end
@@ -91,19 +91,19 @@ module Aspera
91
91
  # @param param_name : key in transfer spec
92
92
  # @param action : type of processing: ignore getvalue envvar opt_without_arg opt_with_arg defer
93
93
  # @param options : options for type
94
- def process_param(param_name,action=nil)
94
+ def process_param(param_name, action=nil)
95
95
  options = @params_definition[param_name]
96
96
  # should not happen
97
97
  if options.nil?
98
- Log.log.warn("Unknown parameter #{param_name}")
98
+ Log.log.warn{"Unknown parameter #{param_name}"}
99
99
  return
100
100
  end
101
101
  action = options[:cltype] if action.nil?
102
102
  # check mandatory parameter (nil is valid value)
103
- raise Fasp::Error, "Missing mandatory parameter: #{param_name}" if options[:mandatory] && !@param_hash.has_key?(param_name)
103
+ raise Fasp::Error, "Missing mandatory parameter: #{param_name}" if options[:mandatory] && !@param_hash.key?(param_name)
104
104
  parameter_value = @param_hash[param_name]
105
105
 
106
- #parameter_value=options[:default] if parameter_value.nil? and options.has_key?(:default)
106
+ # parameter_value=options[:default] if parameter_value.nil? and options.has_key?(:default)
107
107
 
108
108
  # Check parameter type
109
109
  expected_classes = options[:accepted_types].map do |s|
@@ -112,11 +112,11 @@ module Aspera
112
112
  when :array then Array
113
113
  when :hash then Hash
114
114
  when :int then Integer
115
- when :bool then [TrueClass,FalseClass]
115
+ when :bool then [TrueClass, FalseClass]
116
116
  else raise "INTERNAL: unexpected value: #{s}"
117
117
  end
118
118
  end.flatten
119
- raise Fasp::Error,"#{param_name} is : #{parameter_value.class} (#{parameter_value}), shall be #{options[:accepted_types]}, " \
119
+ raise Fasp::Error, "#{param_name} is : #{parameter_value.class} (#{parameter_value}), shall be #{options[:accepted_types]}, " \
120
120
  unless parameter_value.nil? || expected_classes.include?(parameter_value.class)
121
121
  @used_param_names.push(param_name) unless action.eql?(:defer)
122
122
 
@@ -124,7 +124,7 @@ module Aspera
124
124
  return nil if parameter_value.nil?
125
125
 
126
126
  # check that value is of an accepted type (string, int bool)
127
- raise "Value #{parameter_value} is not allowed for #{param_name}" if options.has_key?(:enum) && !options[:enum].include?(parameter_value)
127
+ raise "Value #{parameter_value} is not allowed for #{param_name}" if options.key?(:enum) && !options[:enum].include?(parameter_value)
128
128
 
129
129
  # convert some values if value on command line needs processing from value in structure
130
130
  case options[:clconvert]
@@ -135,8 +135,8 @@ module Aspera
135
135
  parameter_value = new_value
136
136
  when String
137
137
  # :clconvert has name of class and encoding method
138
- convclass,convmethod = options[:clconvert].split('.')
139
- newvalue = Kernel.const_get(convclass).send(convmethod,parameter_value)
138
+ convclass, convmethod = options[:clconvert].split('.')
139
+ newvalue = Kernel.const_get(convclass).send(convmethod, parameter_value)
140
140
  raise Fasp::Error, "unsupported #{param_name}: #{parameter_value}" if newvalue.nil?
141
141
  parameter_value = newvalue
142
142
  when NilClass
@@ -144,13 +144,13 @@ module Aspera
144
144
  end
145
145
 
146
146
  case action
147
- when :ignore,:defer # ignore this parameter or process later
147
+ when :ignore, :defer # ignore this parameter or process later
148
148
  return
149
149
  when :get_value # just get value
150
150
  return parameter_value
151
151
  when :envvar # set in env var
152
152
  # define ascp parameter in env var from transfer spec
153
- @result_env[env_name(param_name,options)] = parameter_value
153
+ @result_env[env_name(param_name, options)] = parameter_value
154
154
  when :opt_without_arg # if present and true : just add option without value
155
155
  add_param = false
156
156
  case parameter_value
@@ -161,12 +161,12 @@ module Aspera
161
161
  add_param = !add_param if options[:add_on_false]
162
162
  add_command_line_options([options[:clswitch]]) if add_param
163
163
  when :opt_with_arg # transform into command line option with value
164
- #parameter_value=parameter_value.to_s if parameter_value.is_a?(Integer)
164
+ # parameter_value=parameter_value.to_s if parameter_value.is_a?(Integer)
165
165
  parameter_value = [parameter_value] unless parameter_value.is_a?(Array)
166
166
  # if transfer_spec value is an array, applies option many times
167
- parameter_value.each{|v|add_command_line_options([options[:clswitch],v])}
167
+ parameter_value.each{|v|add_command_line_options([options[:clswitch], v])}
168
168
  when NilClass
169
- Log.log.debug("Ignoring parameter: #{param_name}")
169
+ Log.log.debug{"Ignoring parameter: #{param_name}"}
170
170
  else
171
171
  raise "ERROR: unknown action: #{action}/#{action.class}"
172
172
  end
@@ -5,19 +5,19 @@ require 'aspera/rest'
5
5
  require 'xmlsimple'
6
6
 
7
7
  module Aspera
8
- class CosNode < Rest
8
+ class CosNode < Aspera::Node
9
9
  class << self
10
- def parameters_from_svc_creds(service_credentials,bucket_region)
10
+ def parameters_from_svc_creds(service_credentials, bucket_region)
11
11
  # check necessary contents
12
12
  raise 'service_credentials must be a Hash' unless service_credentials.is_a?(Hash)
13
13
  %w[apikey resource_instance_id endpoints].each do |field|
14
- raise "service_credentials must have a field: #{field}" unless service_credentials.has_key?(field)
14
+ raise "service_credentials must have a field: #{field}" unless service_credentials.key?(field)
15
15
  end
16
- Aspera::Log.dump('service_credentials',service_credentials)
16
+ Aspera::Log.dump('service_credentials', service_credentials)
17
17
  # read endpoints from service provided in service credentials
18
18
  endpoints = Aspera::Rest.new({base_url: service_credentials['endpoints']}).read('')[:data]
19
- Aspera::Log.dump('endpoints',endpoints)
20
- storage_endpoint = endpoints.dig('service-endpoints','regional',bucket_region,'public',bucket_region)
19
+ Aspera::Log.dump('endpoints', endpoints)
20
+ storage_endpoint = endpoints.dig('service-endpoints', 'regional', bucket_region, 'public', bucket_region)
21
21
  raise "no such region: #{bucket_region}" if storage_endpoint.nil?
22
22
  return {
23
23
  instance_id: service_credentials['resource_instance_id'],
@@ -28,8 +28,8 @@ module Aspera
28
28
  end
29
29
  IBM_CLOUD_TOKEN_URL = 'https://iam.cloud.ibm.com/identity'
30
30
  TOKEN_FIELD = 'delegated_refresh_token'
31
- attr_reader :add_ts
32
- def initialize(bucket_name,storage_endpoint,instance_id,api_key,auth_url=IBM_CLOUD_TOKEN_URL)
31
+
32
+ def initialize(bucket_name, storage_endpoint, instance_id, api_key, auth_url= IBM_CLOUD_TOKEN_URL)
33
33
  @auth_url = auth_url
34
34
  @api_key = api_key
35
35
  s3_api = Aspera::Rest.new({
@@ -53,18 +53,20 @@ module Aspera
53
53
  url_params: {'faspConnectionInfo' => nil}
54
54
  )[:http].body
55
55
  ats_info = XmlSimple.xml_in(xml_result_text, {'ForceArray' => false})
56
- Aspera::Log.dump('ats_info',ats_info)
57
- super({
58
- base_url: ats_info['ATSEndpoint'],
59
- auth: {
60
- type: :basic,
61
- username: ats_info['AccessKey']['Id'],
62
- password: ats_info['AccessKey']['Secret']}})
63
- # prepare transfer spec addition
64
- @add_ts = {'tags' => {'aspera' => {'node' => {'storage_credentials' => {
56
+ Aspera::Log.dump('ats_info', ats_info)
57
+ @storage_credentials = {
65
58
  'type' => 'token',
66
59
  'token' => {TOKEN_FIELD => nil}
67
- }}}}}
60
+ }
61
+ super(
62
+ params: {
63
+ base_url: ats_info['ATSEndpoint'],
64
+ auth: {
65
+ type: :basic,
66
+ username: ats_info['AccessKey']['Id'],
67
+ password: ats_info['AccessKey']['Secret']}},
68
+ add_tspec: {'tags'=>{'aspera'=>{'node'=>{'storage_credentials'=>@storage_credentials}}}})
69
+ # update storage_credentials AND Rest params
68
70
  generate_token
69
71
  end
70
72
 
@@ -83,8 +85,8 @@ module Aspera
83
85
  receiver_client_ids: 'aspera_ats'
84
86
  }})
85
87
  # get delegated token to be placed in rest call header and in transfer tags
86
- @add_ts['tags']['aspera']['node']['storage_credentials']['token'][TOKEN_FIELD] = delegated_oauth.get_authorization.gsub(/^Bearer /,'')
87
- @params[:headers] = {'X-Aspera-Storage-Credentials' => JSON.generate(@add_ts['tags']['aspera']['node']['storage_credentials'])}
88
+ @storage_credentials['token'][TOKEN_FIELD] = delegated_oauth.get_authorization.gsub(/^Bearer /, '')
89
+ @params[:headers] = {'X-Aspera-Storage-Credentials' => JSON.generate(@storage_credentials)}
88
90
  end
89
91
  end
90
92
  end
@@ -9,7 +9,7 @@ module Aspera
9
9
  include Singleton
10
10
  # get binary value from data repository
11
11
  def data(id)
12
- File.read(File.join(__dir__,'data',id.to_s),mode: 'rb')
12
+ File.read(File.join(__dir__, 'data', id.to_s), mode: 'rb')
13
13
  end
14
14
  end
15
15
  end
@@ -10,12 +10,16 @@ module Aspera
10
10
  OS_X = :osx
11
11
  OS_LINUX = :linux
12
12
  OS_AIX = :aix
13
- OS_LIST = [OS_WINDOWS,OS_X,OS_LINUX,OS_AIX].freeze
13
+ OS_LIST = [OS_WINDOWS, OS_X, OS_LINUX, OS_AIX].freeze
14
14
  CPU_X86_64 = :x86_64
15
15
  CPU_PPC64 = :ppc64
16
16
  CPU_PPC64LE = :ppc64le
17
17
  CPU_S390 = :s390
18
- CPU_LIST = [CPU_X86_64,CPU_PPC64,CPU_PPC64LE,CPU_S390].freeze
18
+ CPU_LIST = [CPU_X86_64, CPU_PPC64, CPU_PPC64LE, CPU_S390].freeze
19
+
20
+ BITS_PER_BYTE = 8
21
+ MEBI = 1024 * 1024
22
+ BYTES_PER_MEBIBIT = MEBI / BITS_PER_BYTE
19
23
 
20
24
  class << self
21
25
  def ruby_version
@@ -24,9 +28,9 @@ module Aspera
24
28
 
25
29
  def os
26
30
  case RbConfig::CONFIG['host_os']
27
- when /mswin/,/msys/,/mingw/,/cygwin/,/bccwin/,/wince/,/emc/
31
+ when /mswin/, /msys/, /mingw/, /cygwin/, /bccwin/, /wince/, /emc/
28
32
  return OS_WINDOWS
29
- when /darwin/,/mac os/
33
+ when /darwin/, /mac os/
30
34
  return OS_X
31
35
  when /linux/
32
36
  return OS_LINUX
@@ -39,9 +43,9 @@ module Aspera
39
43
 
40
44
  def cpu
41
45
  case RbConfig::CONFIG['host_cpu']
42
- when /x86_64/,/x64/
46
+ when /x86_64/, /x64/
43
47
  return CPU_X86_64
44
- when /powerpc/,/ppc64/
48
+ when /powerpc/, /ppc64/
45
49
  return CPU_PPC64LE if os.eql?(OS_LINUX)
46
50
  return CPU_PPC64
47
51
  when /s390/
@@ -65,9 +69,9 @@ module Aspera
65
69
  # on Windows, the env var %USERPROFILE% provides the path to user's home more reliably than %HOMEDRIVE%%HOMEPATH%
66
70
  # so, tell Ruby the right way
67
71
  def fix_home
68
- return unless os.eql?(OS_WINDOWS) && ENV.has_key?('USERPROFILE') && Dir.exist?(ENV['USERPROFILE'])
72
+ return unless os.eql?(OS_WINDOWS) && ENV.key?('USERPROFILE') && Dir.exist?(ENV['USERPROFILE'])
69
73
  ENV['HOME'] = ENV['USERPROFILE']
70
- Log.log.debug("Windows: set home to USERPROFILE: #{ENV['HOME']}")
74
+ Log.log.debug{"Windows: set home to USERPROFILE: #{ENV['HOME']}"}
71
75
  end
72
76
 
73
77
  def empty_binding
@@ -76,19 +80,35 @@ module Aspera
76
80
 
77
81
  # secure execution of Ruby code
78
82
  def secure_eval(code)
79
- Kernel.send('lave'.reverse,code,empty_binding, __FILE__, __LINE__)
83
+ Kernel.send('lave'.reverse, code, empty_binding, __FILE__, __LINE__)
80
84
  end
81
85
 
82
86
  # value is provided in block
83
- def write_file_restricted(path,force: false)
87
+ def write_file_restricted(path, force: false)
84
88
  raise 'coding error, missing content block' unless block_given?
85
89
  if force || !File.exist?(path)
86
90
  File.unlink(path) rescue nil # Windows may give error
87
- File.write(path,yield)
88
- File.chmod(0400,path)
91
+ File.write(path, yield)
92
+ restrict_file_access(path)
89
93
  end
90
94
  return path
91
95
  end
92
- end
93
- end
94
- end
96
+
97
+ def restrict_file_access(path, mode: nil)
98
+ if mode.nil?
99
+ # or FileUtils ?
100
+ if File.file?(path)
101
+ mode = 0o600
102
+ elsif File.directory?(path)
103
+ mode = 0o700
104
+ else
105
+ Log.log.debug{"No restriction can be set for #{path}"}
106
+ end
107
+ end
108
+ File.chmod(mode, path) unless mode.nil?
109
+ rescue => e
110
+ Log.log.warn(e.message)
111
+ end
112
+ end # self
113
+ end # Environment
114
+ end # Aspera