aspera-cli 4.2.0 → 4.4.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +749 -353
  3. data/docs/Makefile +4 -4
  4. data/docs/README.erb.md +743 -283
  5. data/docs/doc_tools.rb +58 -0
  6. data/docs/test_env.conf +9 -1
  7. data/examples/aoc.rb +14 -3
  8. data/examples/faspex4.rb +89 -0
  9. data/lib/aspera/aoc.rb +24 -22
  10. data/lib/aspera/cli/main.rb +48 -20
  11. data/lib/aspera/cli/plugin.rb +13 -6
  12. data/lib/aspera/cli/plugins/aoc.rb +117 -78
  13. data/lib/aspera/cli/plugins/config.rb +127 -80
  14. data/lib/aspera/cli/plugins/faspex.rb +112 -63
  15. data/lib/aspera/cli/plugins/faspex5.rb +29 -25
  16. data/lib/aspera/cli/plugins/node.rb +54 -25
  17. data/lib/aspera/cli/plugins/preview.rb +94 -68
  18. data/lib/aspera/cli/plugins/server.rb +16 -5
  19. data/lib/aspera/cli/transfer_agent.rb +92 -72
  20. data/lib/aspera/cli/version.rb +1 -1
  21. data/lib/aspera/command_line_builder.rb +48 -31
  22. data/lib/aspera/cos_node.rb +4 -3
  23. data/lib/aspera/fasp/http_gw.rb +47 -26
  24. data/lib/aspera/fasp/local.rb +31 -24
  25. data/lib/aspera/fasp/manager.rb +3 -0
  26. data/lib/aspera/fasp/node.rb +23 -1
  27. data/lib/aspera/fasp/parameters.rb +72 -89
  28. data/lib/aspera/fasp/parameters.yaml +531 -0
  29. data/lib/aspera/fasp/uri.rb +1 -1
  30. data/lib/aspera/faspex_gw.rb +10 -9
  31. data/lib/aspera/id_generator.rb +22 -0
  32. data/lib/aspera/node.rb +11 -3
  33. data/lib/aspera/oauth.rb +131 -135
  34. data/lib/aspera/persistency_action_once.rb +11 -7
  35. data/lib/aspera/persistency_folder.rb +6 -26
  36. data/lib/aspera/rest.rb +1 -1
  37. data/lib/aspera/sync.rb +40 -35
  38. data/lib/aspera/timer_limiter.rb +22 -0
  39. data/lib/aspera/web_auth.rb +105 -0
  40. metadata +22 -4
  41. data/docs/transfer_spec.html +0 -99
  42. data/lib/aspera/fasp/aoc.rb +0 -24
@@ -4,6 +4,7 @@ require 'aspera/temp_file_manager'
4
4
  require 'securerandom'
5
5
  require 'base64'
6
6
  require 'json'
7
+ require 'yaml'
7
8
  require 'securerandom'
8
9
  require 'fileutils'
9
10
 
@@ -12,97 +13,72 @@ module Aspera
12
13
  # translate transfer specification to ascp parameter list
13
14
  class Parameters
14
15
  private
15
- # temp folder for file lists, must contain only file lists
16
+ # Temp folder for file lists, must contain only file lists
16
17
  # because of garbage collection takes any file there
17
18
  # this could be refined, as , for instance, on macos, temp folder is already user specific
18
19
  @@file_list_folder=TempFileManager.instance.new_file_path_global('asession_filelists')
19
- PARAM_DEFINITION={
20
- # parameters with env vars
21
- 'remote_password' => { :type => :envvar, :variable=>'ASPERA_SCP_PASS'},
22
- 'token' => { :type => :envvar, :variable=>'ASPERA_SCP_TOKEN'},
23
- 'cookie' => { :type => :envvar, :variable=>'ASPERA_SCP_COOKIE'},
24
- 'ssh_private_key' => { :type => :envvar, :variable=>'ASPERA_SCP_KEY'},
25
- 'EX_at_rest_password' => { :type => :envvar, :variable=>'ASPERA_SCP_FILEPASS'},
26
- 'EX_proxy_password' => { :type => :envvar, :variable=>'ASPERA_PROXY_PASS'},
27
- 'EX_license_text' => { :type => :envvar, :variable=>'ASPERA_SCP_LICENSE'},
28
- # bool params
29
- 'create_dir' => { :type => :opt_without_arg, :option_switch=>'-d'},
30
- 'precalculate_job_size' => { :type => :opt_without_arg},
31
- 'keepalive' => { :type => :opt_without_arg},
32
- 'delete_before_transfer' => { :type => :opt_without_arg}, #TODO: doc readme
33
- 'preserve_access_time' => { :type => :opt_without_arg}, #TODO: doc
34
- 'preserve_creation_time' => { :type => :opt_without_arg}, #TODO: doc
35
- 'preserve_times' => { :type => :opt_without_arg}, #TODO: doc
36
- 'preserve_modification_time'=> { :type => :opt_without_arg}, #TODO: doc
37
- 'remove_empty_directories'=> { :type => :opt_without_arg}, #TODO: doc
38
- 'remove_after_transfer' => { :type => :opt_without_arg}, #TODO: doc
39
- 'remove_empty_source_directory'=> { :type => :opt_without_arg}, #TODO: doc
40
- # value params
41
- 'cipher' => { :type => :opt_with_arg, :option_switch=>'-c',:accepted_types=>String,:encode=>lambda{|cipher|cipher.tr('-','')}},
42
- 'resume_policy' => { :type => :opt_with_arg, :option_switch=>'-k',:accepted_types=>String,:default=>'sparse_csum',:translate_values=>{'none'=>0,'attrs'=>1,'sparse_csum'=>2,'full_csum'=>3}},
43
- 'direction' => { :type => :opt_with_arg, :option_switch=>'--mode',:accepted_types=>String,:translate_values=>{'receive'=>'recv','send'=>'send'}},
44
- 'remote_user' => { :type => :opt_with_arg, :option_switch=>'--user',:accepted_types=>String},
45
- 'remote_host' => { :type => :opt_with_arg, :option_switch=>'--host',:accepted_types=>String},
46
- 'ssh_port' => { :type => :opt_with_arg, :option_switch=>'-P',:accepted_types=>Integer},
47
- 'fasp_port' => { :type => :opt_with_arg, :option_switch=>'-O',:accepted_types=>Integer},
48
- 'dgram_size' => { :type => :opt_with_arg, :option_switch=>'-Z',:accepted_types=>Integer},
49
- 'target_rate_kbps' => { :type => :opt_with_arg, :option_switch=>'-l',:accepted_types=>Integer},
50
- 'min_rate_kbps' => { :type => :opt_with_arg, :option_switch=>'-m',:accepted_types=>Integer},
51
- 'rate_policy' => { :type => :opt_with_arg, :option_switch=>'--policy',:accepted_types=>String},
52
- 'http_fallback' => { :type => :opt_with_arg, :option_switch=>'-y',:accepted_types=>[String,*Aspera::CommandLineBuilder::BOOLEAN_CLASSES],:translate_values=>{'force'=>'F',true=>1,false=>0}},
53
- 'http_fallback_port' => { :type => :opt_with_arg, :option_switch=>'-t',:accepted_types=>Integer},
54
- 'source_root' => { :type => :opt_with_arg, :option_switch=>'--source-prefix64',:accepted_types=>String,:encode=>lambda{|prefix|Base64.strict_encode64(prefix)}},
55
- 'sshfp' => { :type => :opt_with_arg, :option_switch=>'--check-sshfp',:accepted_types=>String},
56
- 'symlink_policy' => { :type => :opt_with_arg, :option_switch=>'--symbolic-links',:accepted_types=>String},
57
- 'overwrite' => { :type => :opt_with_arg, :accepted_types=>String},
58
- 'exclude_newer_than' => { :type => :opt_with_arg, :accepted_types=>Integer},
59
- 'exclude_older_than' => { :type => :opt_with_arg, :accepted_types=>Integer},
60
- 'preserve_acls' => { :type => :opt_with_arg, :accepted_types=>String},
61
- 'move_after_transfer' => { :type => :opt_with_arg, :accepted_types=>String},
62
- 'multi_session_threshold' => { :type => :opt_with_arg, :accepted_types=>Integer},
63
- # non standard parameters
64
- 'EX_fasp_proxy_url' => { :type => :opt_with_arg, :option_switch=>'--proxy',:accepted_types=>String},
65
- 'EX_http_proxy_url' => { :type => :opt_with_arg, :option_switch=>'-x',:accepted_types=>String},
66
- 'EX_ssh_key_paths' => { :type => :opt_with_arg, :option_switch=>'-i',:accepted_types=>Array},
67
- 'EX_http_transfer_jpeg' => { :type => :opt_with_arg, :option_switch=>'-j',:accepted_types=>Integer},
68
- 'EX_multi_session_part' => { :type => :opt_with_arg, :option_switch=>'-C',:accepted_types=>String},
69
- 'EX_no_read' => { :type => :opt_without_arg, :option_switch=>'--no-read'},
70
- 'EX_no_write' => { :type => :opt_without_arg, :option_switch=>'--no-write'},
71
- 'EX_apply_local_docroot' => { :type => :opt_without_arg, :option_switch=>'--apply-local-docroot'},
72
- # TODO: manage those parameters, some are for connect only ? node api ?
73
- 'target_rate_cap_kbps' => { :type => :ignore, :accepted_types=>Integer},
74
- 'target_rate_percentage' => { :type => :ignore, :accepted_types=>String}, # -wf -l<rate>p
75
- 'min_rate_cap_kbps' => { :type => :ignore, :accepted_types=>Integer},
76
- 'rate_policy_allowed' => { :type => :ignore, :accepted_types=>String},
77
- 'fasp_url' => { :type => :ignore, :accepted_types=>String},
78
- 'lock_rate_policy' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
79
- 'lock_min_rate' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
80
- 'lock_target_rate' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
81
- 'authentication' => { :type => :ignore, :accepted_types=>String}, # value = token
82
- 'https_fallback_port' => { :type => :ignore, :accepted_types=>Integer}, # same as http fallback, option -t ?
83
- 'content_protection' => { :type => :ignore, :accepted_types=>String},
84
- 'cipher_allowed' => { :type => :ignore, :accepted_types=>String},
85
- 'multi_session' => { :type => :ignore, :accepted_types=>Integer}, # managed
86
- 'obfuscate_file_names' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
87
- # optional tags ( additional option to generate: {:space=>' ',:object_nl=>' ',:space_before=>'+',:array_nl=>'1'} )
88
- 'tags' => { :type => :opt_with_arg, :option_switch=>'--tags64',:accepted_types=>Hash,:encode=>lambda{|tags|Base64.strict_encode64(JSON.generate(tags))}},
89
- # special processing @builder.process_param( called individually
90
- 'use_ascp4' => { :type => :defer, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
91
- 'paths' => { :type => :defer, :accepted_types=>Array},
92
- 'EX_file_list' => { :type => :defer, :option_switch=>'--file-list', :accepted_types=>String},
93
- 'EX_file_pair_list' => { :type => :defer, :option_switch=>'--file-pair-list', :accepted_types=>String},
94
- 'EX_ascp_args' => { :type => :defer, :accepted_types=>Array},
95
- 'destination_root' => { :type => :defer, :accepted_types=>String},
96
- 'wss_enabled' => { :type => :defer, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
97
- 'wss_port' => { :type => :defer, :accepted_types=>Integer},
98
- }
99
-
100
- private_constant :PARAM_DEFINITION
20
+ @@param_description_cache=nil
21
+ # @return normaiwed description of transfer spec parameters
22
+ def self.description
23
+ return @@param_description_cache unless @@param_description_cache.nil?
24
+ # config file in same folder with same name as this source
25
+ @@param_description_cache=YAML.load_file("#{__FILE__[0..-3]}yaml")
26
+ Aspera::CommandLineBuilder.normalize_description(@@param_description_cache)
27
+ end
28
+
29
+ # Agents shown in manual
30
+ SUPPORTED_AGENTS=[:direct,:node,:connect]
31
+ # Short names of columns in manual
32
+ SUPPORTED_AGENTS_SHORT=SUPPORTED_AGENTS.map{|a|a.to_s[0].to_sym}
33
+
34
+ # @return a table suitable to display a manual
35
+ def self.man_table
36
+ result=[]
37
+ description.keys.map do |k|
38
+ i=description[k]
39
+ param={name: k, type: [i[:accepted_types]].flatten.join(','),description: i[:desc]}
40
+ SUPPORTED_AGENTS.each do |a|
41
+ param[a.to_s[0].to_sym]=i[:context].nil? || i[:context].include?(a) ? 'Y' : ''
42
+ end
43
+ # only keep lines that are usable in supported agents
44
+ next if SUPPORTED_AGENTS_SHORT.inject(true){|m,i|m and param[i].empty?}
45
+ param[:cli]=case i[:cltype]
46
+ when :envvar; 'env:'+i[:clvarname]
47
+ when :opt_without_arg,:opt_with_arg; i[:option_switch]
48
+ else ''
49
+ end
50
+ if i.has_key?(:enum)
51
+ param[:description] << "\nAllowed values: #{i[:enum].join(', ')}"
52
+ end
53
+ result.push(param)
54
+ end
55
+ return result
56
+ end
57
+
58
+ # special encoding methods used in YAML (key: :encode)
59
+ def self.encode_cipher(v)
60
+ v.tr('-','')
61
+ end
62
+
63
+ # special encoding methods used in YAML (key: :encode)
64
+ def self.encode_source_root(v)
65
+ Base64.strict_encode64(v)
66
+ end
67
+
68
+ # special encoding methods used in YAML (key: :encode)
69
+ def self.encode_tags(v)
70
+ Base64.strict_encode64(JSON.generate(v))
71
+ end
72
+
73
+ def self.ts_has_file_list(ts)
74
+ ts.has_key?('EX_ascp_args') and ts['EX_ascp_args'].is_a?(Array) and ['--file-list','--file-pair-list'].any?{|i|ts['EX_ascp_args'].include?(i)}
75
+ end
101
76
 
102
77
  def initialize(job_spec,options)
103
78
  @job_spec=job_spec
104
- @builder=Aspera::CommandLineBuilder.new(@job_spec,PARAM_DEFINITION)
105
79
  @options=options
80
+ @builder=Aspera::CommandLineBuilder.new(@job_spec,self.class.description)
81
+ Log.log.debug("agent options: #{@options}")
106
82
  end
107
83
 
108
84
  public
@@ -125,8 +101,8 @@ module Aspera
125
101
  # special cases
126
102
  @job_spec.delete('source_root') if @job_spec.has_key?('source_root') and @job_spec['source_root'].empty?
127
103
 
128
- # use web socket initiation ?
129
- if @builder.process_param('wss_enabled',:get_value) and @options[:wss]
104
+ # use web socket session initiation ?
105
+ if @builder.process_param('wss_enabled',:get_value) and ( @options[:wss] or !@job_spec.has_key?('fasp_port') )
130
106
  # by default use web socket session if available, unless removed by user
131
107
  @builder.add_command_line_options(['--ws-connect'])
132
108
  # TODO: option to give order ssh,ws (legacy http is implied bu ssh)
@@ -151,10 +127,17 @@ module Aspera
151
127
  # destination will be base64 encoded, put before path arguments
152
128
  @builder.add_command_line_options(['--dest64'])
153
129
  end
154
-
155
- PARAM_DEFINITION['paths'][:mandatory]=!@job_spec.has_key?('keepalive')
130
+ # paths is mandatory, unless ...
131
+ file_list_provided=self.class.ts_has_file_list(@job_spec)
132
+ @builder.params_definition['paths'][:mandatory]=!@job_spec.has_key?('keepalive') and !file_list_provided
156
133
  paths_array=@builder.process_param('paths',:get_value)
157
- unless paths_array.nil?
134
+ if file_list_provided and ! paths_array.nil?
135
+ Log.log.warn("file list provided both in transfer spec and ascp file list. Keeping file list only.")
136
+ paths_array=nil
137
+ end
138
+ if ! paths_array.nil?
139
+ # it's an array
140
+ raise "paths is empty in transfer spec" if paths_array.empty?
158
141
  # use file list if there is storage defined for it.
159
142
  if @@file_list_folder.nil?
160
143
  # not safe for special characters ? (maybe not, depends on OS)