aspera-cli 4.3.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.
@@ -45,6 +45,7 @@ module Aspera
45
45
  AOC_COMMAND_V2='aspera'
46
46
  AOC_COMMAND_V3='aoc'
47
47
  AOC_COMMAND_CURRENT=AOC_COMMAND_V3
48
+ SERVER_COMMAND='server'
48
49
  CONNECT_WEB_URL = 'https://d3gcli72yxqn2z.cloudfront.net/connect'
49
50
  CONNECT_VERSIONS = 'connectversions.js'
50
51
  TRANSFER_SDK_ARCHIVE_URL = 'https://ibm.biz/aspera_sdk'
@@ -58,14 +59,31 @@ Subject: Amelia email test
58
59
 
59
60
  It worked !
60
61
  END_OF_TEMPLATE
62
+ # special extended values
63
+ EXTV_INCLUDE_PRESETS='incps'
64
+ EXTV_PRESET='preset'
65
+ DEFAULT_CHECK_NEW_VERSION_DAYS=7
66
+ DEFAULT_PRIV_KEY_FILENAME='aspera_aoc_key'
67
+ DEFAULT_PRIVKEY_LENGTH=4096
68
+ private_constant :DEFAULT_CONFIG_FILENAME,:CONF_PRESET_CONFIG,:CONF_PRESET_VERSION,:CONF_PRESET_DEFAULT,
69
+ :CONF_PRESET_GLOBAL,:PROGRAM_NAME_V1,:PROGRAM_NAME_V2,:DEFAULT_REDIRECT,:ASPERA_PLUGINS_FOLDERNAME,
70
+ :RUBY_FILE_EXT,:AOC_COMMAND_V1,:AOC_COMMAND_V2,:AOC_COMMAND_V3,:AOC_COMMAND_CURRENT,:DEMO,
71
+ :TRANSFER_SDK_ARCHIVE_URL,:AOC_PATH_API_CLIENTS,:DEMO_SERVER_PRESET,:EMAIL_TEST_TEMPLATE,:EXTV_INCLUDE_PRESETS,
72
+ :EXTV_PRESET,:DEFAULT_CHECK_NEW_VERSION_DAYS,:DEFAULT_PRIV_KEY_FILENAME,:SERVER_COMMAND
61
73
  def option_preset; nil; end
62
74
 
63
75
  def option_preset=(value)
64
- self.options.add_option_preset(preset_by_name(value))
76
+ case value
77
+ when String
78
+ self.options.add_option_preset(preset_by_name(value))
79
+ when Hash
80
+ self.options.add_option_preset(value)
81
+ else
82
+ raise "Preset definition must be a String for name, or Hash for value"
83
+ end
84
+ nil
65
85
  end
66
86
 
67
- private_constant :DEFAULT_CONFIG_FILENAME,:CONF_PRESET_CONFIG,:CONF_PRESET_VERSION,:CONF_PRESET_DEFAULT,:CONF_PRESET_GLOBAL,:PROGRAM_NAME_V1,:PROGRAM_NAME_V2,:DEFAULT_REDIRECT,:ASPERA_PLUGINS_FOLDERNAME,:RUBY_FILE_EXT,:AOC_COMMAND_V1,:AOC_COMMAND_V2,:AOC_COMMAND_V3,:AOC_COMMAND_CURRENT,:DEMO,:TRANSFER_SDK_ARCHIVE_URL,:AOC_PATH_API_CLIENTS,:DEMO_SERVER_PRESET,:EMAIL_TEST_TEMPLATE
68
-
69
87
  def initialize(env,tool_name,help_url,version,main_folder)
70
88
  super(env)
71
89
  raise 'missing secret manager' if @agents[:secret].nil?
@@ -93,35 +111,36 @@ END_OF_TEMPLATE
93
111
  # add preset handler (needed for smtp)
94
112
  ExtendedValue.instance.set_handler(EXTV_PRESET,:reader,lambda{|v|preset_by_name(v)})
95
113
  ExtendedValue.instance.set_handler(EXTV_INCLUDE_PRESETS,:decoder,lambda{|v|expanded_with_preset_includes(v)})
96
- self.options.set_obj_attr(:override,self,:option_override,:no)
97
114
  self.options.set_obj_attr(:ascp_path,self,:option_ascp_path)
98
115
  self.options.set_obj_attr(:use_product,self,:option_use_product)
99
116
  self.options.set_obj_attr(:preset,self,:option_preset)
100
117
  self.options.set_obj_attr(:secret,@agents[:secret],:default_secret)
101
118
  self.options.set_obj_attr(:secrets,@agents[:secret],:all_secrets)
102
- self.options.add_opt_boolean(:override,'override existing value')
103
119
  self.options.add_opt_switch(:no_default,'-N','do not load default configuration for plugin') { @use_plugin_defaults=false }
104
- self.options.add_opt_boolean(:use_generic_client,'wizard: AoC: use global or org specific jwt client id')
105
- self.options.add_opt_simple(:pkeypath,'path to private key for JWT (wizard)')
120
+ self.options.add_opt_boolean(:override,'Wizard: override existing value')
121
+ self.options.add_opt_boolean(:use_generic_client,'Wizard: AoC: use global or org specific jwt client id')
122
+ self.options.add_opt_boolean(:default,'Wizard: set as default configuration for specified plugin (also: update)')
123
+ self.options.add_opt_boolean(:test_mode,'Wizard: skip private key check step')
124
+ self.options.add_opt_simple(:pkeypath,'Wizard: path to private key for JWT')
106
125
  self.options.add_opt_simple(:ascp_path,'path to ascp')
107
126
  self.options.add_opt_simple(:use_product,'use ascp from specified product')
108
127
  self.options.add_opt_simple(:smtp,'smtp configuration (extended value: hash)')
109
128
  self.options.add_opt_simple(:fpac,'proxy auto configuration URL')
110
129
  self.options.add_opt_simple(:preset,'-PVALUE','load the named option preset from current config file')
111
- self.options.add_opt_simple(:default,'set as default configuration for specified plugin')
112
130
  self.options.add_opt_simple(:secret,'default secret')
113
131
  self.options.add_opt_simple(:secrets,'secret repository (Hash)')
114
132
  self.options.add_opt_simple(:sdk_url,'URL to get SDK')
115
- self.options.add_opt_simple(:sdk_folder,'SDK folder location')
133
+ self.options.add_opt_simple(:sdk_folder,'SDK folder path')
116
134
  self.options.add_opt_simple(:notif_to,'email recipient for notification of transfers')
117
135
  self.options.add_opt_simple(:notif_template,'email ERB template for notification of transfers')
118
- self.options.add_opt_boolean(:test_mode,'skip user validation in wizard mode')
119
- self.options.add_opt_simple(:version_check_days,Integer,'period to check neew version in days (zero to disable)')
136
+ self.options.add_opt_simple(:version_check_days,Integer,'period in days to check new version (zero to disable)')
120
137
  self.options.set_option(:use_generic_client,true)
121
138
  self.options.set_option(:test_mode,false)
122
- self.options.set_option(:version_check_days,7)
139
+ self.options.set_option(:default,true)
140
+ self.options.set_option(:version_check_days,DEFAULT_CHECK_NEW_VERSION_DAYS)
123
141
  self.options.set_option(:sdk_url,TRANSFER_SDK_ARCHIVE_URL)
124
142
  self.options.set_option(:sdk_folder,File.join(@main_folder,'sdk'))
143
+ self.options.set_option(:override,:no)
125
144
  self.options.parse_options!
126
145
  raise CliBadArgument,'secrets shall be Hash' unless @agents[:secret].all_secrets.is_a?(Hash)
127
146
  Fasp::Installation.instance.folder=self.options.get_option(:sdk_folder,:mandatory)
@@ -198,9 +217,9 @@ END_OF_TEMPLATE
198
217
  end
199
218
  private
200
219
 
201
- def generate_new_key(private_key_path)
220
+ def generate_rsa_private_key(private_key_path,length)
202
221
  require 'openssl'
203
- priv_key = OpenSSL::PKey::RSA.new(4096)
222
+ priv_key = OpenSSL::PKey::RSA.new(length)
204
223
  File.write(private_key_path,priv_key.to_s)
205
224
  File.write(private_key_path+'.pub',priv_key.public_key.to_s)
206
225
  nil
@@ -253,12 +272,8 @@ END_OF_TEMPLATE
253
272
  attr_reader :main_folder
254
273
  attr_reader :gem_url
255
274
  attr_reader :plugins
256
- attr_accessor :option_override
257
275
  attr_accessor :option_config_file
258
276
 
259
- EXTV_INCLUDE_PRESETS='incps'
260
- EXTV_PRESET='preset'
261
-
262
277
  # @return the hash from name (also expands possible includes)
263
278
  def preset_by_name(config_name, include_path=[])
264
279
  raise CliError,"no such config preset: #{config_name}" unless @config_presets.has_key?(config_name)
@@ -343,11 +358,11 @@ END_OF_TEMPLATE
343
358
  Log.log.warn("No config file found. Creating empty configuration file: #{@option_config_file}")
344
359
  @config_presets={CONF_PRESET_CONFIG=>{CONF_PRESET_VERSION=>@program_version}}
345
360
  else
346
- Log.log.debug "loading #{@option_config_file}"
361
+ Log.log.debug("loading #{@option_config_file}")
347
362
  @config_presets=YAML.load_file(conf_file_to_load)
348
363
  end
349
364
  files_to_copy=[]
350
- Log.log.debug "Available_presets: #{@config_presets}"
365
+ Log.log.debug("Available_presets: #{@config_presets}")
351
366
  raise 'Expecting YAML Hash' unless @config_presets.is_a?(Hash)
352
367
  # check there is at least the config section
353
368
  if !@config_presets.has_key?(CONF_PRESET_CONFIG)
@@ -589,7 +604,7 @@ END_OF_TEMPLATE
589
604
  save_presets_to_config_file
590
605
  return Main.result_status("Modified: #{@option_config_file}")
591
606
  when :update
592
- default_for_plugin=self.options.get_option(:default,:optional)
607
+ default_for_plugin=self.options.get_option(:default,:mandatory)
593
608
  # get unprocessed options
594
609
  theopts=self.options.get_options_table
595
610
  Log.log.debug("opts=#{theopts}")
@@ -621,7 +636,7 @@ END_OF_TEMPLATE
621
636
  return Main.result_nothing
622
637
  when :genkey # generate new rsa key
623
638
  private_key_path=self.options.get_next_argument('private key file path')
624
- generate_new_key(private_key_path)
639
+ generate_rsa_private_key(private_key_path,DEFAULT_PRIVKEY_LENGTH)
625
640
  return Main.result_status('Generated key: '+private_key_path)
626
641
  when :echo # display the content of a value given on command line
627
642
  result={:type=>:other_struct, :data=>self.options.get_next_argument('value')}
@@ -638,23 +653,32 @@ END_OF_TEMPLATE
638
653
  when :overview
639
654
  return {:type=>:object_list,:data=>self.class.flatten_all_config(@config_presets)}
640
655
  when :wizard
656
+ # interactive mode
641
657
  self.options.ask_missing_mandatory=true
642
658
  # register url option
643
659
  BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
660
+ # get from option, or ask
644
661
  instance_url=self.options.get_option(:url,:mandatory)
662
+ # allow user to tell the preset name
663
+ preset_name=self.options.get_option(:id,:optional)
645
664
  appli=ApiDetector.discover_product(instance_url)
665
+ plugin_name="<replace per app>"
666
+ test_args="<replace per app>"
646
667
  case appli[:product]
647
668
  when :aoc
648
669
  self.format.display_status('Detected: Aspera on Cloud'.bold)
670
+ plugin_name=AOC_COMMAND_CURRENT
649
671
  organization,instance_domain=AoC.parse_url(instance_url)
650
- aspera_preset_name='aoc_'+organization
651
- self.format.display_status("Preparing preset: #{aspera_preset_name}")
672
+ # if not defined by user, generate name
673
+ preset_name=[appli[:product],organization].join('_') if preset_name.nil?
674
+ self.format.display_status("Preparing preset: #{preset_name}")
652
675
  # init defaults if necessary
653
- @config_presets[CONF_PRESET_DEFAULT]||=Hash.new
654
- if !option_override
655
- raise CliError,"a default configuration already exists for plugin '#{AOC_COMMAND_CURRENT}' (use --override=yes)" if @config_presets[CONF_PRESET_DEFAULT].has_key?(AOC_COMMAND_CURRENT)
656
- raise CliError,"preset already exists: #{aspera_preset_name} (use --override=yes)" if @config_presets.has_key?(aspera_preset_name)
657
- end
676
+ @config_presets[CONF_PRESET_DEFAULT]||={}
677
+ option_override=self.options.get_option(:override,:mandatory)
678
+ option_default=self.options.get_option(:default,:mandatory)
679
+ Log.log.error("override=#{option_override} -> #{option_override.class}")
680
+ raise CliError,"A default configuration already exists for plugin '#{plugin_name}' (use --override=yes or --default=no)" if !option_override and option_default and @config_presets[CONF_PRESET_DEFAULT].has_key?(plugin_name)
681
+ raise CliError,"Preset already exists: #{preset_name} (use --override=yes or --id=<name>)" if !option_override and @config_presets.has_key?(preset_name)
658
682
  # lets see if path to priv key is provided
659
683
  private_key_path=self.options.get_option(:pkeypath,:optional)
660
684
  # give a chance to provide
@@ -664,23 +688,23 @@ END_OF_TEMPLATE
664
688
  end
665
689
  # else generate path
666
690
  if private_key_path.empty?
667
- private_key_path=File.join(@main_folder,'aspera_aoc_key')
691
+ private_key_path=File.join(@main_folder,DEFAULT_PRIV_KEY_FILENAME)
668
692
  end
669
693
  if File.exist?(private_key_path)
670
694
  self.format.display_status('Using existing key:')
671
695
  else
672
- self.format.display_status('Generating key...')
673
- generate_new_key(private_key_path)
696
+ self.format.display_status("Generating #{DEFAULT_PRIVKEY_LENGTH} bit RSA key...")
697
+ generate_rsa_private_key(private_key_path,DEFAULT_PRIVKEY_LENGTH)
674
698
  self.format.display_status('Created:')
675
699
  end
676
- self.format.display_status("#{private_key_path}")
700
+ self.format.display_status(private_key_path)
677
701
  pub_key_pem=OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
678
702
  # declare command line options for AoC
679
703
  require 'aspera/cli/plugins/aoc'
680
704
  # make username mandatory for jwt, this triggers interactive input
681
705
  self.options.get_option(:username,:mandatory)
682
706
  # instanciate AoC plugin, so that command line options are known
683
- files_plugin=self.class.plugin_new(AOC_COMMAND_CURRENT,@agents.merge({skip_basic_auth_options: true, private_key_path: private_key_path}))
707
+ files_plugin=self.class.plugin_new(plugin_name,@agents.merge({skip_basic_auth_options: true, private_key_path: private_key_path}))
684
708
  aoc_api=files_plugin.get_api
685
709
  auto_set_pub_key=false
686
710
  auto_set_jwt=false
@@ -723,7 +747,7 @@ END_OF_TEMPLATE
723
747
  end
724
748
  myself=aoc_api.read('self')[:data]
725
749
  if auto_set_pub_key
726
- raise CliError,'public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? or option_override
750
+ raise CliError,'Public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? or option_override
727
751
  self.format.display_status('Updating profile with new key')
728
752
  aoc_api.update("users/#{myself['id']}",{'public_key'=>pub_key_pem})
729
753
  end
@@ -731,8 +755,8 @@ END_OF_TEMPLATE
731
755
  self.format.display_status('Enabling JWT for client')
732
756
  aoc_api.update("clients/#{self.options.get_option(:client_id)}",{'jwt_grant_enabled'=>true,'explicit_authorization_required'=>false})
733
757
  end
734
- self.format.display_status("creating new config preset: #{aspera_preset_name}")
735
- @config_presets[aspera_preset_name]={
758
+ self.format.display_status("Creating new config preset: #{preset_name}")
759
+ @config_presets[preset_name]={
736
760
  :url.to_s =>self.options.get_option(:url),
737
761
  :username.to_s =>myself['email'],
738
762
  :auth.to_s =>:jwt.to_s,
@@ -741,16 +765,21 @@ END_OF_TEMPLATE
741
765
  # set only if non nil
742
766
  [:client_id,:client_secret].each do |s|
743
767
  o=self.options.get_option(s)
744
- @config_presets[s.to_s] = o unless o.nil?
768
+ @config_presets[preset_name][s.to_s] = o unless o.nil?
745
769
  end
746
- self.format.display_status("Setting config preset as default for #{AOC_COMMAND_CURRENT}")
747
- @config_presets[CONF_PRESET_DEFAULT][AOC_COMMAND_CURRENT]=aspera_preset_name
748
- self.format.display_status('saving config file')
749
- save_presets_to_config_file
750
- return Main.result_status("Done.\nYou can test with:\n#{@tool_name} #{AOC_COMMAND_CURRENT} user info show")
770
+ test_args="#{plugin_name} user info show"
751
771
  else
752
772
  raise CliBadArgument,"Supports only: aoc. Detected: #{appli}"
773
+ end # product
774
+ if option_default
775
+ self.format.display_status("Setting config preset as default for #{plugin_name}")
776
+ @config_presets[CONF_PRESET_DEFAULT][plugin_name]=preset_name
777
+ else
778
+ test_args="-P#{preset_name} #{test_args}"
753
779
  end
780
+ self.format.display_status('Saving config file.')
781
+ save_presets_to_config_file
782
+ return Main.result_status("Done.\nYou can test with:\n#{@tool_name} #{test_args}")
754
783
  when :export_to_cli
755
784
  self.format.display_status('Exporting: Aspera on Cloud')
756
785
  require 'aspera/cli/plugins/aoc'
@@ -820,16 +849,16 @@ END_OF_TEMPLATE
820
849
  @config_presets[DEMO_SERVER_PRESET]={'url'=>'ssh://'+DEMO+'.asperasoft.com:33001','username'=>AOC_COMMAND_V2,'ssAP'.downcase.reverse+'drow'.reverse=>DEMO+AOC_COMMAND_V2}
821
850
  end
822
851
  @config_presets[CONF_PRESET_DEFAULT]||={}
823
- if @config_presets[CONF_PRESET_DEFAULT].has_key?('server')
824
- Log.log.warn("server default preset already set to: #{@config_presets[CONF_PRESET_DEFAULT]['server']}")
825
- Log.log.warn("use #{DEMO_SERVER_PRESET} for demo: -P#{DEMO_SERVER_PRESET}") unless DEMO_SERVER_PRESET.eql?(@config_presets[CONF_PRESET_DEFAULT]['server'])
852
+ if @config_presets[CONF_PRESET_DEFAULT].has_key?(SERVER_COMMAND)
853
+ Log.log.warn("Server default preset already set to: #{@config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND]}")
854
+ Log.log.warn("Use #{DEMO_SERVER_PRESET} for demo: -P#{DEMO_SERVER_PRESET}") unless DEMO_SERVER_PRESET.eql?(@config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND])
826
855
  else
827
- @config_presets[CONF_PRESET_DEFAULT]['server']=DEMO_SERVER_PRESET
828
- Log.log.info("setting server default preset to : #{DEMO_SERVER_PRESET}")
856
+ @config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND]=DEMO_SERVER_PRESET
857
+ Log.log.info("Setting server default preset to : #{DEMO_SERVER_PRESET}")
829
858
  end
830
859
  save_presets_to_config_file
831
860
  return Main.result_status("Done")
832
- else raise 'error'
861
+ else raise 'INTERNAL ERROR: wrong case'
833
862
  end
834
863
  end
835
864
 
@@ -888,7 +917,7 @@ END_OF_TEMPLATE
888
917
  def save_presets_to_config_file
889
918
  raise 'no configuration loaded' if @config_presets.nil?
890
919
  FileUtils.mkdir_p(@main_folder) unless Dir.exist?(@main_folder)
891
- Log.log.debug "writing #{@option_config_file}"
920
+ Log.log.debug("Writing #{@option_config_file}")
892
921
  File.write(@option_config_file,@config_presets.to_yaml)
893
922
  end
894
923
 
@@ -23,12 +23,14 @@ module Aspera
23
23
  PACKAGE_MATCH_FIELD='package_id'
24
24
  # list of supported atoms
25
25
  ATOM_MAILBOXES=[:inbox, :archive, :sent]
26
- # number is added by CLI
27
- MAX_ITEMS='max'
28
- MAX_PAGES='pmax'
29
- ATOM_PARAMS=['page', 'count', 'startIndex', MAX_ITEMS, MAX_PAGES]
26
+ # allowed parameters for inbox.atom
27
+ ATOM_PARAMS=['page', 'count', 'startIndex']
28
+ # with special parameters (from Plugin class)
29
+ ATOM_EXT_PARAMS=ATOM_PARAMS+[MAX_ITEMS, MAX_PAGES]
30
+ # sub path in url for public link delivery
30
31
  PUB_LINK_EXTERNAL_MATCH='external_deliveries/'
31
- private_constant :KEY_NODE,:KEY_PATH,:VAL_ALL,:PACKAGE_MATCH_FIELD,:ATOM_MAILBOXES,:PUB_LINK_EXTERNAL_MATCH
32
+ private_constant :KEY_NODE,:KEY_PATH,:VAL_ALL,:PACKAGE_MATCH_FIELD,:ATOM_MAILBOXES,
33
+ :ATOM_PARAMS,:ATOM_EXT_PARAMS,:PUB_LINK_EXTERNAL_MATCH
32
34
 
33
35
  def initialize(env)
34
36
  @api_v3=nil
@@ -126,7 +128,7 @@ module Aspera
126
128
  result=[]
127
129
  if !mailbox_query.nil?
128
130
  raise "query: must be Hash or nil" unless mailbox_query.is_a?(Hash)
129
- raise "query: supported params: #{ATOM_PARAMS}" unless (mailbox_query.keys-ATOM_PARAMS).empty?
131
+ raise "query: supported params: #{ATOM_EXT_PARAMS}" unless (mailbox_query.keys-ATOM_EXT_PARAMS).empty?
130
132
  raise "query: startIndex and page are exclusive" if mailbox_query.has_key?('startIndex') and mailbox_query.has_key?('page')
131
133
  max_items=mailbox_query[MAX_ITEMS]
132
134
  mailbox_query.delete(MAX_ITEMS)
@@ -13,22 +13,34 @@ module Aspera
13
13
  private_constant :SAMPLE_SOAP_CALL
14
14
  def initialize(env)
15
15
  super(env)
16
- # this is added to some requests , for instance to add tags
16
+ # this is added to some requests , for instance to add tags (COS)
17
17
  @add_request_param = env[:add_request_param] || {}
18
18
  unless env[:skip_basic_auth_options]
19
19
  self.options.add_opt_simple(:validator,"identifier of validator (optional for central)")
20
20
  self.options.add_opt_simple(:asperabrowserurl,"URL for simple aspera web ui")
21
21
  self.options.add_opt_simple(:name,"sync name")
22
- self.options.add_opt_list(:token,[:aspera,:basic,:auto],'todo: type of token used for transfers')
22
+ self.options.add_opt_list(:token_type,[:aspera,:basic,:hybrid],'Type of token used for transfers')
23
23
  self.options.set_option(:asperabrowserurl,'https://asperabrowser.mybluemix.net')
24
- self.options.set_option(:token,:aspera)
24
+ self.options.set_option(:token_type,:aspera)
25
25
  self.options.parse_options!
26
26
  end
27
27
  return if env[:man_only]
28
28
  if env.has_key?(:node_api)
29
29
  @api_node=env[:node_api]
30
30
  else
31
- @api_node=basic_auth_api unless env[:man_only]
31
+ if self.options.get_option(:password,:mandatory).start_with?('Bearer ')
32
+ # info is provided like node_info of aoc
33
+ @api_node=Rest.new({
34
+ base_url: self.options.get_option(:url,:mandatory),
35
+ headers: {
36
+ 'Authorization' => self.options.get_option(:password,:mandatory),
37
+ 'X-Aspera-AccessKey' => self.options.get_option(:username,:mandatory),
38
+ }
39
+ })
40
+ else
41
+ # this is normal case
42
+ @api_node=basic_auth_api
43
+ end
32
44
  end
33
45
  end
34
46
 
@@ -191,22 +203,36 @@ module Aspera
191
203
  #raise "unknown type: #{send_result['self']['type']}"
192
204
  end
193
205
  return c_result_remove_prefix_path(result,'path',prefix_path)
194
- when :upload
195
- # we send only a list of one transfer request
196
- transfer_request = { :paths => [ { :destination => self.transfer.destination_folder('send') } ] }
197
- transfer_request.deep_merge!(@add_request_param)
198
- send_result=@api_node.create('files/upload_setup',{:transfer_requests => [ { :transfer_request => transfer_request } ] } )[:data]
199
- # only one request, so only one answer
200
- transfer_spec=send_result['transfer_specs'].first['transfer_spec']
201
- # delete this part, as the returned value contains only destination, and not sources
202
- transfer_spec.delete('paths')
203
- return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
204
- when :download
205
- transfer_request = {:paths => self.transfer.ts_source_paths }
206
- transfer_request.deep_merge!(@add_request_param)
207
- send_result=@api_node.create('files/download_setup',{:transfer_requests => [ { :transfer_request => transfer_request } ] } )[:data]
208
- # only one request, so only one answer
209
- transfer_spec=send_result['transfer_specs'].first['transfer_spec']
206
+ when :upload,:download
207
+ token_type=self.options.get_option(:token_type,:optional)
208
+ # nil if Shares 1.x
209
+ token_type=:aspera if token_type.nil?
210
+ case token_type
211
+ when :aspera,:hybrid
212
+ transfer_paths=case command
213
+ when :upload;[ { :destination => self.transfer.destination_folder('send') } ]
214
+ when :download;self.transfer.ts_source_paths
215
+ end
216
+ # only one request, so only one answer
217
+ transfer_spec=@api_node.create("files/#{command}_setup",{:transfer_requests => [ { transfer_request: {
218
+ paths: transfer_paths
219
+ }.deep_merge(@add_request_param) } ] } )[:data]['transfer_specs'].first['transfer_spec']
220
+ # delete this part, as the returned value contains only destination, and not sources
221
+ transfer_spec.delete('paths') if command.eql?(:upload)
222
+ when :basic
223
+ raise "shall have auth" unless @api_node.params[:auth].is_a?(Hash)
224
+ raise "shall be basic auth" unless @api_node.params[:auth][:type].eql?(:basic)
225
+ transfer_spec={
226
+ 'remote_host'=>URI.parse(@api_node.params[:base_url]).host,
227
+ 'remote_user'=>Aspera::Node::ACCESS_KEY_TRANSFER_USER,
228
+ 'ssh_port'=>Aspera::Node::SSH_PORT_DEFAULT,
229
+ 'direction'=>case command;when :upload;'send';when :download;'recv';else raise "Error";end
230
+ }
231
+ else raise "ERROR: token_type #{tt}"
232
+ end
233
+ if [:basic,:hybrid].include?(token_type)
234
+ Aspera::Node.set_ak_basic_token(transfer_spec,@api_node.params[:auth][:username],@api_node.params[:auth][:password])
235
+ end
210
236
  return Main.result_transfer(self.transfer.start(transfer_spec,{:src=>:node_gen3}))
211
237
  when :api_details
212
238
  return { :type=>:single_object, :data => @api_node.params }
@@ -409,9 +435,11 @@ module Aspera
409
435
  command=self.options.get_next_command([ :list, :modify])
410
436
  case command
411
437
  when :list
412
- request_data.deep_merge!({"validation"=>validation}) unless validation.nil?
413
- resp=@api_node.create('services/rest/transfers/v1/files',request_data)
414
- return {:type=>:object_list,:data=>resp[:data]["file_transfer_info_result"]["file_transfer_info"],:fields=>["session_uuid","file_id","status","path"]}
438
+ request_data.deep_merge!({'validation'=>validation}) unless validation.nil?
439
+ resp=@api_node.create('services/rest/transfers/v1/files',request_data)[:data]
440
+ resp=JSON.parse(resp) if resp.is_a?(String)
441
+ Log.dump(:resp,resp)
442
+ return {:type=>:object_list,:data=>resp['file_transfer_info_result']['file_transfer_info'],:fields=>["session_uuid","file_id","status","path"]}
415
443
  when :modify
416
444
  request_data.deep_merge!(validation) unless validation.nil?
417
445
  @api_node.update('services/rest/transfers/v1/files',request_data)
@@ -202,15 +202,17 @@ module Aspera
202
202
  if @default_transfer_spec.nil?
203
203
  # make a dummy call to get some default transfer parameters
204
204
  res=@api_node.create('files/upload_setup',{'transfer_requests'=>[{'transfer_request'=>{'paths'=>[{}],'destination_root'=>'/'}}]})
205
- sample_transfer_spec=res[:data]['transfer_specs'].first['transfer_spec']
205
+ template_ts=res[:data]['transfer_specs'].first['transfer_spec']
206
206
  # get ports, anyway that should be 33001 for both. add remote_user ?
207
- @default_transfer_spec=['ssh_port','fasp_port'].inject({}){|h,e|h[e]=sample_transfer_spec[e];h}
207
+ @default_transfer_spec=['ssh_port','fasp_port'].inject({}){|h,e|h[e]=template_ts[e];h}
208
+ if ! @default_transfer_spec['remote_user'].eql?(Aspera::Node::ACCESS_KEY_TRANSFER_USER)
209
+ Log.log.warn("remote_user shall be xfer")
210
+ @default_transfer_spec['remote_user']=Aspera::Node::ACCESS_KEY_TRANSFER_USER
211
+ end
212
+ Aspera::Node::set_ak_basic_token(@default_transfer_spec,@access_key_self['id'],self.options.get_option(:password,:mandatory))
208
213
  # note: we use the same address for ascp than for node api instead of the one from upload_setup
209
- @default_transfer_spec.merge!({
210
- 'token' => "Basic #{Base64.strict_encode64("#{@access_key_self['id']}:#{self.options.get_option(:password,:mandatory)}")}",
211
- 'remote_host' => @transfer_server_address,
212
- 'remote_user' => Fasp::ACCESS_KEY_TRANSFER_USER
213
- })
214
+ # TODO: configurable ? useful ?
215
+ @default_transfer_spec['remote_host']=@transfer_server_address
214
216
  end
215
217
  tspec=@default_transfer_spec.merge({
216
218
  'direction' => direction,
@@ -1,5 +1,6 @@
1
1
  require 'aspera/cli/basic_auth_plugin'
2
2
  require 'aspera/ascmd'
3
+ require 'aspera/node'
3
4
  require 'aspera/ssh'
4
5
  require 'aspera/nagios'
5
6
  require 'tempfile'
@@ -67,13 +68,15 @@ module Aspera
67
68
  def execute_action
68
69
  server_uri=URI.parse(self.options.get_option(:url,:mandatory))
69
70
  Log.log.debug("URI : #{server_uri}, port=#{server_uri.port}, scheme:#{server_uri.scheme}")
71
+ server_transfer_spec={'remote_host'=>server_uri.hostname}
70
72
  shell_executor=nil
71
73
  case server_uri.scheme
72
74
  when 'ssh'
73
- server_transfer_spec={
74
- 'remote_host'=>server_uri.hostname,
75
- 'remote_user'=>self.options.get_option(:username,:mandatory),
76
- }
75
+ if self.options.get_option(:username,:optional).nil?
76
+ self.options.set_option(:username,Aspera::Node::ACCESS_KEY_TRANSFER_USER)
77
+ Log.log.info("Using default transfer user: #{Aspera::Node::ACCESS_KEY_TRANSFER_USER}")
78
+ end
79
+ server_transfer_spec['remote_user']=self.options.get_option(:username,:mandatory)
77
80
  ssh_options=self.options.get_option(:ssh_options,:optional)
78
81
  raise 'expecting a Hash for ssh_options' unless ssh_options.is_a?(Hash)
79
82
  if !server_uri.port.nil?
@@ -102,8 +105,16 @@ module Aspera
102
105
  cred_set=true
103
106
  end
104
107
  end
105
- raise 'either password or key must be provided' if !cred_set
108
+ # if user provided transfer spec has a token, we will use by pass keys
109
+ cred_set=true if self.transfer.option_transfer_spec['token'].is_a?(String)
110
+ raise 'either password, key , or transfer spec token must be provided' if !cred_set
106
111
  shell_executor=Ssh.new(server_transfer_spec['remote_host'],server_transfer_spec['remote_user'],ssh_options)
112
+ when 'https'
113
+ raise "ERROR: transfer spec with token required" unless self.transfer.option_transfer_spec['token'].is_a?(String)
114
+ server_transfer_spec.merge!({
115
+ 'wss_enabled'=>true,
116
+ 'wss_port' =>server_uri.port
117
+ })
107
118
  when 'local'
108
119
  shell_executor=LocalExecutor.new
109
120
  else
@@ -1,7 +1,7 @@
1
1
  require 'aspera/fasp/local'
2
+ require 'aspera/fasp/parameters'
2
3
  require 'aspera/fasp/connect'
3
4
  require 'aspera/fasp/node'
4
- require 'aspera/fasp/aoc'
5
5
  require 'aspera/fasp/http_gw'
6
6
  require 'aspera/cli/listener/logger'
7
7
  require 'aspera/cli/listener/progress_multi'
@@ -43,9 +43,9 @@ END_OF_TEMPLATE
43
43
  options.add_opt_simple(:local_resume,"set resume policy (Hash, use @json: prefix), current=#{options.get_option(:local_resume,:optional)}")
44
44
  options.add_opt_simple(:to_folder,"destination folder for downloaded files")
45
45
  options.add_opt_simple(:sources,"list of source files (see doc)")
46
- options.add_opt_simple(:transfer_info,"additional information for transfer client")
46
+ options.add_opt_simple(:transfer_info,"parameters for transfer agent")
47
47
  options.add_opt_list(:src_type,[:list,:pair],"type of file list")
48
- options.add_opt_list(:transfer,[:direct,:httpgw,:connect,:node,:aoc],"type of transfer")
48
+ options.add_opt_list(:transfer,[:direct,:httpgw,:connect,:node],"type of transfer agent")
49
49
  options.add_opt_list(:progress,[:none,:native,:multi],"type of progress bar")
50
50
  options.set_option(:transfer,:direct)
51
51
  options.set_option(:src_type,:list)
@@ -124,22 +124,6 @@ END_OF_TEMPLATE
124
124
  new_agent=Fasp::Node.new(node_api)
125
125
  # add root id if it's an access key
126
126
  new_agent.options={root_id: node_config[:root_id]} if node_config.has_key?(:root_id)
127
- when :aoc
128
- aoc_config=options.get_option(:transfer_info,:optional)
129
- if aoc_config.nil?
130
- param_set_name=config.get_plugin_default_config_name(:aspera)
131
- raise CliBadArgument,"No default AoC configured, Please specify --#{:transfer_info.to_s.gsub('_','-')}" if param_set_name.nil?
132
- aoc_config=config.preset_by_name(param_set_name)
133
- end
134
- Log.log.debug("aoc=#{aoc_config}")
135
- raise CliBadArgument,"the aoc configuration shall be Hash, not #{aoc_config.class} (#{aoc_config}), refer to manual" if !aoc_config.is_a?(Hash)
136
- # convert keys from string (config) to symbol (agent)
137
- aoc_config=aoc_config.symbolize_keys
138
- # convert auth value from string (config) to symbol (agent)
139
- aoc_config[:auth]=aoc_config[:auth].to_sym if aoc_config[:auth].is_a?(String)
140
- # private key could be @file:... in config
141
- aoc_config[:private_key]=ExtendedValue.instance.evaluate(aoc_config[:private_key])
142
- new_agent=Fasp::Aoc.new(aoc_config)
143
127
  else
144
128
  raise "Unexpected transfer agent type: #{agent_type}"
145
129
  end
@@ -183,7 +167,8 @@ END_OF_TEMPLATE
183
167
  raise CliBadArgument,"specify at least one file on command line or use --sources=#{FILE_LIST_FROM_TRANSFER_SPEC} to use transfer spec" if !file_list.is_a?(Array) or file_list.empty?
184
168
  when FILE_LIST_FROM_TRANSFER_SPEC
185
169
  Log.log.debug("assume list provided in transfer spec")
186
- raise CliBadArgument,"transfer spec on command line must have sources" if @transfer_paths.nil?
170
+ special_case_direct_with_list=options.get_option(:transfer,:mandatory).eql?(:direct) and Fasp::Parameters.ts_has_file_list(@transfer_spec_cmdline)
171
+ raise CliBadArgument,"transfer spec on command line must have sources" if @transfer_paths.nil? and !special_case_direct_with_list
187
172
  # here we assume check of sources is made in transfer agent
188
173
  return @transfer_paths
189
174
  when Array
@@ -1,5 +1,5 @@
1
1
  module Aspera
2
2
  module Cli
3
- VERSION = "4.3.0"
3
+ VERSION = "4.4.0"
4
4
  end
5
5
  end