aspera-cli 4.9.0 → 4.10.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.
data/docs/test_env.conf CHANGED
@@ -6,8 +6,7 @@ default:
6
6
  aoc: tst_aoc1
7
7
  faspex: tst_faspex
8
8
  faspex5: tst_faspex5
9
- shares: tst_shares_1
10
- shares2: tst_shares2
9
+ shares: tst_shares
11
10
  node: tst_node
12
11
  server: tst_server
13
12
  orchestrator: tst_orch
@@ -74,11 +73,11 @@ tst_shares_1:
74
73
  url: your value here
75
74
  username: your value here
76
75
  password: your value here
77
- tst_shares2:
76
+ tst_node:
78
77
  url: your value here
79
78
  username: your value here
80
79
  password: your value here
81
- tst_node:
80
+ node_srv:
82
81
  url: your value here
83
82
  username: your value here
84
83
  password: your value here
@@ -118,6 +117,9 @@ tst_cos:
118
117
  crn: your value here
119
118
  bucket: your value here
120
119
  endpoint: your value here
120
+ sync:
121
+ local_path: your value here
122
+ remote_path: your value here
121
123
  misc:
122
124
  upload_folder: your value here
123
125
  syncuser: your value here
data/examples/dascli CHANGED
@@ -1,12 +1,16 @@
1
1
  #!/usr/bin/env bash
2
+ # set env var image to specify another docker image
3
+ # set env var version to specify another image version
4
+ # set env var docker_args to add options to docker run
2
5
  : ${image:=martinlaurent/ascli}
3
6
  # by default take latest version
4
7
  : ${version:=latest}
5
- imgtag=$image:$version
8
+ : ${docker:=docker}
9
+ : ${imgtag=$image:$version}
10
+ # transform var into array
11
+ add_dock_args=( $docker_args )
6
12
  # same location as in Dockerfile: main config folder for ascli in container
7
13
  ascli_home_container=/home/cliuser/.aspera/ascli
8
- # convenience: special argument to install the image
9
- case "$1" in install) docker pull $imgtag; exit 0; esac
10
14
  # set default location for config folder on host if necessary
11
15
  : ${ASCLI_HOME:=$HOME/.aspera/ascli}
12
16
  if test ! -d $ASCLI_HOME;then
@@ -14,10 +18,11 @@ if test ! -d $ASCLI_HOME;then
14
18
  # create it if necessary to allow mounting the volume in container
15
19
  mkdir -p "$ASCLI_HOME"
16
20
  fi
17
- exec docker run \
21
+ exec $docker run \
18
22
  --rm \
19
23
  --tty \
20
24
  --interactive \
21
25
  --volume "$ASCLI_HOME:$ascli_home_container" \
26
+ "${add_dock_args[@]}" \
22
27
  $imgtag \
23
28
  ascli "$@"
data/examples/faspex4.rb CHANGED
@@ -74,7 +74,7 @@ Aspera::Log.dump('job_id',job_id)
74
74
  result = transfer_client.wait_for_transfers_completion
75
75
  # notify of any transfer error
76
76
  result.reject{|i|i.eql?(:success)}.each do |e|
77
- Aspera::Log.log.error("A transfer error occured: #{e.message}")
77
+ Aspera::Log.log.error("A transfer error occurred: #{e.message}")
78
78
  end
79
79
 
80
80
  # 3: Faspex 4 API v4
data/examples/node.rb CHANGED
@@ -93,4 +93,4 @@ transfer_agent.start_transfer(transfer_spec)
93
93
  transfer_result = transfer_agent.wait_for_transfers_completion
94
94
  errors = transfer_result.reject{|i|i.eql?(:success)}
95
95
  # the transfer was not success, as there is at least one error
96
- raise "Error(s) occured: #{errors.join(',')}" if !errors.empty?
96
+ raise "Error(s) occurred: #{errors.join(',')}" if !errors.empty?
data/examples/server.rb CHANGED
@@ -90,4 +90,4 @@ $stdout.puts(JSON.generate(transfer_result))
90
90
  # get list of errors only
91
91
  errors = transfer_result.reject{|i|i.eql?(:success)}
92
92
  # the transfer was not success, as there is at least one error
93
- raise "Error(s) occured: #{errors.join(',')}" if !errors.empty?
93
+ raise "Error(s) occurred: #{errors.join(',')}" if !errors.empty?
@@ -10,9 +10,9 @@ module Aspera
10
10
  GEM_URL = "https://rubygems.org/gems/#{GEM_NAME}"
11
11
  SRC_URL = 'https://github.com/IBM/aspera-cli'
12
12
  # set this to warn in advance when minimum required ruby version will increase
13
- # for example currently minimum version is 2.4 in gemspec, but future minimum will be 2.5
13
+ # for example currently minimum version is 2.4 in gemspec, but future minimum will be different
14
14
  # set to current minimum if there is no deprecation
15
15
  # the actual current minimum required version is in gemspec at required_ruby_version
16
- RUBY_FUTURE_MINIMUM_VERSION = '2.5'
16
+ RUBY_FUTURE_MINIMUM_VERSION = '2.7'
17
17
  end
18
18
  end
@@ -87,7 +87,7 @@ module Aspera
87
87
  if @option_insecure
88
88
  url=http.inspect.gsub(/^[^ ]* /,'https://').gsub(/ [^ ]*$/,'')
89
89
  if !@ssl_warned_urls.include?(url)
90
- @plugin_env[:formater].display_message(:error,"#{WARNING_FLASH} ignoring certificate for: #{url}. Only for tests, do not use in production.")
90
+ @plugin_env[:formater].display_message(:error,"#{WARNING_FLASH} ignoring certificate for: #{url}. Do not use unsafe certificates in production.")
91
91
  @ssl_warned_urls.push(url)
92
92
  end
93
93
  http.verify_mode = SELF_SIGNED_CERT
@@ -44,15 +44,17 @@ module Aspera
44
44
  # resolves on extended value syntax
45
45
  class Manager
46
46
  # boolean options are set to true/false from the following values
47
- TRUE_VALUES = [:yes,true].freeze
48
- BOOLEAN_VALUES = [TRUE_VALUES,:no,false].flatten.freeze
49
- BOOLEAN_SIMPLE = %i[yes no].freeze
47
+ BOOLEAN_SIMPLE = %i[no yes].freeze
48
+ FALSE_VALUES = [BOOLEAN_SIMPLE.first,false].freeze
49
+ TRUE_VALUES = [BOOLEAN_SIMPLE.last,true].freeze
50
+ BOOLEAN_VALUES = [TRUE_VALUES,FALSE_VALUES].flatten.freeze
51
+
50
52
  # option name separator on command line
51
53
  OPTION_SEP_LINE = '-'
52
54
  # option name separator in code (symbol)
53
55
  OPTION_SEP_NAME = '_'
54
56
 
55
- private_constant :TRUE_VALUES,:BOOLEAN_VALUES,:OPTION_SEP_LINE,:OPTION_SEP_NAME
57
+ private_constant :FALSE_VALUES,:TRUE_VALUES,:BOOLEAN_VALUES,:OPTION_SEP_LINE,:OPTION_SEP_NAME
56
58
 
57
59
  class << self
58
60
  def enum_to_bool(enum)
@@ -35,7 +35,9 @@ module Aspera
35
35
  options.add_opt_simple(:property,'name of property to set')
36
36
  options.add_opt_simple(:id,"resource identifier (#{INSTANCE_OPS.join(',')})")
37
37
  options.add_opt_boolean(:bulk,'Bulk operation (only some)')
38
+ options.add_opt_boolean(:bfail,'Bulk operation error handling')
38
39
  options.set_option(:bulk,:no)
40
+ options.set_option(:bfail,:yes)
39
41
  options.parse_options!
40
42
  @@options_created = true # rubocop:disable Style/ClassVars
41
43
  end
@@ -72,6 +74,7 @@ module Aspera
72
74
  result = res if param.is_a?(Hash)
73
75
  result['status'] = success_msg
74
76
  rescue StandardError => e
77
+ raise e if options.get_option(:bfail)
75
78
  result['status'] = e.to_s
76
79
  end
77
80
  result_list.push(result)
@@ -140,7 +143,8 @@ module Aspera
140
143
  end
141
144
  data = item_list
142
145
  end
143
- return {type: :object_list, data: data, fields: display_fields}
146
+ return {type: :object_list, data: data, fields: display_fields} if data.empty? || data.first.is_a?(Hash)
147
+ return {type: :value_list, data: data, name: 'id'}
144
148
  when :modify
145
149
  property = options.get_option(:property)
146
150
  parameters = {property => parameters} unless property.nil?
@@ -673,7 +673,7 @@ module Aspera
673
673
  startdate_persistency&.save
674
674
  if !options.get_option(:notif_to).nil?
675
675
  events.each do |tr_event|
676
- config.send_email_template({ev: tr_event})
676
+ config.send_email_template(values: {ev: tr_event})
677
677
  end
678
678
  end
679
679
  return {type: :object_list,data: events}
@@ -4,6 +4,7 @@ require 'aspera/cli/basic_auth_plugin'
4
4
  require 'aspera/cli/extended_value'
5
5
  require 'aspera/cli/version'
6
6
  require 'aspera/cli/formater'
7
+ require 'aspera/cli/info'
7
8
  require 'aspera/fasp/installation'
8
9
  require 'aspera/fasp/parameters'
9
10
  require 'aspera/fasp/transfer_spec'
@@ -37,7 +38,6 @@ module Aspera
37
38
  CONF_PRESET_VERSION = 'version'
38
39
  CONF_PRESET_DEFAULT = 'default'
39
40
  CONF_PRESET_GLOBAL = 'global_common_defaults'
40
- CONF_PRESET_SECRETS = 'default_secrets' # pragma: allowlist secret
41
41
  CONF_PLUGIN_SYM = :config # Plugins::Config.name.split('::').last.downcase.to_sym
42
42
  CONF_GLOBAL_SYM = :config
43
43
  # old tool name
@@ -62,13 +62,14 @@ module Aspera
62
62
  EMAIL_TEST_TEMPLATE = <<~END_OF_TEMPLATE
63
63
  From: <%=from_name%> <<%=from_email%>>
64
64
  To: <<%=to%>>
65
- Subject: Amelia email test
65
+ Subject: #{GEM_NAME} email test
66
66
 
67
- It worked !
67
+ This email was sent to test #{PROGRAM_NAME}.
68
68
  END_OF_TEMPLATE
69
69
  # special extended values
70
70
  EXTV_INCLUDE_PRESETS = :incps
71
71
  EXTV_PRESET = :preset
72
+ EXTV_VAULT = :vault
72
73
  PRESET_DIG_SEPARATOR = '.'
73
74
  DEFAULT_CHECK_NEW_VERSION_DAYS = 7
74
75
  DEFAULT_PRIV_KEY_FILENAME = 'aspera_aoc_key' # pragma: allowlist secret
@@ -77,7 +78,7 @@ module Aspera
77
78
  :CONF_PRESET_GLOBAL,:PROGRAM_NAME_V1,:PROGRAM_NAME_V2,:DEFAULT_REDIRECT,:ASPERA_PLUGINS_FOLDERNAME,
78
79
  :RUBY_FILE_EXT,:AOC_COMMAND_V1,:AOC_COMMAND_V2,:AOC_COMMAND_V3,:AOC_COMMAND_CURRENT,:DEMO,
79
80
  :TRANSFER_SDK_ARCHIVE_URL,:AOC_PATH_API_CLIENTS,:DEMO_SERVER_PRESET,:EMAIL_TEST_TEMPLATE,:EXTV_INCLUDE_PRESETS,
80
- :EXTV_PRESET,:DEFAULT_CHECK_NEW_VERSION_DAYS,:DEFAULT_PRIV_KEY_FILENAME,:SERVER_COMMAND,:CONF_PRESET_SECRETS,
81
+ :EXTV_PRESET,:EXTV_VAULT,:DEFAULT_CHECK_NEW_VERSION_DAYS,:DEFAULT_PRIV_KEY_FILENAME,:SERVER_COMMAND,
81
82
  :PRESET_DIG_SEPARATOR
82
83
  def initialize(env,params)
83
84
  raise 'env and params must be Hash' unless env.is_a?(Hash) && params.is_a?(Hash)
@@ -107,6 +108,7 @@ module Aspera
107
108
  # add preset handler (needed for smtp)
108
109
  ExtendedValue.instance.set_handler(EXTV_PRESET,:reader,lambda{|v|preset_by_name(v)})
109
110
  ExtendedValue.instance.set_handler(EXTV_INCLUDE_PRESETS,:decoder,lambda{|v|expanded_with_preset_includes(v)})
111
+ ExtendedValue.instance.set_handler(EXTV_VAULT,:decoder,lambda{|v|vault_value(v)})
110
112
  # load defaults before it can be overriden
111
113
  add_plugin_default_preset(CONF_GLOBAL_SYM)
112
114
  options.parse_options!
@@ -122,18 +124,20 @@ module Aspera
122
124
  options.add_opt_boolean(:test_mode,'Wizard: skip private key check step')
123
125
  options.add_opt_simple(:preset,'-PVALUE','load the named option preset from current config file')
124
126
  options.add_opt_simple(:pkeypath,'Wizard: path to private key for JWT')
125
- options.add_opt_simple(:ascp_path,'path to ascp')
126
- options.add_opt_simple(:use_product,'use ascp from specified product')
127
- options.add_opt_simple(:smtp,'smtp configuration (extended value: hash)')
128
- options.add_opt_simple(:fpac,'proxy auto configuration script')
129
- options.add_opt_simple(:secret,'default secret')
130
- options.add_opt_simple(:secrets,'secret vault')
127
+ options.add_opt_simple(:ascp_path,'Path to ascp')
128
+ options.add_opt_simple(:use_product,'Use ascp from specified product')
129
+ options.add_opt_simple(:smtp,'SMTP configuration (extended value: hash)')
130
+ options.add_opt_simple(:fpac,'Proxy auto configuration script')
131
+ options.add_opt_simple(:proxy_credentials,'HTTP proxy credentials (Array with user and password)')
132
+ options.add_opt_simple(:secret,'Secret for access keys')
133
+ options.add_opt_simple(:vault,'Vault for secrets')
134
+ options.add_opt_simple(:vault_password,'Vault password')
131
135
  options.add_opt_simple(:sdk_url,'URL to get SDK')
132
136
  options.add_opt_simple(:sdk_folder,'SDK folder path')
133
- options.add_opt_simple(:notif_to,'email recipient for notification of transfers')
134
- options.add_opt_simple(:notif_template,'email ERB template for notification of transfers')
135
- options.add_opt_simple(:version_check_days,Integer,'period in days to check new version (zero to disable)')
136
- options.add_opt_simple(:plugin_folder,'folder where to find additional plugins')
137
+ options.add_opt_simple(:notif_to,'Email recipient for notification of transfers')
138
+ options.add_opt_simple(:notif_template,'Email ERB template for notification of transfers')
139
+ options.add_opt_simple(:version_check_days,Integer,'Period in days to check new version (zero to disable)')
140
+ options.add_opt_simple(:plugin_folder,'Folder where to find additional plugins')
137
141
  options.set_option(:use_generic_client,true)
138
142
  options.set_option(:test_mode,false)
139
143
  options.set_option(:default,true)
@@ -145,6 +149,13 @@ module Aspera
145
149
  pac_script = options.get_option(:fpac)
146
150
  # create PAC executor
147
151
  @pac_exec = Aspera::ProxyAutoConfig.new(pac_script).register_uri_generic unless pac_script.nil?
152
+ proxy_creds=options.get_option(:proxy_credentials)
153
+ if !proxy_creds.nil?
154
+ raise CliBadArgument,'proxy credentials shall be an array (#{proxy_creds.class})' unless proxy_creds.is_a?(Array)
155
+ raise CliBadArgument,'proxy credentials shall have two elements (#{proxy_creds.length})' unless proxy_creds.length.eql?(2)
156
+ @pac_exec.proxy_user=Rest.proxy_user=proxy_creds[0]
157
+ @pac_exec.proxy_pass=Rest.proxy_pass=proxy_creds[1]
158
+ end
148
159
  end
149
160
 
150
161
  # env var name to override the app's main folder
@@ -251,9 +262,9 @@ module Aspera
251
262
  require 'openssl'
252
263
  priv_key = OpenSSL::PKey::RSA.new(length)
253
264
  File.write(private_key_path,priv_key.to_s)
254
- File.chmod(0400,private_key_path)
255
265
  File.write(private_key_path + '.pub',priv_key.public_key.to_s)
256
- File.chmod(0400,private_key_path + '.pub')
266
+ Environment.restrict_file_access(private_key_path)
267
+ Environment.restrict_file_access(private_key_path + '.pub')
257
268
  nil
258
269
  end
259
270
 
@@ -479,11 +490,14 @@ module Aspera
479
490
  Log.log.error('YAML error in config file')
480
491
  raise e
481
492
  rescue StandardError => e
482
- Log.log.debug("-> #{e}")
483
- new_name = "#{@option_config_file}.pre#{@info[:version]}.manual_conversion_needed"
484
- File.rename(@option_config_file,new_name)
485
- Log.log.warn("Renamed config file to #{new_name}.")
486
- Log.log.warn('Manual Conversion is required. Next time, a new empty file will be created.')
493
+ Log.log.debug("-> #{e.class.name} : #{e}")
494
+ if File.exist?(@option_config_file)
495
+ # then there is a problem with that file.
496
+ new_name = "#{@option_config_file}.pre#{@info[:version]}.manual_conversion_needed"
497
+ File.rename(@option_config_file,new_name)
498
+ Log.log.warn("Renamed config file to #{new_name}.")
499
+ Log.log.warn('Manual Conversion is required. Next time, a new empty file will be created.')
500
+ end
487
501
  raise CliError,e.to_s
488
502
  end
489
503
  end
@@ -621,7 +635,8 @@ module Aspera
621
635
  last_line = line
622
636
  case line
623
637
  when %r{^DBG Path ([^ ]+) (dir|file) +: (.*)$} then data[Regexp.last_match(1)] = Regexp.last_match(3)
624
- when %r{^DBG Added module group:"([^"]+)" name:"([^"]+)", version:"([^"]+)" interface:"([^"]+)"$} then data[Regexp.last_match(2)] = Regexp.last_match(4)
638
+ when %r{^DBG Added module group:"([^"]+)" name:"([^"]+)", version:"([^"]+)" interface:"([^"]+)"$}
639
+ data[Regexp.last_match(2)] = "#{Regexp.last_match(4)} #{Regexp.last_match(1)} v#{Regexp.last_match(3)}"
625
640
  when %r{^DBG License result \(/license/(\S+)\): (.+)$} then data[Regexp.last_match(1)] = Regexp.last_match(2)
626
641
  when %r{^LOG (.+) version ([0-9.]+)$} then data['product_name'] = Regexp.last_match(1);data['product_version'] = Regexp.last_match(2)
627
642
  when %r{^LOG Initializing FASP version ([^,]+),} then data['ascp_version'] = Regexp.last_match(1)
@@ -891,7 +906,7 @@ module Aspera
891
906
  when :file
892
907
  return Main.result_status(@option_config_file)
893
908
  when :email_test
894
- send_email_template({},EMAIL_TEST_TEMPLATE)
909
+ send_email_template(email_template_default: EMAIL_TEST_TEMPLATE)
895
910
  return Main.result_nothing
896
911
  when :smtp_settings
897
912
  return {type: :single_object, data: email_settings}
@@ -924,46 +939,7 @@ module Aspera
924
939
  end
925
940
  save_presets_to_config_file
926
941
  return Main.result_status('Done')
927
- when :vault
928
- command = options.get_next_command(%i[init list get set delete])
929
- case command
930
- when :init
931
- type = options.get_option(:value)
932
- case type
933
- when 'config',NilClass
934
- raise 'default secrets already exists' if @config_presets.has_key?(CONF_PRESET_SECRETS)
935
- @config_presets[CONF_PRESET_SECRETS] = {}
936
- set_global_default(:secrets,"@preset:#{CONF_PRESET_SECRETS}")
937
- else raise 'no such vault type'
938
- end
939
- return Main.result_status('Done')
940
- when :list
941
- return {type: :object_list, data: vault.list}
942
- when :set
943
- # register url option
944
- BasicAuthPlugin.register_options(@agents)
945
- username = options.get_option(:username,is_type: :mandatory)
946
- url = options.get_option(:url,is_type: :mandatory)
947
- description = options.get_option(:value)
948
- secret = options.get_next_argument('secret')
949
- vault.set(username: username, url: url, description: description, secret: secret)
950
- save_presets_to_config_file if vault.is_a?(Keychain::EncryptedHash)
951
- return Main.result_status('Done')
952
- when :get
953
- # register url option
954
- BasicAuthPlugin.register_options(@agents)
955
- username = options.get_option(:username,is_type: :mandatory)
956
- url = options.get_option(:url)
957
- result = vault.get(username: username, url: url)
958
- return {type: :single_object, data: result}
959
- when :delete
960
- # register url option
961
- BasicAuthPlugin.register_options(@agents)
962
- username = options.get_option(:username,is_type: :mandatory)
963
- url = options.get_option(:url)
964
- vault.delete(username: username, url: url)
965
- return Main.result_status('Done')
966
- end
942
+ when :vault then execute_vault
967
943
  else raise 'INTERNAL ERROR: wrong case'
968
944
  end
969
945
  end
@@ -992,21 +968,21 @@ module Aspera
992
968
  Kernel.binding
993
969
  end
994
970
 
995
- def send_email_template(vars,email_template_default=nil)
996
- vars[:to] ||= options.get_option(:notif_to,is_type: :mandatory)
971
+ def send_email_template(email_template_default: nil, values: {})
972
+ values[:to] ||= options.get_option(:notif_to,is_type: :mandatory)
997
973
  notif_template = options.get_option(:notif_template,is_type: email_template_default.nil? ? :mandatory : :optional) || email_template_default
998
974
  mail_conf = email_settings
999
- vars[:from_name] ||= mail_conf[:from_name]
1000
- vars[:from_email] ||= mail_conf[:from_email]
975
+ values[:from_name] ||= mail_conf[:from_name]
976
+ values[:from_email] ||= mail_conf[:from_email]
1001
977
  %i[from_name from_email].each do |n|
1002
- raise "Missing email parameter: #{n}" unless vars.has_key?(n)
978
+ raise "Missing email parameter: #{n}" unless values.has_key?(n)
1003
979
  end
1004
980
  start_options = [mail_conf[:domain]]
1005
981
  start_options.push(mail_conf[:username],mail_conf[:password],:login) if mail_conf.has_key?(:username) && mail_conf.has_key?(:password)
1006
- # create a binding with only variables defined in vars
982
+ # create a binding with only variables defined in values
1007
983
  template_binding = empty_binding
1008
984
  # add variables to binding
1009
- vars.each do |k,v|
985
+ values.each do |k,v|
1010
986
  raise "key (#{k.class}) must be Symbol" unless k.is_a?(Symbol)
1011
987
  template_binding.local_variable_set(k,v)
1012
988
  end
@@ -1016,17 +992,17 @@ module Aspera
1016
992
  smtp = Net::SMTP.new(mail_conf[:server], mail_conf[:port])
1017
993
  smtp.enable_starttls if mail_conf[:tls]
1018
994
  smtp.start(*start_options) do |smtp_session|
1019
- smtp_session.send_message(msg_with_headers, vars[:from_email], vars[:to])
995
+ smtp_session.send_message(msg_with_headers, values[:from_email], values[:to])
1020
996
  end
1021
997
  end
1022
998
 
1023
999
  def save_presets_to_config_file
1024
1000
  raise 'no configuration loaded' if @config_presets.nil?
1025
1001
  FileUtils.mkdir_p(@main_folder) unless Dir.exist?(@main_folder)
1026
- File.chmod(0700,@main_folder)
1027
1002
  Log.log.debug("Writing #{@option_config_file}")
1028
1003
  File.write(@option_config_file,@config_presets.to_yaml)
1029
- File.chmod(0600,@option_config_file)
1004
+ Environment.restrict_file_access(@main_folder)
1005
+ Environment.restrict_file_access(@option_config_file)
1030
1006
  end
1031
1007
 
1032
1008
  # returns [String] name if config_presets has default
@@ -1051,25 +1027,65 @@ module Aspera
1051
1027
  return nil
1052
1028
  end # get_plugin_default_config_name
1053
1029
 
1030
+ ALLOWED_KEYS=%i[password username description].freeze
1031
+ def execute_vault
1032
+ command = options.get_next_command(%i[list show create delete password])
1033
+ case command
1034
+ when :list
1035
+ return {type: :object_list, data: vault.list}
1036
+ when :show
1037
+ return {type: :single_object, data: vault.get(label: options.get_next_argument('label'))}
1038
+ when :create
1039
+ label=options.get_next_argument('label')
1040
+ info=options.get_next_argument('info Hash')
1041
+ raise 'info must be Hash' unless info.is_a?(Hash)
1042
+ info=info.symbolize_keys
1043
+ info[:label]=label
1044
+ vault.set(info)
1045
+ return Main.result_status('Password added')
1046
+ when :delete
1047
+ vault.delete(label: options.get_next_argument('label'))
1048
+ return Main.result_status('Password deleted')
1049
+ when :password
1050
+ raise 'Vault does not support password change' unless vault.respond_to?(:password=)
1051
+ new_password=options.get_next_argument('new_password')
1052
+ vault.password=new_password
1053
+ vault.save
1054
+ return Main.result_status('Password updated')
1055
+ end
1056
+ end
1057
+
1058
+ def vault_value(name)
1059
+ m=name.match(/^(.+)\.(.+)$/)
1060
+ raise 'vault name shall match <name>.<param>' if m.nil?
1061
+ info=vault.get(label: m[1])
1062
+ #raise "no such vault entry: #{m[1]}" if info.nil?
1063
+ value=info[m[2].to_sym]
1064
+ raise "no such entry value: #{m[2]}" if value.nil?
1065
+ return value
1066
+ end
1067
+
1054
1068
  def vault
1055
1069
  if @vault.nil?
1056
- vault_info = options.get_option(:secrets)
1057
- case vault_info
1058
- when Hash
1059
- @vault = Keychain::EncryptedHash.new(vault_info)
1060
- when /^system/
1061
- name = vault_info.start_with?('system:') ? vault_info[7..-1] : nil
1070
+ vault_info = options.get_option(:vault) || {'type'=>'file','name'=>'vault.bin'}
1071
+ vault_password = options.get_option(:vault_password,is_type: :mandatory)
1072
+ raise 'vault must be Hash' unless vault_info.is_a?(Hash)
1073
+ vault_type = vault_info['type'] || 'file'
1074
+ vault_name = vault_info['name'] || (vault_type.eql?('file') ? 'vault.bin' : PROGRAM_NAME)
1075
+ case vault_type
1076
+ when 'file'
1077
+ vault_path=vault_name
1078
+ @vault = Keychain::EncryptedHash.new(vault_path,vault_password)
1079
+ when 'system'
1062
1080
  case Environment.os
1063
1081
  when Environment::OS_X
1064
- @vault = Keychain::MacosSecurity.new(name)
1082
+ @vault = Keychain::MacosSystem.new(vault_name,vault_password)
1065
1083
  when Environment::OS_WINDOWS,Environment::OS_LINUX,Environment::OS_AIX
1066
1084
  raise 'not implemented'
1067
- else raise 'Error'
1085
+ else raise 'Error, OS not supported'
1068
1086
  end
1069
- when NilClass
1070
- # keep nil
1071
1087
  else
1072
- raise CliBadArgument,'secrets shall be Hash'
1088
+ raise CliBadArgument,"Unknown vault type: #{vault_type}"
1073
1089
  end
1074
1090
  end
1075
1091
  raise 'No vault defined' if @vault.nil?
@@ -56,7 +56,7 @@ module Aspera
56
56
  # extract elements from anonymous faspex link
57
57
  def get_link_data(publink)
58
58
  publink_uri = URI.parse(publink)
59
- raise CliBadArgument, 'public link does not match Faspex format' unless (m = publink_uri.path.match(/^(.*)\/(external.*)$/))
59
+ raise CliBadArgument, 'Public link does not match Faspex format' unless (m = publink_uri.path.match(/^(.*)\/(external.*)$/))
60
60
  base = m[1]
61
61
  subpath = m[2]
62
62
  port_add = publink_uri.port.eql?(publink_uri.default_port) ? '' : ":#{publink_uri.port}"
@@ -236,7 +236,7 @@ module Aspera
236
236
  begin
237
237
  pkgdatares = JSON.parse("[#{pkgdatares}]")
238
238
  rescue JSON::ParserError # => e
239
- raise 'Link not valid'
239
+ raise 'Unexpected response: missing metadata ?'
240
240
  end
241
241
  return pkgdatares.first
242
242
  end
@@ -357,7 +357,7 @@ module Aspera
357
357
  headers: {'Accept' => 'application/xml'})
358
358
  if !pkgdatares[:http].body.start_with?('<?xml ')
359
359
  OpenApplication.instance.uri(link_url)
360
- raise CliError, 'no such package'
360
+ raise CliError, 'Unexpected response: package not found ?'
361
361
  end
362
362
  package_entry = XmlSimple.xml_in(pkgdatares[:http].body, {'ForceArray' => false})
363
363
  Log.dump(:package_entry,package_entry)
@@ -82,12 +82,14 @@ module Aspera
82
82
  end
83
83
  end
84
84
 
85
- ACTIONS = %i[health package admin user].freeze
85
+ ACTIONS = %i[health version user bearer_token package admin].freeze
86
86
 
87
87
  def execute_action
88
88
  set_api
89
89
  command = options.get_next_command(ACTIONS)
90
90
  case command
91
+ when :version
92
+ return { type: :single_object, data: @api_v5.read('version')[:data] }
91
93
  when :health
92
94
  nagios = Nagios.new
93
95
  begin
@@ -110,6 +112,8 @@ module Aspera
110
112
  return Main.result_status('modified')
111
113
  end
112
114
  end
115
+ when :bearer_token
116
+ return {type: :text,data: @api_v5.oauth_token}
113
117
  when :package
114
118
  command = options.get_next_command(%i[list show send receive])
115
119
  case command
@@ -427,6 +427,7 @@ module Aspera
427
427
  raise 'ERR'
428
428
  end # execute_node_gen4_command
429
429
 
430
+ # This is older API
430
431
  def execute_async
431
432
  command = options.get_next_command(%i[list delete files show counters bandwidth])
432
433
  unless command.eql?(:list)
@@ -504,13 +505,27 @@ module Aspera
504
505
  end
505
506
  end
506
507
 
507
- ACTIONS = %i[postprocess stream transfer cleanup forward access_key watch_folder service async central asperabrowser basic_token].concat(COMMON_ACTIONS).freeze
508
+ ACTIONS = %i[postprocess stream transfer cleanup forward access_key watch_folder service async sync central asperabrowser
509
+ basic_token].concat(COMMON_ACTIONS).freeze
508
510
 
509
511
  def execute_action(command=nil,prefix_path=nil)
510
512
  command ||= options.get_next_command(ACTIONS)
511
513
  case command
512
514
  when *COMMON_ACTIONS then return execute_simple_common(command,prefix_path)
513
515
  when :async then return execute_async
516
+ when :sync
517
+ sync_command = options.get_next_command([Plugin::ALL_OPS,%i[bandwidth counters files start state stop summary]].flatten-%i[modify])
518
+ case sync_command
519
+ when *Plugin::ALL_OPS then return entity_command(sync_command,@api_node,'asyncs',item_list_key: 'ids')
520
+ else
521
+ parameters = options.get_option(:value)
522
+ asyncs_id=instance_identifier
523
+ if %i[start stop].include?(sync_command)
524
+ @api_node.create("asyncs/#{asyncs_id}/#{sync_command}",parameters)
525
+ return Main.result_status('ok')
526
+ end
527
+ return { type: :single_object, data: @api_node.read("asyncs/#{asyncs_id}/#{sync_command}",parameters)[:data] }
528
+ end
514
529
  when :stream
515
530
  command = options.get_next_command(%i[list create show modify cancel])
516
531
  case command
@@ -545,7 +560,9 @@ module Aspera
545
560
  case command
546
561
  when :list
547
562
  # could use ? subpath: 'transfers'
548
- resp = @api_node.read(res_class_path,options.get_option(:value))
563
+ query=options.get_option(:value) || options.get_option(:query)
564
+ raise 'Query must be a Hash' unless query.nil? || query.is_a?(Hash)
565
+ resp = @api_node.read(res_class_path,query)
549
566
  return {
550
567
  type: :object_list,
551
568
  data: resp[:data],
@@ -635,8 +652,11 @@ module Aspera
635
652
  when :list
636
653
  request_data.deep_merge!({'validation' => validation}) unless validation.nil?
637
654
  resp = @api_node.create('services/rest/transfers/v1/sessions',request_data)
638
- return { type: :object_list, data: resp[:data]['session_info_result']['session_info'],
639
- fields: %w[session_uuid status transport direction bytes_transferred]}
655
+ return {
656
+ type: :object_list,
657
+ data: resp[:data]['session_info_result']['session_info'],
658
+ fields: %w[session_uuid status transport direction bytes_transferred]
659
+ }
640
660
  end
641
661
  when :file
642
662
  command = options.get_next_command(%i[list modify])
@@ -397,7 +397,7 @@ module Aspera
397
397
  Log.log.warn("unknown entry type: #{entry['type']}")
398
398
  end
399
399
  rescue StandardError => e
400
- Log.log.warn("An error occured: #{e}, ignoring")
400
+ Log.log.warn("An error occurred: #{e}, ignoring")
401
401
  end
402
402
  end
403
403
  end
@@ -3,6 +3,7 @@
3
3
  require 'aspera/fasp/transfer_spec'
4
4
  require 'aspera/cli/listener/logger'
5
5
  require 'aspera/cli/listener/progress_multi'
6
+ require 'aspera/cli/info'
6
7
 
7
8
  module Aspera
8
9
  module Cli
@@ -230,11 +231,11 @@ module Aspera
230
231
  global_status = self.class.session_status(statuses)
231
232
  email_vars = {
232
233
  global_transfer_status: global_status,
233
- subject: "ascli transfer: #{global_status}",
234
+ subject: "#{PROGRAM_NAME} transfer: #{global_status}",
234
235
  body: "Transfer is: #{global_status}",
235
236
  ts: transfer_spec
236
237
  }
237
- @config.send_email_template(email_vars,DEFAULT_TRANSFER_NOTIF_TMPL)
238
+ @config.send_email_template(email_template_default: DEFAULT_TRANSFER_NOTIF_TMPL, values: email_vars)
238
239
  end
239
240
 
240
241
  # shut down if agent requires it
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Aspera
4
4
  module Cli
5
- VERSION = '4.9.0'
5
+ VERSION = '4.10.0'
6
6
  end
7
7
  end