aspera-cli 4.5.0 → 4.8.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 (104) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -0
  3. data/README.md +1894 -1574
  4. data/bin/ascli +21 -1
  5. data/bin/asession +38 -34
  6. data/docs/test_env.conf +14 -3
  7. data/examples/aoc.rb +17 -15
  8. data/examples/dascli +26 -0
  9. data/examples/faspex4.rb +42 -35
  10. data/examples/proxy.pac +1 -1
  11. data/examples/transfer.rb +38 -37
  12. data/lib/aspera/aoc.rb +245 -205
  13. data/lib/aspera/ascmd.rb +111 -90
  14. data/lib/aspera/ats_api.rb +16 -14
  15. data/lib/aspera/cli/basic_auth_plugin.rb +19 -18
  16. data/lib/aspera/cli/extended_value.rb +50 -39
  17. data/lib/aspera/cli/formater.rb +161 -135
  18. data/lib/aspera/cli/info.rb +18 -0
  19. data/lib/aspera/cli/listener/line_dump.rb +4 -2
  20. data/lib/aspera/cli/listener/logger.rb +3 -1
  21. data/lib/aspera/cli/listener/progress.rb +20 -21
  22. data/lib/aspera/cli/listener/progress_multi.rb +29 -31
  23. data/lib/aspera/cli/main.rb +194 -183
  24. data/lib/aspera/cli/manager.rb +213 -206
  25. data/lib/aspera/cli/plugin.rb +71 -49
  26. data/lib/aspera/cli/plugins/alee.rb +8 -7
  27. data/lib/aspera/cli/plugins/aoc.rb +675 -558
  28. data/lib/aspera/cli/plugins/ats.rb +116 -109
  29. data/lib/aspera/cli/plugins/bss.rb +35 -34
  30. data/lib/aspera/cli/plugins/config.rb +722 -542
  31. data/lib/aspera/cli/plugins/console.rb +28 -22
  32. data/lib/aspera/cli/plugins/cos.rb +28 -37
  33. data/lib/aspera/cli/plugins/faspex.rb +281 -227
  34. data/lib/aspera/cli/plugins/faspex5.rb +129 -84
  35. data/lib/aspera/cli/plugins/node.rb +426 -232
  36. data/lib/aspera/cli/plugins/orchestrator.rb +106 -98
  37. data/lib/aspera/cli/plugins/preview.rb +196 -191
  38. data/lib/aspera/cli/plugins/server.rb +131 -126
  39. data/lib/aspera/cli/plugins/shares.rb +49 -36
  40. data/lib/aspera/cli/plugins/sync.rb +27 -28
  41. data/lib/aspera/cli/transfer_agent.rb +84 -79
  42. data/lib/aspera/cli/version.rb +3 -1
  43. data/lib/aspera/colors.rb +37 -28
  44. data/lib/aspera/command_line_builder.rb +84 -63
  45. data/lib/aspera/cos_node.rb +68 -34
  46. data/lib/aspera/data_repository.rb +4 -2
  47. data/lib/aspera/environment.rb +61 -46
  48. data/lib/aspera/fasp/agent_base.rb +36 -31
  49. data/lib/aspera/fasp/agent_connect.rb +44 -37
  50. data/lib/aspera/fasp/agent_direct.rb +101 -104
  51. data/lib/aspera/fasp/agent_httpgw.rb +91 -90
  52. data/lib/aspera/fasp/agent_node.rb +36 -33
  53. data/lib/aspera/fasp/agent_trsdk.rb +28 -31
  54. data/lib/aspera/fasp/error.rb +3 -1
  55. data/lib/aspera/fasp/error_info.rb +81 -54
  56. data/lib/aspera/fasp/installation.rb +171 -151
  57. data/lib/aspera/fasp/listener.rb +2 -0
  58. data/lib/aspera/fasp/parameters.rb +105 -111
  59. data/lib/aspera/fasp/parameters.yaml +305 -249
  60. data/lib/aspera/fasp/resume_policy.rb +20 -20
  61. data/lib/aspera/fasp/transfer_spec.rb +27 -0
  62. data/lib/aspera/fasp/uri.rb +31 -29
  63. data/lib/aspera/faspex_gw.rb +95 -118
  64. data/lib/aspera/hash_ext.rb +12 -13
  65. data/lib/aspera/id_generator.rb +11 -9
  66. data/lib/aspera/keychain/encrypted_hash.rb +73 -57
  67. data/lib/aspera/keychain/macos_security.rb +27 -29
  68. data/lib/aspera/log.rb +40 -39
  69. data/lib/aspera/nagios.rb +24 -22
  70. data/lib/aspera/node.rb +38 -30
  71. data/lib/aspera/oauth.rb +217 -248
  72. data/lib/aspera/open_application.rb +9 -7
  73. data/lib/aspera/persistency_action_once.rb +15 -14
  74. data/lib/aspera/persistency_folder.rb +15 -18
  75. data/lib/aspera/preview/file_types.rb +266 -270
  76. data/lib/aspera/preview/generator.rb +94 -92
  77. data/lib/aspera/preview/image_error.png +0 -0
  78. data/lib/aspera/preview/options.rb +20 -17
  79. data/lib/aspera/preview/utils.rb +99 -102
  80. data/lib/aspera/preview/video_error.png +0 -0
  81. data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
  82. data/lib/aspera/proxy_auto_config.rb +114 -21
  83. data/lib/aspera/rest.rb +144 -142
  84. data/lib/aspera/rest_call_error.rb +3 -2
  85. data/lib/aspera/rest_error_analyzer.rb +31 -31
  86. data/lib/aspera/rest_errors_aspera.rb +18 -16
  87. data/lib/aspera/secret_hider.rb +68 -0
  88. data/lib/aspera/ssh.rb +20 -16
  89. data/lib/aspera/sync.rb +57 -54
  90. data/lib/aspera/temp_file_manager.rb +20 -14
  91. data/lib/aspera/timer_limiter.rb +10 -8
  92. data/lib/aspera/uri_reader.rb +14 -15
  93. data/lib/aspera/web_auth.rb +85 -80
  94. data.tar.gz.sig +0 -0
  95. metadata +169 -40
  96. metadata.gz.sig +2 -0
  97. data/bin/dascli +0 -13
  98. data/docs/Makefile +0 -63
  99. data/docs/README.erb.md +0 -4221
  100. data/docs/README.md +0 -13
  101. data/docs/diagrams.txt +0 -49
  102. data/docs/doc_tools.rb +0 -58
  103. data/lib/aspera/cli/plugins/shares2.rb +0 -114
  104. data/lib/aspera/fasp/default.rb +0 -17
data/lib/aspera/ascmd.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'aspera/log'
2
4
 
3
5
  module Aspera
@@ -7,7 +9,7 @@ module Aspera
7
9
  # Note: "ls" can take filters: as_ls -f *.txt -f *.bin /
8
10
  class AsCmd
9
11
  # list of supported actions
10
- OPERATIONS=[:ls,:rm,:mv,:du,:info,:mkdir,:cp,:df,:md5sum]
12
+ OPERATIONS = %i[ls rm mv du info mkdir cp df md5sum].freeze
11
13
 
12
14
  # @param command_executor [Object] provides the "execute" method, taking a command to execute, and stdin to feed to it, typically: ssh or local
13
15
  def initialize(command_executor)
@@ -20,132 +22,151 @@ module Aspera
20
22
  # @return result of command, type depends on command (bool, array, hash)
21
23
  def execute_single(action_sym,args=nil)
22
24
  # concatenate arguments, enclose in double quotes, protect backslash and double quotes, add "as_" command and as_exit
23
- stdin_input=(args||[]).map{|v| '"' + v.gsub(/["\\]/n) {|s| '\\' + s } + '"'}.unshift('as_'+action_sym.to_s).join(' ')+"\nas_exit\n"
25
+ stdin_input = (args || []).map{|v| '"' + v.gsub(/["\\]/n) {|s| '\\' + s } + '"'}.unshift('as_' + action_sym.to_s).join(' ') + "\nas_exit\n"
24
26
  # execute, get binary output
25
- bytebuffer=@command_executor.execute('ascmd',stdin_input).unpack('C*')
27
+ bytebuffer = @command_executor.execute('ascmd',stdin_input).unpack('C*')
26
28
  # get hash or table result
27
- result=self.class.parse(bytebuffer,:result)
28
- raise "ERROR: unparsed bytes remaining" unless bytebuffer.empty?
29
+ result = self.class.parse(bytebuffer,:result)
30
+ raise 'ERROR: unparsed bytes remaining' unless bytebuffer.empty?
29
31
  # get and delete info,always present in results
30
- system_info=result[:info]
32
+ system_info = result[:info]
31
33
  result.delete(:info)
32
34
  # make single file result like a folder
33
- if result.has_key?(:file);result[:dir]=[result[:file]];result.delete(:file);end
35
+ if result.has_key?(:file);result[:dir] = [result[:file]];result.delete(:file);end
34
36
  # add type field for stats
35
37
  if result.has_key?(:dir)
36
38
  result[:dir].each do |file|
37
39
  if file.has_key?(:smode)
38
40
  # Converts the first character of the file mode (see 'man ls') into a type.
39
- file[:type]=case file[:smode][0,1];when'd';:directory;when'-';:file;when'l';:link;else;:other;end
41
+ file[:type] = case file[:smode][0,1];when 'd' then:directory;when '-' then:file;when 'l' then:link;else;:other;end
40
42
  end
41
43
  end
42
44
  end
43
45
  # for info, second overrides first, so restore it
44
- case result.keys.length;when 0;result=system_info;when 1;result=result[result.keys.first];else raise "error";end
46
+ case result.keys.length;when 0 then result = system_info;when 1 then result = result[result.keys.first];else raise 'error';end
45
47
  # raise error as exception
46
- raise Error.new(result[:errno],result[:errstr],action_sym,args) if result.is_a?(Hash) and result.keys.sort == TYPES_DESCR[:error][:fields].map{|i|i[:name]}.sort
48
+ raise Error.new(result[:errno],result[:errstr],action_sym,args) if
49
+ result.is_a?(Hash) && (result.keys.sort == TYPES_DESCR[:error][:fields].map{|i|i[:name]}.sort)
47
50
  return result
48
51
  end # execute_single
49
52
 
50
53
  # This exception is raised when +ascmd+ returns an error.
51
54
  class Error < StandardError
52
55
  attr_reader :errno, :errstr, :command, :args
53
- def initialize(errno,errstr,cmd,args);@errno=errno;@errstr=errstr;@command=cmd;@args=args;end
56
+ def initialize(errno,errstr,cmd,args);super();@errno = errno;@errstr = errstr;@command = cmd;@args = args;end
54
57
 
55
58
  def message; "ascmd: (#{errno}) #{errstr}"; end
56
59
 
57
60
  def extended_message; "ascmd: errno=#{errno} errstr=\"#{errstr}\" command=\"#{command}\" args=#{args}"; end
58
61
  end # Error
59
62
 
60
- private
61
-
62
63
  # description of result structures (see ascmdtypes.h). Base types are big endian
63
64
  # key = name of type
64
- TYPES_DESCR={
65
- :result =>{:decode=>:field_list,:fields=>[{:name=>:file,:is_a=>:stat},{:name=>:dir,:is_a=>:stat,:special=>:substruct},{:name=>:size,:is_a=>:size},{:name=>:error,:is_a=>:error},{:name=>:info,:is_a=>:info},{:name=>:success,:is_a=>nil,:special=>:return_true},{:name=>:exit,:is_a=>nil},{:name=>:df,:is_a=>:mnt,:special=>:restart_on_first},{:name=>:md5sum,:is_a=>:md5sum}]},
66
- :stat =>{:decode=>:field_list,:fields=>[{:name=>:name,:is_a=>:zstr},{:name=>:size,:is_a=>:int64},{:name=>:mode,:is_a=>:int32,:check=>nil},{:name=>:zmode,:is_a=>:zstr},{:name=>:uid,:is_a=>:int32,:check=>nil},{:name=>:zuid,:is_a=>:zstr},{:name=>:gid,:is_a=>:int32,:check=>nil},{:name=>:zgid,:is_a=>:zstr},{:name=>:ctime,:is_a=>:epoch},{:name=>:zctime,:is_a=>:zstr},{:name=>:mtime,:is_a=>:epoch},{:name=>:zmtime,:is_a=>:zstr},{:name=>:atime,:is_a=>:epoch},{:name=>:zatime,:is_a=>:zstr},{:name=>:symlink,:is_a=>:zstr},{:name=>:errno,:is_a=>:int32},{:name=>:errstr,:is_a=>:zstr}]},
67
- :info =>{:decode=>:field_list,:fields=>[{:name=>:platform,:is_a=>:zstr},{:name=>:version,:is_a=>:zstr},{:name=>:lang,:is_a=>:zstr},{:name=>:territory,:is_a=>:zstr},{:name=>:codeset,:is_a=>:zstr},{:name=>:lc_ctype,:is_a=>:zstr},{:name=>:lc_numeric,:is_a=>:zstr},{:name=>:lc_time,:is_a=>:zstr},{:name=>:lc_all,:is_a=>:zstr},{:name=>:dev,:is_a=>:zstr,:special=>:multiple},{:name=>:browse_caps,:is_a=>:zstr},{:name=>:protocol,:is_a=>:zstr}]},
68
- :size =>{:decode=>:field_list,:fields=>[{:name=>:size,:is_a=>:int64},{:name=>:fcount,:is_a=>:int32},{:name=>:dcount,:is_a=>:int32},{:name=>:failed_fcount,:is_a=>:int32},{:name=>:failed_dcount,:is_a=>:int32}]},
69
- :error =>{:decode=>:field_list,:fields=>[{:name=>:errno,:is_a=>:int32},{:name=>:errstr,:is_a=>:zstr}]},
70
- :mnt =>{:decode=>:field_list,:fields=>[{:name=>:fs,:is_a=>:zstr},{:name=>:dir,:is_a=>:zstr},{:name=>:is_a,:is_a=>:zstr},{:name=>:total,:is_a=>:int64},{:name=>:used,:is_a=>:int64},{:name=>:free,:is_a=>:int64},{:name=>:fcount,:is_a=>:int64},{:name=>:errno,:is_a=>:int32},{:name=>:errstr,:is_a=>:zstr}]},
71
- :md5sum =>{:decode=>:field_list,:fields=>[{:name=>:md5sum,:is_a=>:zstr}]},
72
- :int8 =>{:decode=>:base,:unpack=>'C',:size=>1},
73
- :int32 =>{:decode=>:base,:unpack=>'L>',:size=>4},
74
- :int64 =>{:decode=>:base,:unpack=>'Q>',:size=>8},
75
- :epoch =>{:decode=>:base,:unpack=>'Q>',:size=>8},
76
- :zstr =>{:decode=>:base,:unpack=>'Z*'},
77
- :blist =>{:decode=>:buffer_list}
78
- }
65
+ TYPES_DESCR = {
66
+ result: {decode: :field_list,
67
+ fields: [{name: :file,is_a: :stat},{name: :dir,is_a: :stat,special: :substruct},{name: :size,is_a: :size},{name: :error,is_a: :error},
68
+ {name: :info,is_a: :info},{name: :success,is_a: nil,special: :return_true},{name: :exit,is_a: nil},
69
+ {name: :df,is_a: :mnt,special: :restart_on_first},{name: :md5sum,is_a: :md5sum}]},
70
+ stat: {decode: :field_list,
71
+ fields: [{name: :name,is_a: :zstr},{name: :size,is_a: :int64},{name: :mode,is_a: :int32,check: nil},{name: :zmode,is_a: :zstr},
72
+ {name: :uid,is_a: :int32,check: nil},{name: :zuid,is_a: :zstr},{name: :gid,is_a: :int32,check: nil},{name: :zgid,is_a: :zstr},
73
+ {name: :ctime,is_a: :epoch},{name: :zctime,is_a: :zstr},{name: :mtime,is_a: :epoch},{name: :zmtime,is_a: :zstr},
74
+ {name: :atime,is_a: :epoch},{name: :zatime,is_a: :zstr},{name: :symlink,is_a: :zstr},{name: :errno,is_a: :int32},
75
+ {name: :errstr,is_a: :zstr}]},
76
+ info: {decode: :field_list,
77
+ fields: [{name: :platform,is_a: :zstr},{name: :version,is_a: :zstr},{name: :lang,is_a: :zstr},{name: :territory,is_a: :zstr},
78
+ {name: :codeset,is_a: :zstr},{name: :lc_ctype,is_a: :zstr},{name: :lc_numeric,is_a: :zstr},{name: :lc_time,is_a: :zstr},
79
+ {name: :lc_all,is_a: :zstr},{name: :dev,is_a: :zstr,special: :multiple},{name: :browse_caps,is_a: :zstr},
80
+ {name: :protocol,is_a: :zstr}]},
81
+ size: {decode: :field_list,
82
+ fields: [{name: :size,is_a: :int64},{name: :fcount,is_a: :int32},{name: :dcount,is_a: :int32},{name: :failed_fcount,is_a: :int32},
83
+ {name: :failed_dcount,is_a: :int32}]},
84
+ error: {decode: :field_list,
85
+ fields: [{name: :errno,is_a: :int32},{name: :errstr,is_a: :zstr}]},
86
+ mnt: {decode: :field_list,
87
+ fields: [{name: :fs,is_a: :zstr},{name: :dir,is_a: :zstr},{name: :is_a,is_a: :zstr},{name: :total,is_a: :int64},
88
+ {name: :used,is_a: :int64},{name: :free,is_a: :int64},{name: :fcount,is_a: :int64},{name: :errno,is_a: :int32},
89
+ {name: :errstr,is_a: :zstr}]},
90
+ md5sum: {decode: :field_list,fields: [{name: :md5sum,is_a: :zstr}]},
91
+ int8: {decode: :base,unpack: 'C',size: 1},
92
+ int32: {decode: :base,unpack: 'L>',size: 4},
93
+ int64: {decode: :base,unpack: 'Q>',size: 8},
94
+ epoch: {decode: :base,unpack: 'Q>',size: 8},
95
+ zstr: {decode: :base,unpack: 'Z*'},
96
+ blist: {decode: :buffer_list}
97
+ }.freeze
79
98
 
80
99
  # protocol enum start at one, but array index start at zero
81
- ENUM_START=1
100
+ ENUM_START = 1
82
101
 
83
102
  private_constant :TYPES_DESCR,:ENUM_START
84
103
 
85
- # get description of structure's field, @param struct_name, @param typed_buffer provides field name
86
- def self.field_description(struct_name,typed_buffer)
87
- result=TYPES_DESCR[struct_name][:fields][typed_buffer[:btype]-ENUM_START]
88
- raise "Unrecognized field for #{struct_name}: #{typed_buffer[:btype]}\n#{typed_buffer[:buffer]}" if result.nil?
89
- return result
90
- end
104
+ class << self
105
+ # get description of structure's field, @param struct_name, @param typed_buffer provides field name
106
+ def field_description(struct_name,typed_buffer)
107
+ result = TYPES_DESCR[struct_name][:fields][typed_buffer[:btype] - ENUM_START]
108
+ raise "Unrecognized field for #{struct_name}: #{typed_buffer[:btype]}\n#{typed_buffer[:buffer]}" if result.nil?
109
+ return result
110
+ end
91
111
 
92
- # decodes the provided buffer as provided type name
93
- # @return a decoded type.
94
- # :base : value, :buffer_list : an array of {btype,buffer}, :field_list : a hash, or array
95
- def self.parse(buffer,type_name,indent_level=nil)
96
- indent_level=(indent_level||-1)+1
97
- type_descr=TYPES_DESCR[type_name]
98
- raise "Unexpected type #{type_name}" if type_descr.nil?
99
- Log.log.debug("#{" ."*indent_level}parse:#{type_name}:#{type_descr[:decode]}:#{buffer[0,16]}...".red)
100
- result=nil
101
- case type_descr[:decode]
102
- when :base
103
- num_bytes=type_name.eql?(:zstr) ? buffer.length : type_descr[:size]
104
- raise "ERROR:not enough bytes" if buffer.length < num_bytes
105
- byte_array=buffer.shift(num_bytes);byte_array=[byte_array] unless byte_array.is_a?(Array)
106
- result=byte_array.pack('C*').unpack(type_descr[:unpack]).first
107
- Log.log.debug("#{" ."*indent_level}-> base:#{byte_array} -> #{result}")
108
- result=Time.at(result) if type_name.eql?(:epoch)
109
- when :buffer_list
110
- result = []
111
- while !buffer.empty?
112
- btype=parse(buffer,:int8,indent_level)
113
- length=parse(buffer,:int32,indent_level)
114
- raise "ERROR:not enough bytes" if buffer.length < length
115
- value=buffer.shift(length)
116
- result.push({:btype=>btype,:buffer=>value})
117
- Log.log.debug("#{" ."*indent_level}:buffer_list[#{result.length-1}] #{result.last}")
118
- end
119
- when :field_list
120
- # by default the result is one struct
121
- result = {}
122
- # get individual binary fields
123
- parse(buffer,:blist,indent_level).each do |typed_buffer|
124
- # what type of field is it ?
125
- field_info=field_description(type_name,typed_buffer)
126
- Log.log.debug("#{" ."*indent_level}+ field(special=#{field_info[:special]})=#{field_info[:name]}".green)
127
- case field_info[:special]
128
- when nil
129
- result[field_info[:name]]=parse(typed_buffer[:buffer],field_info[:is_a],indent_level)
130
- when :return_true
131
- result[field_info[:name]]=true
132
- when :substruct
133
- result[field_info[:name]]=parse(typed_buffer[:buffer],:blist,indent_level).map{|r|parse(r[:buffer],field_info[:is_a],indent_level)}
134
- when :multiple
135
- result[field_info[:name]]||=[]
136
- result[field_info[:name]].push(parse(typed_buffer[:buffer],field_info[:is_a],indent_level))
137
- when :restart_on_first
138
- fl=result[field_info[:name]]=[]
139
- parse(typed_buffer[:buffer],:blist,indent_level).map do |tb|
140
- fl.push({}) if tb[:btype].eql?(ENUM_START)
141
- fi=field_description(field_info[:is_a],tb)
142
- fl.last[fi[:name]]=parse(tb[:buffer],fi[:is_a],indent_level)
112
+ # decodes the provided buffer as provided type name
113
+ # @return a decoded type.
114
+ # :base : value, :buffer_list : an array of {btype,buffer}, :field_list : a hash, or array
115
+ def parse(buffer,type_name,indent_level=nil)
116
+ indent_level = (indent_level || -1) + 1
117
+ type_descr = TYPES_DESCR[type_name]
118
+ raise "Unexpected type #{type_name}" if type_descr.nil?
119
+ Log.log.debug("#{' .' * indent_level}parse:#{type_name}:#{type_descr[:decode]}:#{buffer[0,16]}...".red)
120
+ result = nil
121
+ case type_descr[:decode]
122
+ when :base
123
+ num_bytes = type_name.eql?(:zstr) ? buffer.length : type_descr[:size]
124
+ raise 'ERROR:not enough bytes' if buffer.length < num_bytes
125
+ byte_array = buffer.shift(num_bytes);byte_array = [byte_array] unless byte_array.is_a?(Array)
126
+ result = byte_array.pack('C*').unpack1(type_descr[:unpack])
127
+ Log.log.debug("#{' .' * indent_level}-> base:#{byte_array} -> #{result}")
128
+ result = Time.at(result) if type_name.eql?(:epoch)
129
+ when :buffer_list
130
+ result = []
131
+ while !buffer.empty?
132
+ btype = parse(buffer,:int8,indent_level)
133
+ length = parse(buffer,:int32,indent_level)
134
+ raise 'ERROR:not enough bytes' if buffer.length < length
135
+ value = buffer.shift(length)
136
+ result.push({btype: btype,buffer: value})
137
+ Log.log.debug("#{' .' * indent_level}:buffer_list[#{result.length - 1}] #{result.last}")
138
+ end
139
+ when :field_list
140
+ # by default the result is one struct
141
+ result = {}
142
+ # get individual binary fields
143
+ parse(buffer,:blist,indent_level).each do |typed_buffer|
144
+ # what type of field is it ?
145
+ field_info = field_description(type_name,typed_buffer)
146
+ Log.log.debug("#{' .' * indent_level}+ field(special=#{field_info[:special]})=#{field_info[:name]}".green)
147
+ case field_info[:special]
148
+ when nil
149
+ result[field_info[:name]] = parse(typed_buffer[:buffer],field_info[:is_a],indent_level)
150
+ when :return_true
151
+ result[field_info[:name]] = true
152
+ when :substruct
153
+ result[field_info[:name]] = parse(typed_buffer[:buffer],:blist,indent_level).map{|r|parse(r[:buffer],field_info[:is_a],indent_level)}
154
+ when :multiple
155
+ result[field_info[:name]] ||= []
156
+ result[field_info[:name]].push(parse(typed_buffer[:buffer],field_info[:is_a],indent_level))
157
+ when :restart_on_first
158
+ fl = result[field_info[:name]] = []
159
+ parse(typed_buffer[:buffer],:blist,indent_level).map do |tb|
160
+ fl.push({}) if tb[:btype].eql?(ENUM_START)
161
+ fi = field_description(field_info[:is_a],tb)
162
+ fl.last[fi[:name]] = parse(tb[:buffer],fi[:is_a],indent_level)
163
+ end
143
164
  end
144
165
  end
145
- end
146
- else raise "error: unknown decode:#{type_descr[:decode]}"
147
- end # is_a
148
- return result
166
+ else raise "error: unknown decode:#{type_descr[:decode]}"
167
+ end # is_a
168
+ return result
169
+ end
149
170
  end
150
171
  end
151
172
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'aspera/log'
2
4
  require 'aspera/rest'
3
5
 
@@ -5,32 +7,32 @@ module Aspera
5
7
  class AtsApi < Rest
6
8
  # currently supported clouds
7
9
  # Note to Aspera: shall be an API call
8
- CLOUD_NAME={
9
- :aws =>'Amazon Web Services',
10
- :azure =>'Microsoft Azure',
11
- :google =>'Google Cloud',
12
- :limelight =>'Limelight',
13
- :rackspace =>'Rackspace',
14
- :softlayer =>'IBM Cloud'
15
- }
16
-
10
+ CLOUD_NAME = {
11
+ aws: 'Amazon Web Services',
12
+ azure: 'Microsoft Azure',
13
+ google: 'Google Cloud',
14
+ limelight: 'Limelight',
15
+ rackspace: 'Rackspace',
16
+ softlayer: 'IBM Cloud'
17
+ }.freeze
18
+
17
19
  private_constant :CLOUD_NAME
18
-
20
+
19
21
  def self.base_url;'https://ats.aspera.io';end
20
22
 
21
23
  def initialize
22
- super({:base_url=>AtsApi.base_url+'/pub/v1'})
24
+ super({base_url: AtsApi.base_url + '/pub/v1'})
23
25
  # cache of server data
24
- @all_servers_cache=nil
26
+ @all_servers_cache = nil
25
27
  end
26
-
28
+
27
29
  def cloud_names;CLOUD_NAME;end
28
30
 
29
31
  # all available ATS servers
30
32
  # NOTE to Aspera: an API shall be created to retrieve all servers at once
31
33
  def all_servers
32
34
  if @all_servers_cache.nil?
33
- @all_servers_cache=[]
35
+ @all_servers_cache = []
34
36
  CLOUD_NAME.keys.each do |name|
35
37
  read("servers/#{name.to_s.upcase}")[:data].each do |i|
36
38
  @all_servers_cache.push(i)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'aspera/rest'
2
4
  require 'aspera/cli/plugin'
3
5
 
@@ -5,34 +7,33 @@ module Aspera
5
7
  module Cli
6
8
  # base class for applications supporting basic authentication
7
9
  class BasicAuthPlugin < Plugin
8
- def initialize(env)
9
- super(env)
10
- unless env[:skip_basic_auth_options]
11
- self.options.add_opt_simple(:url,"URL of application, e.g. https://org.asperafiles.com")
12
- self.options.add_opt_simple(:username,"username to log in")
13
- self.options.add_opt_simple(:password,"user's password")
14
- self.options.parse_options!
10
+ class << self
11
+ def register_options(env)
12
+ env[:options].add_opt_simple(:url,'URL of application, e.g. https://org.asperafiles.com')
13
+ env[:options].add_opt_simple(:username,'username to log in')
14
+ env[:options].add_opt_simple(:password,"user's password")
15
+ env[:options].parse_options!
15
16
  end
16
17
  end
17
- ACTIONS=[]
18
18
 
19
- def execute_action
20
- raise "do not execute action on this generic plugin"
19
+ def initialize(env)
20
+ super(env)
21
+ return if env[:skip_basic_auth_options]
22
+ self.class.register_options(env)
21
23
  end
22
24
 
23
25
  # returns a Rest object with basic auth
24
26
  def basic_auth_api(subpath=nil)
25
- api_url=self.options.get_option(:url,:mandatory)
26
- api_url=api_url+'/'+subpath unless subpath.nil?
27
+ api_url = options.get_option(:url,is_type: :mandatory)
28
+ api_url = api_url + '/' + subpath unless subpath.nil?
27
29
  return Rest.new({
28
- :base_url => api_url,
29
- :auth => {
30
- :type => :basic,
31
- :username => self.options.get_option(:username,:mandatory),
32
- :password => self.options.get_option(:password,:mandatory)
30
+ base_url: api_url,
31
+ auth: {
32
+ type: :basic,
33
+ username: options.get_option(:username,is_type: :mandatory),
34
+ password: options.get_option(:password,is_type: :mandatory)
33
35
  }})
34
36
  end
35
-
36
37
  end # BasicAuthPlugin
37
38
  end # Cli
38
39
  end # Aspera
@@ -1,4 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'aspera/cli/plugins/config'
4
+ require 'aspera/uri_reader'
5
+ require 'aspera/environment'
2
6
  require 'json'
3
7
  require 'base64'
4
8
  require 'zlib'
@@ -10,55 +14,62 @@ module Aspera
10
14
  # command line extended values
11
15
  class ExtendedValue
12
16
  include Singleton
13
- private
14
- # decode comma separated table text
15
- def self.decode_csvt(value)
16
- col_titles=nil
17
- hasharray=[]
18
- CSV.parse(value).each do |values|
19
- next if values.empty?
20
- if col_titles.nil?
21
- col_titles=values
22
- else
23
- entry={}
24
- col_titles.each{|title|entry[title]=values.shift}
25
- hasharray.push(entry)
17
+
18
+ class << self
19
+ # decode comma separated table text
20
+ def decode_csvt(value)
21
+ col_titles = nil
22
+ hasharray = []
23
+ CSV.parse(value).each do |values|
24
+ next if values.empty?
25
+ if col_titles.nil?
26
+ col_titles = values
27
+ else
28
+ entry = {}
29
+ col_titles.each{|title|entry[title] = values.shift}
30
+ hasharray.push(entry)
31
+ end
26
32
  end
33
+ return hasharray
27
34
  end
28
- value=hasharray
29
35
  end
30
36
 
37
+ private
38
+
31
39
  def initialize
32
- @handlers={
33
- :decoder=>{
34
- 'base64' =>lambda{|v|Base64.decode64(v)},
35
- 'json' =>lambda{|v|JSON.parse(v)},
36
- 'zlib' =>lambda{|v|Zlib::Inflate.inflate(v)},
37
- 'ruby' =>lambda{|v|eval(v)},
38
- 'csvt' =>lambda{|v|ExtendedValue.decode_csvt(v)},
39
- 'lines' =>lambda{|v|v.split("\n")},
40
- 'list' =>lambda{|v|v[1..-1].split(v[0])}
40
+ @handlers = {
41
+ decoder: {
42
+ base64: lambda{|v|Base64.decode64(v)},
43
+ json: lambda{|v|JSON.parse(v)},
44
+ zlib: lambda{|v|Zlib::Inflate.inflate(v)},
45
+ ruby: lambda{|v|Environment.secure_eval(v)},
46
+ csvt: lambda{|v|ExtendedValue.decode_csvt(v)},
47
+ lines: lambda{|v|v.split("\n")},
48
+ list: lambda{|v|v[1..-1].split(v[0])}
41
49
  },
42
- :reader=>{
43
- 'val' =>lambda{|v|v},
44
- 'file' =>lambda{|v|File.read(File.expand_path(v))},
45
- 'path' =>lambda{|v|File.expand_path(v)},
46
- 'env' =>lambda{|v|ENV[v]},
47
- 'stdin' =>lambda{|v|raise "no value allowed for stdin" unless v.empty?;STDIN.read}
50
+ reader: {
51
+ val: lambda{|v|v},
52
+ file: lambda{|v|File.read(File.expand_path(v))},
53
+ path: lambda{|v|File.expand_path(v)},
54
+ env: lambda{|v|ENV[v]},
55
+ uri: lambda{|v|UriReader.read(v)},
56
+ stdin: lambda{|v|raise 'no value allowed for stdin' unless v.empty?;$stdin.read}
48
57
  }
49
58
  # other handlers can be set using set_handler, e.g. preset is reader in config plugin
50
59
  }
51
60
  end
61
+
52
62
  public
53
63
 
54
- def modifiers;@handlers.keys.map{|i|@handlers[i].keys}.flatten;end
64
+ def modifiers;@handlers.keys.map{|i|@handlers[i].keys}.flatten.map(&:to_s);end
55
65
 
56
66
  # add a new :reader or :decoder
57
67
  # decoder can be chained, reader is last one on right
58
68
  def set_handler(name,type,method)
59
- raise "type must be one of #{@handlers.keys}" unless @handlers.keys.include?(type)
60
69
  Log.log.debug("setting #{type} handler for #{name}")
61
- @handlers[type][name]=method
70
+ raise 'name must be Symbol' unless name.is_a?(Symbol)
71
+ raise "type #{type} must be one of #{@handlers.keys}" unless @handlers.key?(type)
72
+ @handlers[type][name] = method
62
73
  end
63
74
 
64
75
  # parse an option value if it is a String using supported extended value modifiers
@@ -66,20 +77,20 @@ module Aspera
66
77
  def evaluate(value)
67
78
  return value if !value.is_a?(String)
68
79
  # first determine decoders, in reversed order
69
- decoders_reversed=[]
70
- while (m=value.match(/^@([^:]+):(.*)/)) and @handlers[:decoder].include?(m[1])
71
- decoders_reversed.unshift(m[1])
72
- value=m[2]
80
+ decoders_reversed = []
81
+ while (m = value.match(/^@([^:]+):(.*)/)) && @handlers[:decoder].include?(m[1].to_sym)
82
+ decoders_reversed.unshift(m[1].to_sym)
83
+ value = m[2]
73
84
  end
74
85
  # then read value
75
86
  @handlers[:reader].each do |reader,method|
76
- if m=value.match(/^@#{reader}:(.*)/) then
77
- value=method.call(m[1])
87
+ if (m = value.match(/^@#{reader}:(.*)/))
88
+ value = method.call(m[1])
78
89
  break
79
90
  end
80
91
  end
81
92
  decoders_reversed.each do |decoder|
82
- value=@handlers[:decoder][decoder].call(value)
93
+ value = @handlers[:decoder][decoder].call(value)
83
94
  end
84
95
  return value
85
96
  end # parse