aspera-cli 4.15.0 → 4.16.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.
- checksums.yaml +4 -4
 - checksums.yaml.gz.sig +0 -0
 - data/BUGS.md +29 -3
 - data/CHANGELOG.md +292 -228
 - data/CONTRIBUTING.md +69 -18
 - data/README.md +1102 -952
 - data/bin/ascli +13 -31
 - data/bin/asession +3 -1
 - data/examples/dascli +2 -2
 - data/lib/aspera/aoc.rb +28 -33
 - data/lib/aspera/ascmd.rb +3 -6
 - data/lib/aspera/assert.rb +45 -0
 - data/lib/aspera/cli/extended_value.rb +5 -5
 - data/lib/aspera/cli/formatter.rb +26 -13
 - data/lib/aspera/cli/hints.rb +4 -3
 - data/lib/aspera/cli/main.rb +16 -3
 - data/lib/aspera/cli/manager.rb +45 -36
 - data/lib/aspera/cli/plugin.rb +20 -13
 - data/lib/aspera/cli/plugins/aoc.rb +103 -73
 - data/lib/aspera/cli/plugins/ats.rb +4 -3
 - data/lib/aspera/cli/plugins/config.rb +114 -119
 - data/lib/aspera/cli/plugins/cos.rb +2 -2
 - data/lib/aspera/cli/plugins/faspex.rb +23 -19
 - data/lib/aspera/cli/plugins/faspex5.rb +75 -43
 - data/lib/aspera/cli/plugins/node.rb +28 -15
 - data/lib/aspera/cli/plugins/orchestrator.rb +4 -2
 - data/lib/aspera/cli/plugins/preview.rb +9 -7
 - data/lib/aspera/cli/plugins/server.rb +6 -3
 - data/lib/aspera/cli/plugins/shares.rb +30 -26
 - data/lib/aspera/cli/sync_actions.rb +9 -9
 - data/lib/aspera/cli/transfer_agent.rb +21 -14
 - data/lib/aspera/cli/transfer_progress.rb +2 -3
 - data/lib/aspera/cli/version.rb +1 -1
 - data/lib/aspera/command_line_builder.rb +13 -11
 - data/lib/aspera/cos_node.rb +3 -2
 - data/lib/aspera/coverage.rb +22 -0
 - data/lib/aspera/data_repository.rb +33 -2
 - data/lib/aspera/environment.rb +4 -2
 - data/lib/aspera/fasp/{agent_aspera.rb → agent_alpha.rb} +29 -39
 - data/lib/aspera/fasp/agent_base.rb +17 -7
 - data/lib/aspera/fasp/agent_direct.rb +88 -84
 - data/lib/aspera/fasp/agent_httpgw.rb +4 -3
 - data/lib/aspera/fasp/agent_node.rb +3 -2
 - data/lib/aspera/fasp/agent_trsdk.rb +79 -37
 - data/lib/aspera/fasp/installation.rb +51 -12
 - data/lib/aspera/fasp/management.rb +11 -6
 - data/lib/aspera/fasp/parameters.rb +53 -47
 - data/lib/aspera/fasp/resume_policy.rb +7 -5
 - data/lib/aspera/fasp/sync.rb +273 -0
 - data/lib/aspera/fasp/transfer_spec.rb +10 -8
 - data/lib/aspera/fasp/uri.rb +2 -2
 - data/lib/aspera/faspex_gw.rb +11 -8
 - data/lib/aspera/faspex_postproc.rb +6 -5
 - data/lib/aspera/id_generator.rb +3 -1
 - data/lib/aspera/json_rpc.rb +10 -8
 - data/lib/aspera/keychain/encrypted_hash.rb +46 -11
 - data/lib/aspera/keychain/macos_security.rb +15 -13
 - data/lib/aspera/log.rb +4 -3
 - data/lib/aspera/nagios.rb +7 -2
 - data/lib/aspera/node.rb +17 -16
 - data/lib/aspera/node_simulator.rb +214 -0
 - data/lib/aspera/oauth.rb +22 -19
 - data/lib/aspera/persistency_action_once.rb +13 -14
 - data/lib/aspera/persistency_folder.rb +3 -2
 - data/lib/aspera/preview/file_types.rb +53 -267
 - data/lib/aspera/preview/generator.rb +7 -5
 - data/lib/aspera/preview/terminal.rb +14 -5
 - data/lib/aspera/preview/utils.rb +8 -7
 - data/lib/aspera/proxy_auto_config.rb +6 -3
 - data/lib/aspera/rest.rb +29 -13
 - data/lib/aspera/rest_error_analyzer.rb +1 -0
 - data/lib/aspera/rest_errors_aspera.rb +2 -0
 - data/lib/aspera/secret_hider.rb +5 -2
 - data/lib/aspera/ssh.rb +10 -8
 - data/lib/aspera/temp_file_manager.rb +1 -1
 - data/lib/aspera/web_server_simple.rb +2 -1
 - data.tar.gz.sig +0 -0
 - metadata +96 -45
 - metadata.gz.sig +0 -0
 - data/lib/aspera/sync.rb +0 -219
 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            # cspell:ignore initdemo genkey asperasoft
         
     | 
| 
      
 3 
     | 
    
         
            +
            # cspell:ignore initdemo genkey pubkey asperasoft
         
     | 
| 
       4 
4 
     | 
    
         
             
            require 'aspera/cli/basic_auth_plugin'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'aspera/cli/extended_value'
         
     | 
| 
       6 
6 
     | 
    
         
             
            require 'aspera/cli/version'
         
     | 
| 
         @@ -19,9 +19,11 @@ require 'aspera/open_application' 
     | 
|
| 
       19 
19 
     | 
    
         
             
            require 'aspera/persistency_action_once'
         
     | 
| 
       20 
20 
     | 
    
         
             
            require 'aspera/id_generator'
         
     | 
| 
       21 
21 
     | 
    
         
             
            require 'aspera/persistency_folder'
         
     | 
| 
      
 22 
     | 
    
         
            +
            require 'aspera/data_repository'
         
     | 
| 
       22 
23 
     | 
    
         
             
            require 'aspera/line_logger'
         
     | 
| 
       23 
24 
     | 
    
         
             
            require 'aspera/rest'
         
     | 
| 
       24 
25 
     | 
    
         
             
            require 'aspera/log'
         
     | 
| 
      
 26 
     | 
    
         
            +
            require 'aspera/assert'
         
     | 
| 
       25 
27 
     | 
    
         
             
            require 'open3'
         
     | 
| 
       26 
28 
     | 
    
         
             
            require 'date'
         
     | 
| 
       27 
29 
     | 
    
         
             
            require 'erb'
         
     | 
| 
         @@ -35,11 +37,13 @@ module Aspera 
     | 
|
| 
       35 
37 
     | 
    
         
             
                    ASPERA_HOME_FOLDER_NAME = '.aspera'
         
     | 
| 
       36 
38 
     | 
    
         
             
                    # default config file
         
     | 
| 
       37 
39 
     | 
    
         
             
                    DEFAULT_CONFIG_FILENAME = 'config.yaml'
         
     | 
| 
      
 40 
     | 
    
         
            +
                    DEFAULT_VAULT_FILENAME = 'vault.bin'
         
     | 
| 
       38 
41 
     | 
    
         
             
                    # reserved preset names
         
     | 
| 
       39 
42 
     | 
    
         
             
                    CONF_PRESET_CONFIG = 'config'
         
     | 
| 
       40 
43 
     | 
    
         
             
                    CONF_PRESET_VERSION = 'version'
         
     | 
| 
       41 
     | 
    
         
            -
                     
     | 
| 
      
 44 
     | 
    
         
            +
                    CONF_PRESET_DEFAULTS = 'default'
         
     | 
| 
       42 
45 
     | 
    
         
             
                    CONF_PRESET_GLOBAL = 'global_common_defaults'
         
     | 
| 
      
 46 
     | 
    
         
            +
                    # special name to identify value of default
         
     | 
| 
       43 
47 
     | 
    
         
             
                    GLOBAL_DEFAULT_KEYWORD = 'GLOBAL'
         
     | 
| 
       44 
48 
     | 
    
         
             
                    CONF_PLUGIN_SYM = :config # Plugins::Config.name.split('::').last.downcase.to_sym
         
     | 
| 
       45 
49 
     | 
    
         
             
                    CONF_GLOBAL_SYM = :config
         
     | 
| 
         @@ -77,7 +81,7 @@ module Aspera 
     | 
|
| 
       77 
81 
     | 
    
         
             
                    private_constant :DEFAULT_CONFIG_FILENAME,
         
     | 
| 
       78 
82 
     | 
    
         
             
                      :CONF_PRESET_CONFIG,
         
     | 
| 
       79 
83 
     | 
    
         
             
                      :CONF_PRESET_VERSION,
         
     | 
| 
       80 
     | 
    
         
            -
                      : 
     | 
| 
      
 84 
     | 
    
         
            +
                      :CONF_PRESET_DEFAULTS,
         
     | 
| 
       81 
85 
     | 
    
         
             
                      :CONF_PRESET_GLOBAL,
         
     | 
| 
       82 
86 
     | 
    
         
             
                      :ASPERA_PLUGINS_FOLDERNAME,
         
     | 
| 
       83 
87 
     | 
    
         
             
                      :RUBY_FILE_EXT,
         
     | 
| 
         @@ -141,20 +145,22 @@ module Aspera 
     | 
|
| 
       141 
145 
     | 
    
         
             
                      # return product family folder (~/.aspera)
         
     | 
| 
       142 
146 
     | 
    
         
             
                      def module_family_folder
         
     | 
| 
       143 
147 
     | 
    
         
             
                        user_home_folder = Dir.home
         
     | 
| 
       144 
     | 
    
         
            -
                         
     | 
| 
      
 148 
     | 
    
         
            +
                        assert(Dir.exist?(user_home_folder), exception_class: Cli::Error){"Home folder does not exist: #{user_home_folder}. Check your user environment."}
         
     | 
| 
       145 
149 
     | 
    
         
             
                        return File.join(user_home_folder, ASPERA_HOME_FOLDER_NAME)
         
     | 
| 
       146 
150 
     | 
    
         
             
                      end
         
     | 
| 
       147 
151 
     | 
    
         | 
| 
       148 
152 
     | 
    
         
             
                      # return product config folder (~/.aspera/<name>)
         
     | 
| 
       149 
153 
     | 
    
         
             
                      def default_app_main_folder(app_name:)
         
     | 
| 
       150 
     | 
    
         
            -
                         
     | 
| 
      
 154 
     | 
    
         
            +
                        assert_type(app_name, String)
         
     | 
| 
      
 155 
     | 
    
         
            +
                        assert(!app_name.empty?)
         
     | 
| 
       151 
156 
     | 
    
         
             
                        return File.join(module_family_folder, app_name)
         
     | 
| 
       152 
157 
     | 
    
         
             
                      end
         
     | 
| 
       153 
158 
     | 
    
         
             
                    end # self
         
     | 
| 
       154 
159 
     | 
    
         | 
| 
       155 
160 
     | 
    
         
             
                    def initialize(env, params)
         
     | 
| 
       156 
     | 
    
         
            -
                       
     | 
| 
       157 
     | 
    
         
            -
                       
     | 
| 
      
 161 
     | 
    
         
            +
                      assert_type(env, Hash)
         
     | 
| 
      
 162 
     | 
    
         
            +
                      assert_type(params, Hash)
         
     | 
| 
      
 163 
     | 
    
         
            +
                      assert(%i[gem help name version].eql?(params.keys.sort)){'missing param'}
         
     | 
| 
       158 
164 
     | 
    
         
             
                      # we need to defer parsing of options until we have the config file, so we can use @extend with @preset
         
     | 
| 
       159 
165 
     | 
    
         
             
                      super(env)
         
     | 
| 
       160 
166 
     | 
    
         
             
                      @info = params
         
     | 
| 
         @@ -168,6 +174,7 @@ module Aspera 
     | 
|
| 
       168 
174 
     | 
    
         
             
                      @pac_exec = nil
         
     | 
| 
       169 
175 
     | 
    
         
             
                      @sdk_default_location = false
         
     | 
| 
       170 
176 
     | 
    
         
             
                      @option_insecure = false
         
     | 
| 
      
 177 
     | 
    
         
            +
                      @option_warn_insecure_cert = true
         
     | 
| 
       171 
178 
     | 
    
         
             
                      @option_ignore_cert_host_port = []
         
     | 
| 
       172 
179 
     | 
    
         
             
                      @option_http_options = {}
         
     | 
| 
       173 
180 
     | 
    
         
             
                      @ssl_warned_urls = []
         
     | 
| 
         @@ -233,7 +240,8 @@ module Aspera 
     | 
|
| 
       233 
240 
     | 
    
         
             
                      options.declare(:notify_template, 'Email ERB template for notification of transfers')
         
     | 
| 
       234 
241 
     | 
    
         
             
                      # HTTP options
         
     | 
| 
       235 
242 
     | 
    
         
             
                      options.declare(:insecure, 'Do not validate any HTTPS certificate', values: :bool, handler: {o: self, m: :option_insecure}, default: :no)
         
     | 
| 
       236 
     | 
    
         
            -
                      options.declare(:ignore_certificate, ' 
     | 
| 
      
 243 
     | 
    
         
            +
                      options.declare(:ignore_certificate, 'Do not validate HTTPS certificate for these URLs', types: Array, handler: {o: self, m: :option_ignore_cert_host_port})
         
     | 
| 
      
 244 
     | 
    
         
            +
                      options.declare(:silent_insecure, 'Issue a warning if certificate is ignored', values: :bool, handler: {o: self, m: :option_warn_insecure_cert}, default: :yes)
         
     | 
| 
       237 
245 
     | 
    
         
             
                      options.declare(:cert_stores, 'List of folder with trusted certificates', types: [Array, String], handler: {o: self, m: :trusted_cert_locations})
         
     | 
| 
       238 
246 
     | 
    
         
             
                      options.declare(:http_options, 'Options for HTTP/S socket', types: Hash, handler: {o: self, m: :option_http_options}, default: {})
         
     | 
| 
       239 
247 
     | 
    
         
             
                      options.declare(:cache_tokens, 'Save and reuse Oauth tokens', values: :bool, handler: {o: self, m: :option_cache_tokens})
         
     | 
| 
         @@ -264,7 +272,7 @@ module Aspera 
     | 
|
| 
       264 
272 
     | 
    
         
             
                      @pac_exec = Aspera::ProxyAutoConfig.new(pac_script).register_uri_generic unless pac_script.nil?
         
     | 
| 
       265 
273 
     | 
    
         
             
                      proxy_user_pass = options.get_option(:proxy_credentials)
         
     | 
| 
       266 
274 
     | 
    
         
             
                      if !proxy_user_pass.nil?
         
     | 
| 
       267 
     | 
    
         
            -
                         
     | 
| 
      
 275 
     | 
    
         
            +
                        assert(proxy_user_pass.length.eql?(2), exception_class: Cli::BadArgument){"proxy_credentials shall have two elements (#{proxy_user_pass.length})"}
         
     | 
| 
       268 
276 
     | 
    
         
             
                        @proxy_credentials = {user: proxy_user_pass[0], pass: proxy_user_pass[1]}
         
     | 
| 
       269 
277 
     | 
    
         
             
                        @pac_exec.proxy_user = @proxy_credentials[:user]
         
     | 
| 
       270 
278 
     | 
    
         
             
                        @pac_exec.proxy_pass = @proxy_credentials[:pass]
         
     | 
| 
         @@ -280,7 +288,7 @@ module Aspera 
     | 
|
| 
       280 
288 
     | 
    
         
             
                      Aspera::RestErrorsAspera.register_handlers
         
     | 
| 
       281 
289 
     | 
    
         
             
                    end
         
     | 
| 
       282 
290 
     | 
    
         | 
| 
       283 
     | 
    
         
            -
                    attr_accessor :main_folder, :option_cache_tokens, :option_insecure, :option_http_options
         
     | 
| 
      
 291 
     | 
    
         
            +
                    attr_accessor :main_folder, :option_cache_tokens, :option_insecure, :option_warn_insecure_cert, :option_http_options
         
     | 
| 
       284 
292 
     | 
    
         
             
                    attr_reader :option_ignore_cert_host_port, :progress_bar
         
     | 
| 
       285 
293 
     | 
    
         | 
| 
       286 
294 
     | 
    
         
             
                    def trusted_cert_locations=(path_list)
         
     | 
| 
         @@ -293,7 +301,7 @@ module Aspera 
     | 
|
| 
       293 
301 
     | 
    
         
             
                      end
         
     | 
| 
       294 
302 
     | 
    
         | 
| 
       295 
303 
     | 
    
         
             
                      path_list.each do |path|
         
     | 
| 
       296 
     | 
    
         
            -
                         
     | 
| 
      
 304 
     | 
    
         
            +
                        assert_type(path, String){'Expecting a String for cert location'}
         
     | 
| 
       297 
305 
     | 
    
         
             
                        Log.log.debug("Adding cert location: #{path}")
         
     | 
| 
       298 
306 
     | 
    
         
             
                        if path.eql?(ExtendedValue::DEF)
         
     | 
| 
       299 
307 
     | 
    
         
             
                          path = OpenSSL::X509::DEFAULT_CERT_DIR
         
     | 
| 
         @@ -325,22 +333,28 @@ module Aspera 
     | 
|
| 
       325 
333 
     | 
    
         
             
                    def option_ignore_cert_host_port=(url_list)
         
     | 
| 
       326 
334 
     | 
    
         
             
                      url_list.each do |url|
         
     | 
| 
       327 
335 
     | 
    
         
             
                        uri = URI.parse(url)
         
     | 
| 
      
 336 
     | 
    
         
            +
                        raise "Expecting https scheme: #{url}" unless uri.scheme.eql?('https')
         
     | 
| 
       328 
337 
     | 
    
         
             
                        @option_ignore_cert_host_port.push([uri.host, uri.port].freeze)
         
     | 
| 
       329 
338 
     | 
    
         
             
                      end
         
     | 
| 
       330 
339 
     | 
    
         
             
                    end
         
     | 
| 
       331 
340 
     | 
    
         | 
| 
       332 
341 
     | 
    
         
             
                    def ignore_cert?(address, port)
         
     | 
| 
       333 
342 
     | 
    
         
             
                      endpoint = [address, port].freeze
         
     | 
| 
       334 
     | 
    
         
            -
                       
     | 
| 
       335 
     | 
    
         
            -
                       
     | 
| 
       336 
     | 
    
         
            -
             
     | 
| 
       337 
     | 
    
         
            -
             
     | 
| 
       338 
     | 
    
         
            -
             
     | 
| 
       339 
     | 
    
         
            -
                           
     | 
| 
       340 
     | 
    
         
            -
             
     | 
| 
       341 
     | 
    
         
            -
             
     | 
| 
      
 343 
     | 
    
         
            +
                      ignore_cert = false
         
     | 
| 
      
 344 
     | 
    
         
            +
                      if @option_insecure || @option_ignore_cert_host_port.any?(endpoint)
         
     | 
| 
      
 345 
     | 
    
         
            +
                        ignore_cert = true
         
     | 
| 
      
 346 
     | 
    
         
            +
                        if @option_warn_insecure_cert
         
     | 
| 
      
 347 
     | 
    
         
            +
                          base_url = "https://#{address}:#{port}"
         
     | 
| 
      
 348 
     | 
    
         
            +
                          if !@ssl_warned_urls.include?(base_url)
         
     | 
| 
      
 349 
     | 
    
         
            +
                            formatter.display_message(
         
     | 
| 
      
 350 
     | 
    
         
            +
                              :error,
         
     | 
| 
      
 351 
     | 
    
         
            +
                              "#{Formatter::WARNING_FLASH} Ignoring certificate for: #{base_url}. Do not deactivate certificate verification in production.")
         
     | 
| 
      
 352 
     | 
    
         
            +
                            @ssl_warned_urls.push(base_url)
         
     | 
| 
      
 353 
     | 
    
         
            +
                          end
         
     | 
| 
      
 354 
     | 
    
         
            +
                        end
         
     | 
| 
       342 
355 
     | 
    
         
             
                      end
         
     | 
| 
       343 
     | 
    
         
            -
                       
     | 
| 
      
 356 
     | 
    
         
            +
                      Log.log.debug{"ignore cert? #{endpoint} -> #{ignore_cert}"}
         
     | 
| 
      
 357 
     | 
    
         
            +
                      return ignore_cert
         
     | 
| 
       344 
358 
     | 
    
         
             
                    end
         
     | 
| 
       345 
359 
     | 
    
         | 
| 
       346 
360 
     | 
    
         
             
                    # called every time a new REST HTTP session is opened to set user-provided options
         
     | 
| 
         @@ -443,25 +457,25 @@ module Aspera 
     | 
|
| 
       443 
457 
     | 
    
         
             
                      return nil
         
     | 
| 
       444 
458 
     | 
    
         
             
                    end
         
     | 
| 
       445 
459 
     | 
    
         | 
| 
       446 
     | 
    
         
            -
                    # get the default global preset, or  
     | 
| 
      
 460 
     | 
    
         
            +
                    # get the default global preset, or set default one
         
     | 
| 
       447 
461 
     | 
    
         
             
                    def global_default_preset
         
     | 
| 
       448 
     | 
    
         
            -
                       
     | 
| 
       449 
     | 
    
         
            -
                      if  
     | 
| 
       450 
     | 
    
         
            -
                         
     | 
| 
       451 
     | 
    
         
            -
                        set_preset_key( 
     | 
| 
      
 462 
     | 
    
         
            +
                      result = get_plugin_default_config_name(CONF_GLOBAL_SYM)
         
     | 
| 
      
 463 
     | 
    
         
            +
                      if result.nil?
         
     | 
| 
      
 464 
     | 
    
         
            +
                        result = CONF_PRESET_GLOBAL
         
     | 
| 
      
 465 
     | 
    
         
            +
                        set_preset_key(CONF_PRESET_DEFAULTS, CONF_GLOBAL_SYM, result)
         
     | 
| 
       452 
466 
     | 
    
         
             
                      end
         
     | 
| 
       453 
     | 
    
         
            -
                      return  
     | 
| 
      
 467 
     | 
    
         
            +
                      return result
         
     | 
| 
       454 
468 
     | 
    
         
             
                    end
         
     | 
| 
       455 
469 
     | 
    
         | 
| 
       456 
470 
     | 
    
         
             
                    def set_preset_key(preset, param_name, param_value)
         
     | 
| 
       457 
     | 
    
         
            -
                       
     | 
| 
      
 471 
     | 
    
         
            +
                      assert_values(param_name.class, [String, Symbol]){'parameter'}
         
     | 
| 
       458 
472 
     | 
    
         
             
                      param_name = param_name.to_s
         
     | 
| 
       459 
473 
     | 
    
         
             
                      selected_preset = @config_presets[preset]
         
     | 
| 
       460 
474 
     | 
    
         
             
                      if selected_preset.nil?
         
     | 
| 
       461 
475 
     | 
    
         
             
                        Log.log.debug{"No such preset name: #{preset}, initializing"}
         
     | 
| 
       462 
476 
     | 
    
         
             
                        selected_preset = @config_presets[preset] = {}
         
     | 
| 
       463 
477 
     | 
    
         
             
                      end
         
     | 
| 
       464 
     | 
    
         
            -
                       
     | 
| 
      
 478 
     | 
    
         
            +
                      assert_type(selected_preset, Hash){"#{preset}.#{param_name}"}
         
     | 
| 
       465 
479 
     | 
    
         
             
                      if selected_preset.key?(param_name)
         
     | 
| 
       466 
480 
     | 
    
         
             
                        if selected_preset[param_name].eql?(param_value)
         
     | 
| 
       467 
481 
     | 
    
         
             
                          Log.log.warn{"keeping same value for #{preset}: #{param_name}: #{param_value}"}
         
     | 
| 
         @@ -493,7 +507,7 @@ module Aspera 
     | 
|
| 
       493 
507 
     | 
    
         
             
                      include_path = include_path.clone # avoid messing up if there are multiple branches
         
     | 
| 
       494 
508 
     | 
    
         
             
                      current = @config_presets
         
     | 
| 
       495 
509 
     | 
    
         
             
                      config_name.split(PRESET_DIG_SEPARATOR).each do |name|
         
     | 
| 
       496 
     | 
    
         
            -
                         
     | 
| 
      
 510 
     | 
    
         
            +
                        assert_type(current, Hash, exception_class: Cli::Error){"sub key: #{include_path}"}
         
     | 
| 
       497 
511 
     | 
    
         
             
                        include_path.push(name)
         
     | 
| 
       498 
512 
     | 
    
         
             
                        current = current[name]
         
     | 
| 
       499 
513 
     | 
    
         
             
                        raise Cli::Error, "No such config preset: #{include_path}" if current.nil?
         
     | 
| 
         @@ -511,11 +525,10 @@ module Aspera 
     | 
|
| 
       511 
525 
     | 
    
         
             
                    end
         
     | 
| 
       512 
526 
     | 
    
         | 
| 
       513 
527 
     | 
    
         
             
                    def option_plugin_folder=(value)
         
     | 
| 
       514 
     | 
    
         
            -
                       
     | 
| 
       515 
     | 
    
         
            -
                       
     | 
| 
       516 
     | 
    
         
            -
                       
     | 
| 
       517 
     | 
    
         
            -
                       
     | 
| 
       518 
     | 
    
         
            -
                      end
         
     | 
| 
      
 528 
     | 
    
         
            +
                      assert_values(value.class, [String, Array]){'plugin folder'}
         
     | 
| 
      
 529 
     | 
    
         
            +
                      value = [value] if value.is_a?(String)
         
     | 
| 
      
 530 
     | 
    
         
            +
                      assert(value.all?(String)){'plugin folder'}
         
     | 
| 
      
 531 
     | 
    
         
            +
                      value.each{|f|add_plugin_lookup_folder(f)}
         
     | 
| 
       519 
532 
     | 
    
         
             
                    end
         
     | 
| 
       520 
533 
     | 
    
         | 
| 
       521 
534 
     | 
    
         
             
                    def option_plugin_folder
         
     | 
| 
         @@ -558,15 +571,15 @@ module Aspera 
     | 
|
| 
       558 
571 
     | 
    
         
             
                      end
         
     | 
| 
       559 
572 
     | 
    
         
             
                      files_to_copy = []
         
     | 
| 
       560 
573 
     | 
    
         
             
                      Log.log.debug{Log.dump('Available_presets', @config_presets)}
         
     | 
| 
       561 
     | 
    
         
            -
                       
     | 
| 
      
 574 
     | 
    
         
            +
                      assert_type(@config_presets, Hash){'config file YAML'}
         
     | 
| 
       562 
575 
     | 
    
         
             
                      # check there is at least the config section
         
     | 
| 
       563 
     | 
    
         
            -
                       
     | 
| 
      
 576 
     | 
    
         
            +
                      assert(@config_presets.key?(CONF_PRESET_CONFIG)){"Cannot find key: #{CONF_PRESET_CONFIG}"}
         
     | 
| 
       564 
577 
     | 
    
         
             
                      version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]
         
     | 
| 
       565 
578 
     | 
    
         
             
                      raise 'No version found in config section.' if version.nil?
         
     | 
| 
       566 
579 
     | 
    
         
             
                      Log.log.debug{"conf version: #{version}"}
         
     | 
| 
       567 
580 
     | 
    
         
             
                      # VVV if there are any conversion needed, those happen here.
         
     | 
| 
       568 
581 
     | 
    
         
             
                      # fix bug in 4.4 (creating key "true" in "default" preset)
         
     | 
| 
       569 
     | 
    
         
            -
                      @config_presets[ 
     | 
| 
      
 582 
     | 
    
         
            +
                      @config_presets[CONF_PRESET_DEFAULTS].delete(true) if @config_presets[CONF_PRESET_DEFAULTS].is_a?(Hash)
         
     | 
| 
       570 
583 
     | 
    
         
             
                      # ^^^ Place new compatibility code before this line
         
     | 
| 
       571 
584 
     | 
    
         
             
                      # set version to current
         
     | 
| 
       572 
585 
     | 
    
         
             
                      @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = @info[:version]
         
     | 
| 
         @@ -646,13 +659,14 @@ module Aspera 
     | 
|
| 
       646 
659 
     | 
    
         
             
                          next
         
     | 
| 
       647 
660 
     | 
    
         
             
                        end
         
     | 
| 
       648 
661 
     | 
    
         
             
                        next if detection_info.nil?
         
     | 
| 
       649 
     | 
    
         
            -
                         
     | 
| 
      
 662 
     | 
    
         
            +
                        assert_type(detection_info, Hash)
         
     | 
| 
      
 663 
     | 
    
         
            +
                        assert_type(detection_info[:url], String) if detection_info.key?(:url)
         
     | 
| 
       650 
664 
     | 
    
         
             
                        app_name = detect_plugin_class.respond_to?(:application_name) ? detect_plugin_class.application_name : detect_plugin_class.name.split('::').last
         
     | 
| 
       651 
665 
     | 
    
         
             
                        # if there is a redirect, then the detector can override the url.
         
     | 
| 
       652 
666 
     | 
    
         
             
                        found_apps.push({product: plugin_name_sym, name: app_name, url: app_url, version: 'unknown'}.merge(detection_info))
         
     | 
| 
       653 
667 
     | 
    
         
             
                      end # loop
         
     | 
| 
       654 
668 
     | 
    
         
             
                      raise "No known application found at #{app_url}" if found_apps.empty?
         
     | 
| 
       655 
     | 
    
         
            -
                       
     | 
| 
      
 669 
     | 
    
         
            +
                      assert(found_apps.all?{|a|a.keys.all?(Symbol)})
         
     | 
| 
       656 
670 
     | 
    
         
             
                      return found_apps
         
     | 
| 
       657 
671 
     | 
    
         
             
                    end
         
     | 
| 
       658 
672 
     | 
    
         | 
| 
         @@ -666,10 +680,10 @@ module Aspera 
     | 
|
| 
       666 
680 
     | 
    
         
             
                      case command
         
     | 
| 
       667 
681 
     | 
    
         
             
                      when :list
         
     | 
| 
       668 
682 
     | 
    
         
             
                        return {type: :object_list, data: connect_versions, fields: %w[id title version]}
         
     | 
| 
       669 
     | 
    
         
            -
                      when :info 
     | 
| 
      
 683 
     | 
    
         
            +
                      when :info
         
     | 
| 
       670 
684 
     | 
    
         
             
                        one_res.delete('links')
         
     | 
| 
       671 
685 
     | 
    
         
             
                        return {type: :single_object, data: one_res}
         
     | 
| 
       672 
     | 
    
         
            -
                      when :version 
     | 
| 
      
 686 
     | 
    
         
            +
                      when :version
         
     | 
| 
       673 
687 
     | 
    
         
             
                        all_links = one_res['links']
         
     | 
| 
       674 
688 
     | 
    
         
             
                        command = options.get_next_command(%i[list download open])
         
     | 
| 
       675 
689 
     | 
    
         
             
                        if %i[download open].include?(command)
         
     | 
| 
         @@ -678,7 +692,7 @@ module Aspera 
     | 
|
| 
       678 
692 
     | 
    
         
             
                          raise 'no such value' if one_link.nil?
         
     | 
| 
       679 
693 
     | 
    
         
             
                        end
         
     | 
| 
       680 
694 
     | 
    
         
             
                        case command
         
     | 
| 
       681 
     | 
    
         
            -
                        when :list 
     | 
| 
      
 695 
     | 
    
         
            +
                        when :list
         
     | 
| 
       682 
696 
     | 
    
         
             
                          return {type: :object_list, data: all_links}
         
     | 
| 
       683 
697 
     | 
    
         
             
                        when :download
         
     | 
| 
       684 
698 
     | 
    
         
             
                          folder_dest = transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE)
         
     | 
| 
         @@ -706,49 +720,17 @@ module Aspera 
     | 
|
| 
       706 
720 
     | 
    
         
             
                        formatter.display_status("ascp version: #{ascp_version}")
         
     | 
| 
       707 
721 
     | 
    
         
             
                        set_global_default(:ascp_path, ascp_path)
         
     | 
| 
       708 
722 
     | 
    
         
             
                        return Main.result_nothing
         
     | 
| 
       709 
     | 
    
         
            -
                      when :show 
     | 
| 
      
 723 
     | 
    
         
            +
                      when :show
         
     | 
| 
       710 
724 
     | 
    
         
             
                        return {type: :status, data: Fasp::Installation.instance.path(:ascp)}
         
     | 
| 
       711 
     | 
    
         
            -
                      when :info 
     | 
| 
       712 
     | 
    
         
            -
                         
     | 
| 
       713 
     | 
    
         
            -
                         
     | 
| 
       714 
     | 
    
         
            -
                         
     | 
| 
       715 
     | 
    
         
            -
                          last_line = ''
         
     | 
| 
       716 
     | 
    
         
            -
                          while (line = stderr.gets)
         
     | 
| 
       717 
     | 
    
         
            -
                            line.chomp!
         
     | 
| 
       718 
     | 
    
         
            -
                            last_line = line
         
     | 
| 
       719 
     | 
    
         
            -
                            case line
         
     | 
| 
       720 
     | 
    
         
            -
                            when /^DBG Path ([^ ]+) (dir|file) +: (.*)$/
         
     | 
| 
       721 
     | 
    
         
            -
                              data[Regexp.last_match(1)] = Regexp.last_match(3)
         
     | 
| 
       722 
     | 
    
         
            -
                            when /^DBG Added module group:"(?<module>[^"]+)" name:"(?<scheme>[^"]+)", version:"(?<version>[^"]+)" interface:"(?<interface>[^"]+)"$/
         
     | 
| 
       723 
     | 
    
         
            -
                              c = Regexp.last_match.named_captures.symbolize_keys
         
     | 
| 
       724 
     | 
    
         
            -
                              data[c[:interface]] ||= {}
         
     | 
| 
       725 
     | 
    
         
            -
                              data[c[:interface]][c[:module]] ||= []
         
     | 
| 
       726 
     | 
    
         
            -
                              data[c[:interface]][c[:module]].push("#{c[:scheme]} v#{c[:version]}")
         
     | 
| 
       727 
     | 
    
         
            -
                            when %r{^DBG License result \(/license/(\S+)\): (.+)$}
         
     | 
| 
       728 
     | 
    
         
            -
                              data[Regexp.last_match(1)] = Regexp.last_match(2)
         
     | 
| 
       729 
     | 
    
         
            -
                            when /^LOG (.+) version ([0-9.]+)$/
         
     | 
| 
       730 
     | 
    
         
            -
                              data['product_name'] = Regexp.last_match(1)
         
     | 
| 
       731 
     | 
    
         
            -
                              data['product_version'] = Regexp.last_match(2)
         
     | 
| 
       732 
     | 
    
         
            -
                            when /^LOG Initializing FASP version ([^,]+),/
         
     | 
| 
       733 
     | 
    
         
            -
                              data['ascp_version'] = Regexp.last_match(1)
         
     | 
| 
       734 
     | 
    
         
            -
                            end
         
     | 
| 
       735 
     | 
    
         
            -
                          end
         
     | 
| 
       736 
     | 
    
         
            -
                          if !thread.value.exitstatus.eql?(1) && !data.key?('root')
         
     | 
| 
       737 
     | 
    
         
            -
                            raise last_line
         
     | 
| 
       738 
     | 
    
         
            -
                          end
         
     | 
| 
       739 
     | 
    
         
            -
                        end
         
     | 
| 
       740 
     | 
    
         
            -
                        # ascp's openssl directory
         
     | 
| 
       741 
     | 
    
         
            -
                        ascp_file = data['ascp']
         
     | 
| 
       742 
     | 
    
         
            -
                        File.binread(ascp_file).scan(/[\x20-\x7E]{4,}/) do |match|
         
     | 
| 
       743 
     | 
    
         
            -
                          if (m = match.match(/OPENSSLDIR.*"(.*)"/))
         
     | 
| 
       744 
     | 
    
         
            -
                            data['openssldir'] = m[1]
         
     | 
| 
       745 
     | 
    
         
            -
                          end
         
     | 
| 
       746 
     | 
    
         
            -
                        end if File.file?(ascp_file)
         
     | 
| 
       747 
     | 
    
         
            -
                        data['uuid'] = Fasp::Installation.instance.ssh_cert_uuid
         
     | 
| 
       748 
     | 
    
         
            -
                        # log is "-" no need to display
         
     | 
| 
       749 
     | 
    
         
            -
                        data.delete('log')
         
     | 
| 
       750 
     | 
    
         
            -
                        # show command line transfer spec
         
     | 
| 
      
 725 
     | 
    
         
            +
                      when :info
         
     | 
| 
      
 726 
     | 
    
         
            +
                        # collect info from ascp executable
         
     | 
| 
      
 727 
     | 
    
         
            +
                        data = Fasp::Installation.instance.ascp_info
         
     | 
| 
      
 728 
     | 
    
         
            +
                        # add command line transfer spec
         
     | 
| 
       751 
729 
     | 
    
         
             
                        data['ts'] = transfer.updated_ts
         
     | 
| 
      
 730 
     | 
    
         
            +
                        # add keys
         
     | 
| 
      
 731 
     | 
    
         
            +
                        DataRepository::ELEMENTS.each_with_object(data){|i, h|h[i.to_s] = DataRepository.instance.item(i)}
         
     | 
| 
      
 732 
     | 
    
         
            +
                        # declare those as secrets
         
     | 
| 
      
 733 
     | 
    
         
            +
                        SecretHider::ADDITIONAL_KEYS_TO_HIDE.push(*DataRepository::ELEMENTS.map(&:to_s))
         
     | 
| 
       752 
734 
     | 
    
         
             
                        return {type: :single_object, data: data}
         
     | 
| 
       753 
735 
     | 
    
         
             
                      when :products
         
     | 
| 
       754 
736 
     | 
    
         
             
                        command = options.get_next_command(%i[list use])
         
     | 
| 
         @@ -887,6 +869,7 @@ module Aspera 
     | 
|
| 
       887 
869 
     | 
    
         
             
                      open
         
     | 
| 
       888 
870 
     | 
    
         
             
                      documentation
         
     | 
| 
       889 
871 
     | 
    
         
             
                      genkey
         
     | 
| 
      
 872 
     | 
    
         
            +
                      pubkey
         
     | 
| 
       890 
873 
     | 
    
         
             
                      remote_certificate
         
     | 
| 
       891 
874 
     | 
    
         
             
                      gem
         
     | 
| 
       892 
875 
     | 
    
         
             
                      plugins
         
     | 
| 
         @@ -925,6 +908,9 @@ module Aspera 
     | 
|
| 
       925 
908 
     | 
    
         
             
                        private_key_length = options.get_next_argument('size in bits', mandatory: false, type: Integer, default: DEFAULT_PRIV_KEY_LENGTH)
         
     | 
| 
       926 
909 
     | 
    
         
             
                        self.class.generate_rsa_private_key(path: private_key_path, length: private_key_length)
         
     | 
| 
       927 
910 
     | 
    
         
             
                        return Main.result_status("Generated #{private_key_length} bit RSA key: #{private_key_path}")
         
     | 
| 
      
 911 
     | 
    
         
            +
                      when :pubkey # get pub key
         
     | 
| 
      
 912 
     | 
    
         
            +
                        private_key_pem = options.get_next_argument('private key PEM value')
         
     | 
| 
      
 913 
     | 
    
         
            +
                        return Main.result_status(OpenSSL::PKey::RSA.new(private_key_pem).public_key.to_s)
         
     | 
| 
       928 
914 
     | 
    
         
             
                      when :remote_certificate
         
     | 
| 
       929 
915 
     | 
    
         
             
                        remote_url = options.get_next_argument('remote URL')
         
     | 
| 
       930 
916 
     | 
    
         
             
                        @option_insecure = true
         
     | 
| 
         @@ -984,8 +970,7 @@ module Aspera 
     | 
|
| 
       984 
970 
     | 
    
         
             
                        return wizard_find(apps)
         
     | 
| 
       985 
971 
     | 
    
         
             
                      when :coffee
         
     | 
| 
       986 
972 
     | 
    
         
             
                        if OpenApplication.instance.url_method.eql?(:text)
         
     | 
| 
       987 
     | 
    
         
            -
                           
     | 
| 
       988 
     | 
    
         
            -
                          return Main.result_status(Preview::Terminal.build(Rest.new(base_url: COFFEE_IMAGE).read('')[:http].body))
         
     | 
| 
      
 973 
     | 
    
         
            +
                          return Main.result_picture_in_terminal(options, Rest.new(base_url: COFFEE_IMAGE).read('')[:http].body)
         
     | 
| 
       989 
974 
     | 
    
         
             
                        end
         
     | 
| 
       990 
975 
     | 
    
         
             
                        OpenApplication.instance.uri(COFFEE_IMAGE)
         
     | 
| 
       991 
976 
     | 
    
         
             
                        return Main.result_nothing
         
     | 
| 
         @@ -1024,13 +1009,13 @@ module Aspera 
     | 
|
| 
       1024 
1009 
     | 
    
         
             
                            'ssAP'.downcase.reverse + 'drow'.reverse => DEMO + ASPERA # cspell:disable-line
         
     | 
| 
       1025 
1010 
     | 
    
         
             
                          }
         
     | 
| 
       1026 
1011 
     | 
    
         
             
                        end
         
     | 
| 
       1027 
     | 
    
         
            -
                        @config_presets[ 
     | 
| 
       1028 
     | 
    
         
            -
                        if @config_presets[ 
     | 
| 
       1029 
     | 
    
         
            -
                          Log.log.warn{"Server default preset already set to: #{@config_presets[ 
     | 
| 
      
 1012 
     | 
    
         
            +
                        @config_presets[CONF_PRESET_DEFAULTS] ||= {}
         
     | 
| 
      
 1013 
     | 
    
         
            +
                        if @config_presets[CONF_PRESET_DEFAULTS].key?(SERVER_COMMAND)
         
     | 
| 
      
 1014 
     | 
    
         
            +
                          Log.log.warn{"Server default preset already set to: #{@config_presets[CONF_PRESET_DEFAULTS][SERVER_COMMAND]}"}
         
     | 
| 
       1030 
1015 
     | 
    
         
             
                          Log.log.warn{"Use #{DEMO_SERVER_PRESET} for demo: -P#{DEMO_SERVER_PRESET}"} unless
         
     | 
| 
       1031 
     | 
    
         
            -
                            DEMO_SERVER_PRESET.eql?(@config_presets[ 
     | 
| 
      
 1016 
     | 
    
         
            +
                            DEMO_SERVER_PRESET.eql?(@config_presets[CONF_PRESET_DEFAULTS][SERVER_COMMAND])
         
     | 
| 
       1032 
1017 
     | 
    
         
             
                        else
         
     | 
| 
       1033 
     | 
    
         
            -
                          @config_presets[ 
     | 
| 
      
 1018 
     | 
    
         
            +
                          @config_presets[CONF_PRESET_DEFAULTS][SERVER_COMMAND] = DEMO_SERVER_PRESET
         
     | 
| 
       1034 
1019 
     | 
    
         
             
                          Log.log.info{"Setting server default preset to : #{DEMO_SERVER_PRESET}"}
         
     | 
| 
       1035 
1020 
     | 
    
         
             
                        end
         
     | 
| 
       1036 
1021 
     | 
    
         
             
                        return Main.result_status('Done')
         
     | 
| 
         @@ -1041,9 +1026,9 @@ module Aspera 
     | 
|
| 
       1041 
1026 
     | 
    
         
             
                        exception_class_name = options.get_next_argument('exception class name', mandatory: true)
         
     | 
| 
       1042 
1027 
     | 
    
         
             
                        exception_text = options.get_next_argument('exception text', mandatory: true)
         
     | 
| 
       1043 
1028 
     | 
    
         
             
                        exception_class = Object.const_get(exception_class_name)
         
     | 
| 
       1044 
     | 
    
         
            -
                         
     | 
| 
      
 1029 
     | 
    
         
            +
                        assert(exception_class <= Exception){"#{exception_class} is not an exception: #{exception_class.class}"}
         
     | 
| 
       1045 
1030 
     | 
    
         
             
                        raise exception_class, exception_text
         
     | 
| 
       1046 
     | 
    
         
            -
                      else  
     | 
| 
      
 1031 
     | 
    
         
            +
                      else error_unreachable_line
         
     | 
| 
       1047 
1032 
     | 
    
         
             
                      end
         
     | 
| 
       1048 
1033 
     | 
    
         
             
                    end
         
     | 
| 
       1049 
1034 
     | 
    
         | 
| 
         @@ -1064,7 +1049,7 @@ module Aspera 
     | 
|
| 
       1064 
1049 
     | 
    
         
             
                      options.add_option_preset({url: wiz_url})
         
     | 
| 
       1065 
1050 
     | 
    
         
             
                      # instantiate plugin: command line options will be known and wizard can be called
         
     | 
| 
       1066 
1051 
     | 
    
         
             
                      wiz_plugin_class = self.class.plugin_class(identification[:product])
         
     | 
| 
       1067 
     | 
    
         
            -
                       
     | 
| 
      
 1052 
     | 
    
         
            +
                      assert(wiz_plugin_class.respond_to?(:wizard), exception_class: Cli::BadArgument){"Detected: #{identification[:product]}, but this application has no wizard"}
         
     | 
| 
       1068 
1053 
     | 
    
         
             
                      # instantiate plugin: command line options will be known, e.g. private_key
         
     | 
| 
       1069 
1054 
     | 
    
         
             
                      plugin_instance = wiz_plugin_class.new(@agents)
         
     | 
| 
       1070 
1055 
     | 
    
         
             
                      wiz_params = {
         
     | 
| 
         @@ -1089,7 +1074,7 @@ module Aspera 
     | 
|
| 
       1089 
1074 
     | 
    
         
             
                          formatter.display_status('Using existing key:')
         
     | 
| 
       1090 
1075 
     | 
    
         
             
                        else
         
     | 
| 
       1091 
1076 
     | 
    
         
             
                          formatter.display_status("Generating #{DEFAULT_PRIV_KEY_LENGTH} bit RSA key...")
         
     | 
| 
       1092 
     | 
    
         
            -
                           
     | 
| 
      
 1077 
     | 
    
         
            +
                          self.class.generate_rsa_private_key(path: private_key_path)
         
     | 
| 
       1093 
1078 
     | 
    
         
             
                          formatter.display_status('Created key:')
         
     | 
| 
       1094 
1079 
     | 
    
         
             
                        end
         
     | 
| 
       1095 
1080 
     | 
    
         
             
                        formatter.display_status(private_key_path)
         
     | 
| 
         @@ -1102,7 +1087,7 @@ module Aspera 
     | 
|
| 
       1102 
1087 
     | 
    
         
             
                      # finally, call the wizard
         
     | 
| 
       1103 
1088 
     | 
    
         
             
                      wizard_result = wiz_plugin_class.wizard(**wiz_params)
         
     | 
| 
       1104 
1089 
     | 
    
         
             
                      Log.log.debug{"wizard result: #{wizard_result}"}
         
     | 
| 
       1105 
     | 
    
         
            -
                       
     | 
| 
      
 1090 
     | 
    
         
            +
                      assert(WIZARD_RESULT_KEYS.eql?(wizard_result.keys.sort)){"missing or extra keys in wizard result: #{wizard_result.keys}"}
         
     | 
| 
       1106 
1091 
     | 
    
         
             
                      # get preset name from user or default
         
     | 
| 
       1107 
1092 
     | 
    
         
             
                      wiz_preset_name = options.get_option(:id)
         
     | 
| 
       1108 
1093 
     | 
    
         
             
                      if wiz_preset_name.nil?
         
     | 
| 
         @@ -1118,17 +1103,17 @@ module Aspera 
     | 
|
| 
       1118 
1103 
     | 
    
         
             
                      # Write configuration file
         
     | 
| 
       1119 
1104 
     | 
    
         
             
                      formatter.display_status("Preparing preset: #{wiz_preset_name}")
         
     | 
| 
       1120 
1105 
     | 
    
         
             
                      # init defaults if necessary
         
     | 
| 
       1121 
     | 
    
         
            -
                      @config_presets[ 
     | 
| 
      
 1106 
     | 
    
         
            +
                      @config_presets[CONF_PRESET_DEFAULTS] ||= {}
         
     | 
| 
       1122 
1107 
     | 
    
         
             
                      option_override = options.get_option(:override, mandatory: true)
         
     | 
| 
       1123 
1108 
     | 
    
         
             
                      raise Cli::Error, "A default configuration already exists for plugin '#{identification[:product]}' (use --override=yes or --default=no)" \
         
     | 
| 
       1124 
     | 
    
         
            -
                        if !option_override && options.get_option(:default, mandatory: true) && @config_presets[ 
     | 
| 
      
 1109 
     | 
    
         
            +
                        if !option_override && options.get_option(:default, mandatory: true) && @config_presets[CONF_PRESET_DEFAULTS].key?(identification[:product])
         
     | 
| 
       1125 
1110 
     | 
    
         
             
                      raise Cli::Error, "Preset already exists: #{wiz_preset_name}  (use --override=yes or --id=<name>)" \
         
     | 
| 
       1126 
1111 
     | 
    
         
             
                        if !option_override && @config_presets.key?(wiz_preset_name)
         
     | 
| 
       1127 
1112 
     | 
    
         
             
                      @config_presets[wiz_preset_name] = wizard_result[:preset_value].stringify_keys
         
     | 
| 
       1128 
1113 
     | 
    
         
             
                      test_args = wizard_result[:test_args]
         
     | 
| 
       1129 
1114 
     | 
    
         
             
                      if options.get_option(:default, mandatory: true)
         
     | 
| 
       1130 
1115 
     | 
    
         
             
                        formatter.display_status("Setting config preset as default for #{identification[:product]}")
         
     | 
| 
       1131 
     | 
    
         
            -
                        @config_presets[ 
     | 
| 
      
 1116 
     | 
    
         
            +
                        @config_presets[CONF_PRESET_DEFAULTS][identification[:product].to_s] = wiz_preset_name
         
     | 
| 
       1132 
1117 
     | 
    
         
             
                      else
         
     | 
| 
       1133 
1118 
     | 
    
         
             
                        test_args = "-P#{wiz_preset_name} #{test_args}"
         
     | 
| 
       1134 
1119 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -1155,7 +1140,7 @@ module Aspera 
     | 
|
| 
       1155 
1140 
     | 
    
         
             
                      smtp[:domain] ||= smtp[:from_email].gsub(/^.*@/, '') if smtp.key?(:from_email)
         
     | 
| 
       1156 
1141 
     | 
    
         
             
                      # check minimum required
         
     | 
| 
       1157 
1142 
     | 
    
         
             
                      %i[server port domain].each do |n|
         
     | 
| 
       1158 
     | 
    
         
            -
                         
     | 
| 
      
 1143 
     | 
    
         
            +
                        assert(smtp.key?(n)){"Missing mandatory smtp parameter: #{n}"}
         
     | 
| 
       1159 
1144 
     | 
    
         
             
                      end
         
     | 
| 
       1160 
1145 
     | 
    
         
             
                      Log.log.debug{"smtp=#{smtp}"}
         
     | 
| 
       1161 
1146 
     | 
    
         
             
                      return smtp
         
     | 
| 
         @@ -1169,7 +1154,7 @@ module Aspera 
     | 
|
| 
       1169 
1154 
     | 
    
         
             
                      values[:from_name] ||= mail_conf[:from_name]
         
     | 
| 
       1170 
1155 
     | 
    
         
             
                      values[:from_email] ||= mail_conf[:from_email]
         
     | 
| 
       1171 
1156 
     | 
    
         
             
                      %i[from_name from_email].each do |n|
         
     | 
| 
       1172 
     | 
    
         
            -
                         
     | 
| 
      
 1157 
     | 
    
         
            +
                        assert(values.key?(n)){"Missing email parameter: #{n}"}
         
     | 
| 
       1173 
1158 
     | 
    
         
             
                      end
         
     | 
| 
       1174 
1159 
     | 
    
         
             
                      start_options = [mail_conf[:domain]]
         
     | 
| 
       1175 
1160 
     | 
    
         
             
                      start_options.push(mail_conf[:username], mail_conf[:password], :login) if mail_conf.key?(:username) && mail_conf.key?(:password)
         
     | 
| 
         @@ -1177,7 +1162,7 @@ module Aspera 
     | 
|
| 
       1177 
1162 
     | 
    
         
             
                      template_binding = Environment.empty_binding
         
     | 
| 
       1178 
1163 
     | 
    
         
             
                      # add variables to binding
         
     | 
| 
       1179 
1164 
     | 
    
         
             
                      values.each do |k, v|
         
     | 
| 
       1180 
     | 
    
         
            -
                         
     | 
| 
      
 1165 
     | 
    
         
            +
                        assert_type(k, Symbol)
         
     | 
| 
       1181 
1166 
     | 
    
         
             
                        template_binding.local_variable_set(k, v)
         
     | 
| 
       1182 
1167 
     | 
    
         
             
                      end
         
     | 
| 
       1183 
1168 
     | 
    
         
             
                      # execute template
         
     | 
| 
         @@ -1211,14 +1196,14 @@ module Aspera 
     | 
|
| 
       1211 
1196 
     | 
    
         
             
                    # returns [String] name if config_presets has default
         
     | 
| 
       1212 
1197 
     | 
    
         
             
                    # returns nil if there is no config or bypass default params
         
     | 
| 
       1213 
1198 
     | 
    
         
             
                    def get_plugin_default_config_name(plugin_name_sym)
         
     | 
| 
       1214 
     | 
    
         
            -
                       
     | 
| 
      
 1199 
     | 
    
         
            +
                      assert(!@config_presets.nil?){'config_presets shall be defined'}
         
     | 
| 
       1215 
1200 
     | 
    
         
             
                      if !@use_plugin_defaults
         
     | 
| 
       1216 
1201 
     | 
    
         
             
                        Log.log.debug('skip default config')
         
     | 
| 
       1217 
1202 
     | 
    
         
             
                        return nil
         
     | 
| 
       1218 
1203 
     | 
    
         
             
                      end
         
     | 
| 
       1219 
     | 
    
         
            -
                      if @config_presets.key?( 
     | 
| 
       1220 
     | 
    
         
            -
                          @config_presets[ 
     | 
| 
       1221 
     | 
    
         
            -
                        default_config_name = @config_presets[ 
     | 
| 
      
 1204 
     | 
    
         
            +
                      if @config_presets.key?(CONF_PRESET_DEFAULTS) &&
         
     | 
| 
      
 1205 
     | 
    
         
            +
                          @config_presets[CONF_PRESET_DEFAULTS].key?(plugin_name_sym.to_s)
         
     | 
| 
      
 1206 
     | 
    
         
            +
                        default_config_name = @config_presets[CONF_PRESET_DEFAULTS][plugin_name_sym.to_s]
         
     | 
| 
       1222 
1207 
     | 
    
         
             
                        if !@config_presets.key?(default_config_name)
         
     | 
| 
       1223 
1208 
     | 
    
         
             
                          Log.log.error do
         
     | 
| 
       1224 
1209 
     | 
    
         
             
                            "Default config name [#{default_config_name}] specified for plugin [#{plugin_name_sym}], but it does not exist in config file.\n" \
         
     | 
| 
         @@ -1235,16 +1220,17 @@ module Aspera 
     | 
|
| 
       1235 
1220 
     | 
    
         
             
                    # TODO: delete: ALLOWED_KEYS = %i[password username description].freeze
         
     | 
| 
       1236 
1221 
     | 
    
         
             
                    # @return [Hash] result of execution of vault command
         
     | 
| 
       1237 
1222 
     | 
    
         
             
                    def execute_vault
         
     | 
| 
       1238 
     | 
    
         
            -
                      command = options.get_next_command(%i[list show create delete password])
         
     | 
| 
      
 1223 
     | 
    
         
            +
                      command = options.get_next_command(%i[info list show create delete password])
         
     | 
| 
       1239 
1224 
     | 
    
         
             
                      case command
         
     | 
| 
      
 1225 
     | 
    
         
            +
                      when :info
         
     | 
| 
      
 1226 
     | 
    
         
            +
                        return {type: :single_object, data: vault_info}
         
     | 
| 
       1240 
1227 
     | 
    
         
             
                      when :list
         
     | 
| 
       1241 
1228 
     | 
    
         
             
                        return {type: :object_list, data: vault.list}
         
     | 
| 
       1242 
1229 
     | 
    
         
             
                      when :show
         
     | 
| 
       1243 
1230 
     | 
    
         
             
                        return {type: :single_object, data: vault.get(label: options.get_next_argument('label'))}
         
     | 
| 
       1244 
1231 
     | 
    
         
             
                      when :create
         
     | 
| 
       1245 
     | 
    
         
            -
                        label = options.get_next_argument('label')
         
     | 
| 
       1246 
     | 
    
         
            -
                        info = options.get_next_argument('info Hash 
     | 
| 
       1247 
     | 
    
         
            -
                        raise 'info must be Hash' unless info.is_a?(Hash)
         
     | 
| 
      
 1232 
     | 
    
         
            +
                        label = options.get_next_argument('label', type: String)
         
     | 
| 
      
 1233 
     | 
    
         
            +
                        info = options.get_next_argument('info', type: Hash)
         
     | 
| 
       1248 
1234 
     | 
    
         
             
                        info = info.symbolize_keys
         
     | 
| 
       1249 
1235 
     | 
    
         
             
                        info[:label] = label
         
     | 
| 
       1250 
1236 
     | 
    
         
             
                        vault.set(info)
         
     | 
| 
         @@ -1253,7 +1239,7 @@ module Aspera 
     | 
|
| 
       1253 
1239 
     | 
    
         
             
                        vault.delete(label: options.get_next_argument('label'))
         
     | 
| 
       1254 
1240 
     | 
    
         
             
                        return Main.result_status('Password deleted')
         
     | 
| 
       1255 
1241 
     | 
    
         
             
                      when :password
         
     | 
| 
       1256 
     | 
    
         
            -
                         
     | 
| 
      
 1242 
     | 
    
         
            +
                        assert(vault.respond_to?(:password=)){'Vault does not support password change'}
         
     | 
| 
       1257 
1243 
     | 
    
         
             
                        new_password = options.get_next_argument('new_password')
         
     | 
| 
       1258 
1244 
     | 
    
         
             
                        vault.password = new_password
         
     | 
| 
       1259 
1245 
     | 
    
         
             
                        vault.save
         
     | 
| 
         @@ -1272,27 +1258,36 @@ module Aspera 
     | 
|
| 
       1272 
1258 
     | 
    
         
             
                      return value
         
     | 
| 
       1273 
1259 
     | 
    
         
             
                    end
         
     | 
| 
       1274 
1260 
     | 
    
         | 
| 
      
 1261 
     | 
    
         
            +
                    def vault_info
         
     | 
| 
      
 1262 
     | 
    
         
            +
                      info = options.get_option(:vault) || {}
         
     | 
| 
      
 1263 
     | 
    
         
            +
                      info = info.symbolize_keys
         
     | 
| 
      
 1264 
     | 
    
         
            +
                      info[:type] ||= 'file'
         
     | 
| 
      
 1265 
     | 
    
         
            +
                      info[:name] ||= (info[:type].eql?('file') ? DEFAULT_VAULT_FILENAME : PROGRAM_NAME)
         
     | 
| 
      
 1266 
     | 
    
         
            +
                      assert(info.keys.sort == %i[name type]) {"vault info shall have exactly keys 'type' and 'name'"}
         
     | 
| 
      
 1267 
     | 
    
         
            +
                      assert(info.values.all?(String)){'vault info shall have only string values'}
         
     | 
| 
      
 1268 
     | 
    
         
            +
                      info[:password] = options.get_option(:vault_password, mandatory: true)
         
     | 
| 
      
 1269 
     | 
    
         
            +
                      return info
         
     | 
| 
      
 1270 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1271 
     | 
    
         
            +
             
     | 
| 
       1275 
1272 
     | 
    
         
             
                    # @return [Object] vault, from options or cache
         
     | 
| 
       1276 
1273 
     | 
    
         
             
                    def vault
         
     | 
| 
       1277 
1274 
     | 
    
         
             
                      if @vault.nil?
         
     | 
| 
       1278 
     | 
    
         
            -
                         
     | 
| 
       1279 
     | 
    
         
            -
                         
     | 
| 
       1280 
     | 
    
         
            -
                        vault_type = vault_info['type'] || 'file'
         
     | 
| 
       1281 
     | 
    
         
            -
                        vault_name = vault_info['name'] || (vault_type.eql?('file') ? 'vault.bin' : PROGRAM_NAME)
         
     | 
| 
       1282 
     | 
    
         
            -
                        case vault_type
         
     | 
| 
      
 1275 
     | 
    
         
            +
                        info = vault_info
         
     | 
| 
      
 1276 
     | 
    
         
            +
                        case info[:type]
         
     | 
| 
       1283 
1277 
     | 
    
         
             
                        when 'file'
         
     | 
| 
       1284 
1278 
     | 
    
         
             
                          # absolute_path? introduced in ruby 2.7
         
     | 
| 
       1285 
     | 
    
         
            -
                           
     | 
| 
       1286 
     | 
    
         
            -
             
     | 
| 
      
 1279 
     | 
    
         
            +
                          @vault = Keychain::EncryptedHash.new(
         
     | 
| 
      
 1280 
     | 
    
         
            +
                            info[:name].eql?(File.absolute_path(info[:name])) ? info[:name] : File.join(@main_folder, info[:name]),
         
     | 
| 
      
 1281 
     | 
    
         
            +
                            info[:password])
         
     | 
| 
       1287 
1282 
     | 
    
         
             
                        when 'system'
         
     | 
| 
       1288 
1283 
     | 
    
         
             
                          case Environment.os
         
     | 
| 
       1289 
1284 
     | 
    
         
             
                          when Environment::OS_X
         
     | 
| 
       1290 
     | 
    
         
            -
                            @vault = Keychain::MacosSystem.new( 
     | 
| 
      
 1285 
     | 
    
         
            +
                            @vault = Keychain::MacosSystem.new(info[:name], info[:password])
         
     | 
| 
       1291 
1286 
     | 
    
         
             
                          else
         
     | 
| 
       1292 
1287 
     | 
    
         
             
                            raise 'not implemented for this OS'
         
     | 
| 
       1293 
1288 
     | 
    
         
             
                          end
         
     | 
| 
       1294 
1289 
     | 
    
         
             
                        else
         
     | 
| 
       1295 
     | 
    
         
            -
                          raise Cli::BadArgument, "Unknown vault type: #{ 
     | 
| 
      
 1290 
     | 
    
         
            +
                          raise Cli::BadArgument, "Unknown vault type: #{info[:type]}"
         
     | 
| 
       1296 
1291 
     | 
    
         
             
                        end
         
     | 
| 
       1297 
1292 
     | 
    
         
             
                      end
         
     | 
| 
       1298 
1293 
     | 
    
         
             
                      raise 'No vault defined' if @vault.nil?
         
     | 
| 
         @@ -3,6 +3,7 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            require 'aspera/cli/plugin'
         
     | 
| 
       4 
4 
     | 
    
         
             
            require 'aspera/cli/plugins/node'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'aspera/cos_node'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'aspera/assert'
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
       7 
8 
     | 
    
         
             
            module Aspera
         
     | 
| 
       8 
9 
     | 
    
         
             
              module Cli
         
     | 
| 
         @@ -30,8 +31,7 @@ module Aspera 
     | 
|
| 
       30 
31 
     | 
    
         
             
                        # get service credentials, Hash, e.g. @json:@file:...
         
     | 
| 
       31 
32 
     | 
    
         
             
                        service_credentials = options.get_option(:service_credentials)
         
     | 
| 
       32 
33 
     | 
    
         
             
                        storage_endpoint = options.get_option(:endpoint)
         
     | 
| 
       33 
     | 
    
         
            -
                         
     | 
| 
       34 
     | 
    
         
            -
                        raise Cli::BadArgument, 'endpoint and service_credentials are mutually exclusive' unless service_credentials.nil? || storage_endpoint.nil?
         
     | 
| 
      
 34 
     | 
    
         
            +
                        assert(service_credentials.nil? ^ storage_endpoint.nil?, exception_class: Cli::BadArgument){'endpoint and service_credentials are mutually exclusive'}
         
     | 
| 
       35 
35 
     | 
    
         
             
                        if service_credentials.nil?
         
     | 
| 
       36 
36 
     | 
    
         
             
                          service_api_key = options.get_option(:apikey, mandatory: true)
         
     | 
| 
       37 
37 
     | 
    
         
             
                          instance_id = options.get_option(:crn, mandatory: true)
         
     |