aspera-cli 4.3.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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