aspera-cli 4.24.0 → 4.24.2
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/CHANGELOG.md +19 -1
 - data/README.md +1264 -941
 - data/bin/ascli +20 -1
 - data/bin/asession +23 -27
 - data/lib/aspera/agent/base.rb +10 -21
 - data/lib/aspera/agent/connect.rb +2 -3
 - data/lib/aspera/agent/desktop.rb +2 -2
 - data/lib/aspera/agent/direct.rb +49 -32
 - data/lib/aspera/agent/factory.rb +31 -0
 - data/lib/aspera/api/aoc.rb +79 -49
 - data/lib/aspera/api/faspex.rb +212 -0
 - data/lib/aspera/api/node.rb +99 -84
 - data/lib/aspera/ascp/installation.rb +22 -21
 - data/lib/aspera/ascp/management.rb +119 -23
 - data/lib/aspera/assert.rb +14 -8
 - data/lib/aspera/cli/extended_value.rb +15 -15
 - data/lib/aspera/cli/formatter.rb +7 -5
 - data/lib/aspera/cli/hints.rb +8 -0
 - data/lib/aspera/cli/info.rb +4 -4
 - data/lib/aspera/cli/main.rb +56 -71
 - data/lib/aspera/cli/manager.rb +7 -4
 - data/lib/aspera/cli/plugins/alee.rb +2 -1
 - data/lib/aspera/cli/plugins/aoc.rb +110 -186
 - data/lib/aspera/cli/plugins/ats.rb +4 -4
 - data/lib/aspera/cli/plugins/base.rb +335 -0
 - data/lib/aspera/cli/plugins/basic_auth.rb +45 -0
 - data/lib/aspera/cli/plugins/config.rb +263 -221
 - data/lib/aspera/cli/plugins/console.rb +15 -15
 - data/lib/aspera/cli/plugins/cos.rb +2 -2
 - data/lib/aspera/cli/plugins/factory.rb +78 -0
 - data/lib/aspera/cli/plugins/faspex.rb +17 -20
 - data/lib/aspera/cli/plugins/faspex5.rb +79 -193
 - data/lib/aspera/cli/plugins/faspio.rb +14 -13
 - data/lib/aspera/cli/plugins/httpgw.rb +13 -12
 - data/lib/aspera/cli/plugins/node.rb +34 -32
 - data/lib/aspera/cli/plugins/oauth.rb +48 -0
 - data/lib/aspera/cli/plugins/orchestrator.rb +15 -13
 - data/lib/aspera/cli/plugins/preview.rb +4 -4
 - data/lib/aspera/cli/plugins/server.rb +15 -13
 - data/lib/aspera/cli/plugins/shares.rb +18 -15
 - data/lib/aspera/cli/sync_actions.rb +1 -1
 - data/lib/aspera/cli/transfer_agent.rb +24 -20
 - data/lib/aspera/cli/transfer_progress.rb +6 -6
 - data/lib/aspera/cli/version.rb +3 -3
 - data/lib/aspera/cli/wizard.rb +74 -65
 - data/lib/aspera/colors.rb +6 -0
 - data/lib/aspera/command_line_builder.rb +45 -50
 - data/lib/aspera/command_line_converter.rb +2 -1
 - data/lib/aspera/coverage.rb +1 -1
 - data/lib/aspera/data_repository.rb +1 -1
 - data/lib/aspera/environment.rb +13 -9
 - data/lib/aspera/faspex_gw.rb +6 -4
 - data/lib/aspera/faspex_postproc.rb +1 -1
 - data/lib/aspera/keychain/macos_security.rb +1 -1
 - data/lib/aspera/log.rb +88 -37
 - data/lib/aspera/nagios.rb +1 -1
 - data/lib/aspera/oauth/base.rb +17 -10
 - data/lib/aspera/oauth/factory.rb +8 -8
 - data/lib/aspera/oauth/web.rb +2 -2
 - data/lib/aspera/products/connect.rb +4 -3
 - data/lib/aspera/products/desktop.rb +1 -4
 - data/lib/aspera/products/other.rb +9 -1
 - data/lib/aspera/products/transferd.rb +0 -1
 - data/lib/aspera/rest.rb +126 -83
 - data/lib/aspera/ssh.rb +3 -3
 - data/lib/aspera/sync/args.schema.yaml +46 -3
 - data/lib/aspera/sync/conf.schema.yaml +130 -94
 - data/lib/aspera/sync/operations.rb +71 -74
 - data/lib/aspera/temp_file_manager.rb +17 -5
 - data/lib/aspera/transfer/error.rb +16 -7
 - data/lib/aspera/transfer/parameters.rb +34 -20
 - data/lib/aspera/transfer/resumer.rb +74 -0
 - data/lib/aspera/transfer/spec.rb +4 -3
 - data/lib/aspera/transfer/spec.schema.yaml +132 -51
 - data/lib/aspera/transfer/spec_doc.rb +41 -35
 - data/lib/aspera/uri_reader.rb +1 -1
 - data/lib/aspera/web_auth.rb +6 -6
 - data.tar.gz.sig +0 -0
 - metadata +9 -7
 - metadata.gz.sig +2 -2
 - data/lib/aspera/cli/basic_auth_plugin.rb +0 -43
 - data/lib/aspera/cli/plugin.rb +0 -333
 - data/lib/aspera/cli/plugin_factory.rb +0 -81
 - data/lib/aspera/resumer.rb +0 -77
 - data/lib/aspera/transfer/error_info.rb +0 -91
 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            require 'aspera/agent/ 
     | 
| 
      
 3 
     | 
    
         
            +
            require 'aspera/agent/factory'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            module Aspera
         
     | 
| 
       6 
6 
     | 
    
         
             
              module Transfer
         
     | 
| 
         @@ -13,33 +13,38 @@ module Aspera 
     | 
|
| 
       13 
13 
     | 
    
         
             
                    end
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
                    # @param formatter      [Cli::Formatter] Formatter to use, methods: special_format, check_row
         
     | 
| 
       16 
     | 
    
         
            -
                    # @param include_option [Boolean] 
     | 
| 
      
 16 
     | 
    
         
            +
                    # @param include_option [Boolean]        `true` : include CLI options
         
     | 
| 
      
 17 
     | 
    
         
            +
                    # @param agent_columns  [Boolean]        `true` : include agents columns
         
     | 
| 
      
 18 
     | 
    
         
            +
                    # @param schema         [Hash]           The JSON spec
         
     | 
| 
       17 
19 
     | 
    
         
             
                    # @return [Array] a table suitable to display in manual
         
     | 
| 
       18 
     | 
    
         
            -
                    def man_table(formatter, include_option: false, agent_columns: true)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    def man_table(formatter, include_option: false, agent_columns: true, schema: Spec::SCHEMA)
         
     | 
| 
       19 
21 
     | 
    
         
             
                      col_local = agent_to_short(:direct)
         
     | 
| 
       20 
     | 
    
         
            -
                      cols =  
     | 
| 
       21 
     | 
    
         
            -
                       
     | 
| 
      
 22 
     | 
    
         
            +
                      cols = %i[name type description]
         
     | 
| 
      
 23 
     | 
    
         
            +
                      cols.insert(-2, *AGENT_LIST.map(&:last)) if agent_columns
         
     | 
| 
      
 24 
     | 
    
         
            +
                      rows = []
         
     | 
| 
      
 25 
     | 
    
         
            +
                      schema['properties'].each do |name, info|
         
     | 
| 
      
 26 
     | 
    
         
            +
                        if info['type'].eql?('object') && info['properties']
         
     | 
| 
      
 27 
     | 
    
         
            +
                          rows.concat(man_table(formatter, include_option: include_option, agent_columns: agent_columns, schema: info).last.map { |h| h.merge(name: "#{name}.#{h[:name]}") })
         
     | 
| 
      
 28 
     | 
    
         
            +
                        end
         
     | 
| 
       22 
29 
     | 
    
         
             
                        # manual table
         
     | 
| 
       23 
30 
     | 
    
         
             
                        columns = {
         
     | 
| 
       24 
31 
     | 
    
         
             
                          name:        name,
         
     | 
| 
       25 
     | 
    
         
            -
                          type:         
     | 
| 
      
 32 
     | 
    
         
            +
                          type:        info['type'],
         
     | 
| 
       26 
33 
     | 
    
         
             
                          description: []
         
     | 
| 
       27 
34 
     | 
    
         
             
                        }
         
     | 
| 
       28 
     | 
    
         
            -
                        # replace "back solidus" HTML entity with its text value
         
     | 
| 
       29 
     | 
    
         
            -
                        #
         
     | 
| 
       30 
     | 
    
         
            -
                        # split lines
         
     | 
| 
      
 35 
     | 
    
         
            +
                        # replace "back solidus" HTML entity with its text value, highlight keywords, and split lines
         
     | 
| 
       31 
36 
     | 
    
         
             
                        columns[:description] =
         
     | 
| 
       32 
     | 
    
         
            -
                           
     | 
| 
      
 37 
     | 
    
         
            +
                          info['description']
         
     | 
| 
       33 
38 
     | 
    
         
             
                            .gsub('\', '\\')
         
     | 
| 
       34 
39 
     | 
    
         
             
                            .gsub(/`([a-z0-9_.+-]+)`/){formatter.keyword_highlight(Regexp.last_match(1))}
         
     | 
| 
       35 
     | 
    
         
            -
                            .split("\n") if  
     | 
| 
       36 
     | 
    
         
            -
                        columns[:description].unshift("DEPRECATED: #{ 
     | 
| 
      
 40 
     | 
    
         
            +
                            .split("\n") if info.key?('description')
         
     | 
| 
      
 41 
     | 
    
         
            +
                        columns[:description].unshift("DEPRECATED: #{info['x-deprecation']}") if info.key?('x-deprecation')
         
     | 
| 
       37 
42 
     | 
    
         
             
                        # add flags for supported agents in doc
         
     | 
| 
       38 
43 
     | 
    
         
             
                        agents = []
         
     | 
| 
       39 
44 
     | 
    
         
             
                        AGENT_LIST.each do |agent_info|
         
     | 
| 
       40 
     | 
    
         
            -
                          agents.push(agent_info.last) if  
     | 
| 
      
 45 
     | 
    
         
            +
                          agents.push(agent_info.last) if info['x-agents'].nil? || info['x-agents'].include?(agent_info.first.to_s)
         
     | 
| 
       41 
46 
     | 
    
         
             
                        end
         
     | 
| 
       42 
     | 
    
         
            -
                        agents. 
     | 
| 
      
 47 
     | 
    
         
            +
                        Aspera.assert(agents.include?(col_local)){"#{name}: x-cli-option requires agent direct (or nil)"} if info['x-cli-option']
         
     | 
| 
       43 
48 
     | 
    
         
             
                        if agent_columns
         
     | 
| 
       44 
49 
     | 
    
         
             
                          AGENT_LIST.each do |agent_info|
         
     | 
| 
       45 
50 
     | 
    
         
             
                            columns[agent_info.last] = formatter.tick(agents.include?(agent_info.last))
         
     | 
| 
         @@ -49,30 +54,31 @@ module Aspera 
     | 
|
| 
       49 
54 
     | 
    
         
             
                        end
         
     | 
| 
       50 
55 
     | 
    
         
             
                        # only keep lines that are usable in supported agents
         
     | 
| 
       51 
56 
     | 
    
         
             
                        next false if agents.empty?
         
     | 
| 
       52 
     | 
    
         
            -
                        columns[:description].push("Allowed values: #{ 
     | 
| 
       53 
     | 
    
         
            -
                         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
                           
     | 
| 
       56 
     | 
    
         
            -
                             
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                            ''
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
                         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
                       
     | 
| 
      
 57 
     | 
    
         
            +
                        columns[:description].push("Allowed values: #{info['enum'].map{ |v| formatter.keyword_highlight(v)}.join(', ')}") if info.key?('enum')
         
     | 
| 
      
 58 
     | 
    
         
            +
                        if include_option
         
     | 
| 
      
 59 
     | 
    
         
            +
                          envvar_prefix = ''
         
     | 
| 
      
 60 
     | 
    
         
            +
                          cli_option =
         
     | 
| 
      
 61 
     | 
    
         
            +
                            if info.key?('x-cli-envvar')
         
     | 
| 
      
 62 
     | 
    
         
            +
                              envvar_prefix = 'env:'
         
     | 
| 
      
 63 
     | 
    
         
            +
                              info['x-cli-envvar']
         
     | 
| 
      
 64 
     | 
    
         
            +
                            elsif info['x-cli-switch']
         
     | 
| 
      
 65 
     | 
    
         
            +
                              info['x-cli-option']
         
     | 
| 
      
 66 
     | 
    
         
            +
                            elsif info['x-cli-option']
         
     | 
| 
      
 67 
     | 
    
         
            +
                              arg_type = info.key?('enum') ? '{enum}' : "{#{[info['type']].flatten.join('|')}}"
         
     | 
| 
      
 68 
     | 
    
         
            +
                              # conversion_tag = info['x-cli-convert']
         
     | 
| 
      
 69 
     | 
    
         
            +
                              conversion_tag = info.key?('x-cli-convert') ? 'conversion' : nil
         
     | 
| 
      
 70 
     | 
    
         
            +
                              sep = info['x-cli-option'].start_with?('--') ? '=' : ' '
         
     | 
| 
      
 71 
     | 
    
         
            +
                              "#{info['x-cli-option']}#{sep}#{"(#{conversion_tag})" if conversion_tag}#{arg_type}"
         
     | 
| 
      
 72 
     | 
    
         
            +
                            end
         
     | 
| 
      
 73 
     | 
    
         
            +
                          columns[:description].push("(#{'special:' if info['x-cli-special']}#{envvar_prefix}#{formatter.keyword_highlight(cli_option)})") if cli_option
         
     | 
| 
      
 74 
     | 
    
         
            +
                        end
         
     | 
| 
      
 75 
     | 
    
         
            +
                        rows.push(formatter.check_row(columns))
         
     | 
| 
      
 76 
     | 
    
         
            +
                      end
         
     | 
| 
      
 77 
     | 
    
         
            +
                      [cols, rows.sort_by{ |i| i[:name]}]
         
     | 
| 
       72 
78 
     | 
    
         
             
                    end
         
     | 
| 
       73 
79 
     | 
    
         
             
                  end
         
     | 
| 
       74 
80 
     | 
    
         
             
                  # Agents shown in manual for parameters (sub list)
         
     | 
| 
       75 
     | 
    
         
            -
                  AGENT_LIST = Agent:: 
     | 
| 
      
 81 
     | 
    
         
            +
                  AGENT_LIST = Agent::Factory.instance.list.map do |agent_sym|
         
     | 
| 
       76 
82 
     | 
    
         
             
                    [agent_sym, agent_sym.to_s.capitalize, agent_to_short(agent_sym)]
         
     | 
| 
       77 
83 
     | 
    
         
             
                  end.sort_by(&:last).freeze
         
     | 
| 
       78 
84 
     | 
    
         
             
                end
         
     | 
    
        data/lib/aspera/uri_reader.rb
    CHANGED
    
    | 
         @@ -37,7 +37,7 @@ module Aspera 
     | 
|
| 
       37 
37 
     | 
    
         
             
                      return File.expand_path(url[SCHEME_FILE_PFX2.length..-1])
         
     | 
| 
       38 
38 
     | 
    
         
             
                    else
         
     | 
| 
       39 
39 
     | 
    
         
             
                      # download to temp file
         
     | 
| 
       40 
     | 
    
         
            -
                      #  
     | 
| 
      
 40 
     | 
    
         
            +
                      # auto-delete on exit
         
     | 
| 
       41 
41 
     | 
    
         
             
                      sdk_archive_path = TempFileManager.instance.new_file_path_global(suffix: File.basename(url))
         
     | 
| 
       42 
42 
     | 
    
         
             
                      Aspera::Rest.new(base_url: url, redirect_max: 3).call(operation: 'GET', save_to_file: sdk_archive_path)
         
     | 
| 
       43 
43 
     | 
    
         
             
                      return sdk_archive_path
         
     | 
    
        data/lib/aspera/web_auth.rb
    CHANGED
    
    | 
         @@ -17,7 +17,7 @@ module Aspera 
     | 
|
| 
       17 
17 
     | 
    
         
             
                def service(request, response)
         
     | 
| 
       18 
18 
     | 
    
         
             
                  Log.log.debug{"received request from browser #{request.request_method} #{request.path}"}
         
     | 
| 
       19 
19 
     | 
    
         
             
                  Aspera.assert_values(request.request_method, ['GET'], type: WEBrick::HTTPStatus::MethodNotAllowed){'HTTP verb'}
         
     | 
| 
       20 
     | 
    
         
            -
                   
     | 
| 
      
 20 
     | 
    
         
            +
                  additional_info = @web_auth.signal_request(request)
         
     | 
| 
       21 
21 
     | 
    
         
             
                  response.status = 200
         
     | 
| 
       22 
22 
     | 
    
         
             
                  response.content_type = 'text/html'
         
     | 
| 
       23 
23 
     | 
    
         
             
                  response.body = <<~HTML
         
     | 
| 
         @@ -91,7 +91,7 @@ module Aspera 
     | 
|
| 
       91 
91 
     | 
    
         
             
                    <body>
         
     | 
| 
       92 
92 
     | 
    
         
             
                    <h1>Thank You!</h1>
         
     | 
| 
       93 
93 
     | 
    
         
             
                    <p>You can close this window.</p>
         
     | 
| 
       94 
     | 
    
         
            -
                    <p>#{ 
     | 
| 
      
 94 
     | 
    
         
            +
                    <p>#{additional_info}</p>
         
     | 
| 
       95 
95 
     | 
    
         | 
| 
       96 
96 
     | 
    
         
             
                    <!-- JavaScript to generate IBM logos -->
         
     | 
| 
       97 
97 
     | 
    
         
             
                    <script>
         
     | 
| 
         @@ -170,15 +170,15 @@ module Aspera 
     | 
|
| 
       170 
170 
     | 
    
         
             
              # store the final query
         
     | 
| 
       171 
171 
     | 
    
         
             
              class WebAuth < WebServerSimple
         
     | 
| 
       172 
172 
     | 
    
         
             
                # @param endpoint_url     [String] e.g. 'https://127.0.0.1:12345'
         
     | 
| 
       173 
     | 
    
         
            -
                # @param  
     | 
| 
       174 
     | 
    
         
            -
                def initialize(endpoint_url,  
     | 
| 
      
 173 
     | 
    
         
            +
                # @param additional_info [String] Information in web page
         
     | 
| 
      
 174 
     | 
    
         
            +
                def initialize(endpoint_url, additional_info = nil)
         
     | 
| 
       175 
175 
     | 
    
         
             
                  uri = URI.parse(endpoint_url)
         
     | 
| 
       176 
176 
     | 
    
         
             
                  super(uri)
         
     | 
| 
       177 
177 
     | 
    
         
             
                  @mutex = Mutex.new
         
     | 
| 
       178 
178 
     | 
    
         
             
                  @cond = ConditionVariable.new
         
     | 
| 
       179 
179 
     | 
    
         
             
                  @expected_path = uri.path.empty? ? '/' : uri.path
         
     | 
| 
       180 
180 
     | 
    
         
             
                  @query = nil
         
     | 
| 
       181 
     | 
    
         
            -
                  @ 
     | 
| 
      
 181 
     | 
    
         
            +
                  @additional_info = additional_info
         
     | 
| 
       182 
182 
     | 
    
         
             
                  # last argument (self) is provided to constructor of servlet
         
     | 
| 
       183 
183 
     | 
    
         
             
                  mount(@expected_path, WebAuthServlet, self)
         
     | 
| 
       184 
184 
     | 
    
         
             
                  # server runs in thread
         
     | 
| 
         @@ -194,7 +194,7 @@ module Aspera 
     | 
|
| 
       194 
194 
     | 
    
         
             
                    @query = request.query
         
     | 
| 
       195 
195 
     | 
    
         
             
                    @cond.signal
         
     | 
| 
       196 
196 
     | 
    
         
             
                  end
         
     | 
| 
       197 
     | 
    
         
            -
                  return @ 
     | 
| 
      
 197 
     | 
    
         
            +
                  return @additional_info
         
     | 
| 
       198 
198 
     | 
    
         
             
                end
         
     | 
| 
       199 
199 
     | 
    
         | 
| 
       200 
200 
     | 
    
         
             
                # wait for request on web server (main thread)
         
     | 
    
        data.tar.gz.sig
    CHANGED
    
    | 
         Binary file 
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: aspera-cli
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 4.24. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 4.24.2
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Laurent Martin
         
     | 
| 
         @@ -37,7 +37,7 @@ cert_chain: 
     | 
|
| 
       37 
37 
     | 
    
         
             
              eTf9kxhVM40wGQOECVNA8UsEEZHD48eF+csUYZtAJOF5oxTI8UyV9T/o6CgO0c9/
         
     | 
| 
       38 
38 
     | 
    
         
             
              Gzz+Qm5ULOUcPiJLjSpaiTrkiIVYiDGnqNSr6R1Hb1c=
         
     | 
| 
       39 
39 
     | 
    
         
             
              -----END CERTIFICATE-----
         
     | 
| 
       40 
     | 
    
         
            -
            date: 2025- 
     | 
| 
      
 40 
     | 
    
         
            +
            date: 2025-10-23 00:00:00.000000000 Z
         
     | 
| 
       41 
41 
     | 
    
         
             
            dependencies:
         
     | 
| 
       42 
42 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       43 
43 
     | 
    
         
             
              name: blankslate
         
     | 
| 
         @@ -282,6 +282,7 @@ files: 
     | 
|
| 
       282 
282 
     | 
    
         
             
            - lib/aspera/agent/connect.rb
         
     | 
| 
       283 
283 
     | 
    
         
             
            - lib/aspera/agent/desktop.rb
         
     | 
| 
       284 
284 
     | 
    
         
             
            - lib/aspera/agent/direct.rb
         
     | 
| 
      
 285 
     | 
    
         
            +
            - lib/aspera/agent/factory.rb
         
     | 
| 
       285 
286 
     | 
    
         
             
            - lib/aspera/agent/httpgw.rb
         
     | 
| 
       286 
287 
     | 
    
         
             
            - lib/aspera/agent/node.rb
         
     | 
| 
       287 
288 
     | 
    
         
             
            - lib/aspera/agent/transferd.rb
         
     | 
| 
         @@ -289,13 +290,13 @@ files: 
     | 
|
| 
       289 
290 
     | 
    
         
             
            - lib/aspera/api/aoc.rb
         
     | 
| 
       290 
291 
     | 
    
         
             
            - lib/aspera/api/ats.rb
         
     | 
| 
       291 
292 
     | 
    
         
             
            - lib/aspera/api/cos_node.rb
         
     | 
| 
      
 293 
     | 
    
         
            +
            - lib/aspera/api/faspex.rb
         
     | 
| 
       292 
294 
     | 
    
         
             
            - lib/aspera/api/httpgw.rb
         
     | 
| 
       293 
295 
     | 
    
         
             
            - lib/aspera/api/node.rb
         
     | 
| 
       294 
296 
     | 
    
         
             
            - lib/aspera/ascmd.rb
         
     | 
| 
       295 
297 
     | 
    
         
             
            - lib/aspera/ascp/installation.rb
         
     | 
| 
       296 
298 
     | 
    
         
             
            - lib/aspera/ascp/management.rb
         
     | 
| 
       297 
299 
     | 
    
         
             
            - lib/aspera/assert.rb
         
     | 
| 
       298 
     | 
    
         
            -
            - lib/aspera/cli/basic_auth_plugin.rb
         
     | 
| 
       299 
300 
     | 
    
         
             
            - lib/aspera/cli/error.rb
         
     | 
| 
       300 
301 
     | 
    
         
             
            - lib/aspera/cli/extended_value.rb
         
     | 
| 
       301 
302 
     | 
    
         
             
            - lib/aspera/cli/formatter.rb
         
     | 
| 
         @@ -303,19 +304,21 @@ files: 
     | 
|
| 
       303 
304 
     | 
    
         
             
            - lib/aspera/cli/info.rb
         
     | 
| 
       304 
305 
     | 
    
         
             
            - lib/aspera/cli/main.rb
         
     | 
| 
       305 
306 
     | 
    
         
             
            - lib/aspera/cli/manager.rb
         
     | 
| 
       306 
     | 
    
         
            -
            - lib/aspera/cli/plugin.rb
         
     | 
| 
       307 
     | 
    
         
            -
            - lib/aspera/cli/plugin_factory.rb
         
     | 
| 
       308 
307 
     | 
    
         
             
            - lib/aspera/cli/plugins/alee.rb
         
     | 
| 
       309 
308 
     | 
    
         
             
            - lib/aspera/cli/plugins/aoc.rb
         
     | 
| 
       310 
309 
     | 
    
         
             
            - lib/aspera/cli/plugins/ats.rb
         
     | 
| 
      
 310 
     | 
    
         
            +
            - lib/aspera/cli/plugins/base.rb
         
     | 
| 
      
 311 
     | 
    
         
            +
            - lib/aspera/cli/plugins/basic_auth.rb
         
     | 
| 
       311 
312 
     | 
    
         
             
            - lib/aspera/cli/plugins/config.rb
         
     | 
| 
       312 
313 
     | 
    
         
             
            - lib/aspera/cli/plugins/console.rb
         
     | 
| 
       313 
314 
     | 
    
         
             
            - lib/aspera/cli/plugins/cos.rb
         
     | 
| 
      
 315 
     | 
    
         
            +
            - lib/aspera/cli/plugins/factory.rb
         
     | 
| 
       314 
316 
     | 
    
         
             
            - lib/aspera/cli/plugins/faspex.rb
         
     | 
| 
       315 
317 
     | 
    
         
             
            - lib/aspera/cli/plugins/faspex5.rb
         
     | 
| 
       316 
318 
     | 
    
         
             
            - lib/aspera/cli/plugins/faspio.rb
         
     | 
| 
       317 
319 
     | 
    
         
             
            - lib/aspera/cli/plugins/httpgw.rb
         
     | 
| 
       318 
320 
     | 
    
         
             
            - lib/aspera/cli/plugins/node.rb
         
     | 
| 
      
 321 
     | 
    
         
            +
            - lib/aspera/cli/plugins/oauth.rb
         
     | 
| 
       319 
322 
     | 
    
         
             
            - lib/aspera/cli/plugins/orchestrator.rb
         
     | 
| 
       320 
323 
     | 
    
         
             
            - lib/aspera/cli/plugins/preview.rb
         
     | 
| 
       321 
324 
     | 
    
         
             
            - lib/aspera/cli/plugins/server.rb
         
     | 
| 
         @@ -378,7 +381,6 @@ files: 
     | 
|
| 
       378 
381 
     | 
    
         
             
            - lib/aspera/rest_call_error.rb
         
     | 
| 
       379 
382 
     | 
    
         
             
            - lib/aspera/rest_error_analyzer.rb
         
     | 
| 
       380 
383 
     | 
    
         
             
            - lib/aspera/rest_errors_aspera.rb
         
     | 
| 
       381 
     | 
    
         
            -
            - lib/aspera/resumer.rb
         
     | 
| 
       382 
384 
     | 
    
         
             
            - lib/aspera/secret_hider.rb
         
     | 
| 
       383 
385 
     | 
    
         
             
            - lib/aspera/ssh.rb
         
     | 
| 
       384 
386 
     | 
    
         
             
            - lib/aspera/sync/args.schema.yaml
         
     | 
| 
         @@ -388,9 +390,9 @@ files: 
     | 
|
| 
       388 
390 
     | 
    
         
             
            - lib/aspera/temp_file_manager.rb
         
     | 
| 
       389 
391 
     | 
    
         
             
            - lib/aspera/timer_limiter.rb
         
     | 
| 
       390 
392 
     | 
    
         
             
            - lib/aspera/transfer/error.rb
         
     | 
| 
       391 
     | 
    
         
            -
            - lib/aspera/transfer/error_info.rb
         
     | 
| 
       392 
393 
     | 
    
         
             
            - lib/aspera/transfer/faux_file.rb
         
     | 
| 
       393 
394 
     | 
    
         
             
            - lib/aspera/transfer/parameters.rb
         
     | 
| 
      
 395 
     | 
    
         
            +
            - lib/aspera/transfer/resumer.rb
         
     | 
| 
       394 
396 
     | 
    
         
             
            - lib/aspera/transfer/spec.rb
         
     | 
| 
       395 
397 
     | 
    
         
             
            - lib/aspera/transfer/spec.schema.yaml
         
     | 
| 
       396 
398 
     | 
    
         
             
            - lib/aspera/transfer/spec_doc.rb
         
     | 
    
        metadata.gz.sig
    CHANGED
    
    | 
         @@ -1,2 +1,2 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
            �� 
     | 
| 
      
 1 
     | 
    
         
            +
            w��x�t�����Č�ѱ �23��ro��2���=
         
     | 
| 
      
 2 
     | 
    
         
            +
            ����	����������9I�J<D��HA���m����`�C�GNч��`���\/��Ln�Z��&���/�vѨ�:���p`��G��m�8���7�[���X=i�ʉ�����Ks�.Gz�y¼����(ۿS����P����������3�;@|���tꦔ�;����A�u��*
         
     | 
| 
         @@ -1,43 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            require 'aspera/rest'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'aspera/cli/plugin'
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
            module Aspera
         
     | 
| 
       7 
     | 
    
         
            -
              module Cli
         
     | 
| 
       8 
     | 
    
         
            -
                # base class for applications supporting basic authentication
         
     | 
| 
       9 
     | 
    
         
            -
                class BasicAuthPlugin < Cli::Plugin
         
     | 
| 
       10 
     | 
    
         
            -
                  class << self
         
     | 
| 
       11 
     | 
    
         
            -
                    def declare_options(options)
         
     | 
| 
       12 
     | 
    
         
            -
                      options.declare(:url, 'URL of application, e.g. https://app.example.com/aspera/app')
         
     | 
| 
       13 
     | 
    
         
            -
                      options.declare(:username, "User's identifier")
         
     | 
| 
       14 
     | 
    
         
            -
                      options.declare(:password, "User's password")
         
     | 
| 
       15 
     | 
    
         
            -
                      options.parse_options!
         
     | 
| 
       16 
     | 
    
         
            -
                    end
         
     | 
| 
       17 
     | 
    
         
            -
                  end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                  def initialize(context:, basic_options: true)
         
     | 
| 
       20 
     | 
    
         
            -
                    super(context: context)
         
     | 
| 
       21 
     | 
    
         
            -
                    BasicAuthPlugin.declare_options(options) if basic_options
         
     | 
| 
       22 
     | 
    
         
            -
                  end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                  # returns a Rest object with basic auth
         
     | 
| 
       25 
     | 
    
         
            -
                  def basic_auth_params(subpath = nil)
         
     | 
| 
       26 
     | 
    
         
            -
                    api_url = options.get_option(:url, mandatory: true)
         
     | 
| 
       27 
     | 
    
         
            -
                    api_url = "#{api_url}/#{subpath}" unless subpath.nil?
         
     | 
| 
       28 
     | 
    
         
            -
                    return {
         
     | 
| 
       29 
     | 
    
         
            -
                      base_url: api_url,
         
     | 
| 
       30 
     | 
    
         
            -
                      auth:     {
         
     | 
| 
       31 
     | 
    
         
            -
                        type:     :basic,
         
     | 
| 
       32 
     | 
    
         
            -
                        username: options.get_option(:username, mandatory: true),
         
     | 
| 
       33 
     | 
    
         
            -
                        password: options.get_option(:password, mandatory: true)
         
     | 
| 
       34 
     | 
    
         
            -
                      }
         
     | 
| 
       35 
     | 
    
         
            -
                    }
         
     | 
| 
       36 
     | 
    
         
            -
                  end
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
                  def basic_auth_api(subpath = nil)
         
     | 
| 
       39 
     | 
    
         
            -
                    return Rest.new(**basic_auth_params(subpath))
         
     | 
| 
       40 
     | 
    
         
            -
                  end
         
     | 
| 
       41 
     | 
    
         
            -
                end
         
     | 
| 
       42 
     | 
    
         
            -
              end
         
     | 
| 
       43 
     | 
    
         
            -
            end
         
     | 
    
        data/lib/aspera/cli/plugin.rb
    DELETED
    
    | 
         @@ -1,333 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            require 'aspera/cli/extended_value'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'aspera/assert'
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
            module Aspera
         
     | 
| 
       7 
     | 
    
         
            -
              module Cli
         
     | 
| 
       8 
     | 
    
         
            -
                # Base class for plugins
         
     | 
| 
       9 
     | 
    
         
            -
                class Plugin
         
     | 
| 
       10 
     | 
    
         
            -
                  # operations without id
         
     | 
| 
       11 
     | 
    
         
            -
                  GLOBAL_OPS = %i[create list].freeze
         
     | 
| 
       12 
     | 
    
         
            -
                  # operations with id
         
     | 
| 
       13 
     | 
    
         
            -
                  INSTANCE_OPS = %i[modify delete show].freeze
         
     | 
| 
       14 
     | 
    
         
            -
                  # all standard operations
         
     | 
| 
       15 
     | 
    
         
            -
                  ALL_OPS = (GLOBAL_OPS + INSTANCE_OPS).freeze
         
     | 
| 
       16 
     | 
    
         
            -
                  # special query parameter: max number of items for list command
         
     | 
| 
       17 
     | 
    
         
            -
                  MAX_ITEMS = 'max'
         
     | 
| 
       18 
     | 
    
         
            -
                  # special query parameter: max number of pages for list command
         
     | 
| 
       19 
     | 
    
         
            -
                  MAX_PAGES = 'pmax'
         
     | 
| 
       20 
     | 
    
         
            -
                  # special identifier format: look for this name to find where supported
         
     | 
| 
       21 
     | 
    
         
            -
                  REGEX_LOOKUP_ID_BY_FIELD = /^%([^:]+):(.*)$/
         
     | 
| 
       22 
     | 
    
         
            -
                  PER_PAGE_DEFAULT = 1000
         
     | 
| 
       23 
     | 
    
         
            -
                  private_constant :PER_PAGE_DEFAULT
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                  class << self
         
     | 
| 
       26 
     | 
    
         
            -
                    def declare_generic_options(options)
         
     | 
| 
       27 
     | 
    
         
            -
                      options.declare(:query, 'Additional filter for for some commands (list/delete)', types: [Hash, Array])
         
     | 
| 
       28 
     | 
    
         
            -
                      options.declare(:property, 'Name of property to set (modify operation)')
         
     | 
| 
       29 
     | 
    
         
            -
                      options.declare(:bulk, 'Bulk operation (only some)', values: :bool, default: :no)
         
     | 
| 
       30 
     | 
    
         
            -
                      options.declare(:bfail, 'Bulk operation error handling', values: :bool, default: :yes)
         
     | 
| 
       31 
     | 
    
         
            -
                    end
         
     | 
| 
       32 
     | 
    
         
            -
                  end
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                  def initialize(context:)
         
     | 
| 
       35 
     | 
    
         
            -
                    # check presence in descendant of mandatory method and constant
         
     | 
| 
       36 
     | 
    
         
            -
                    Aspera.assert(respond_to?(:execute_action), type: InternalError){"Missing method 'execute_action' in #{self.class}"}
         
     | 
| 
       37 
     | 
    
         
            -
                    Aspera.assert(self.class.constants.include?(:ACTIONS), type: InternalError){"Missing constant 'ACTIONS' in #{self.class}"}
         
     | 
| 
       38 
     | 
    
         
            -
                    @context = context
         
     | 
| 
       39 
     | 
    
         
            -
                    add_manual_header if @context.man_header
         
     | 
| 
       40 
     | 
    
         
            -
                  end
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                  # Global objects
         
     | 
| 
       43 
     | 
    
         
            -
                  attr_reader :context
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                  def options; @context.options; end
         
     | 
| 
       46 
     | 
    
         
            -
                  def transfer; @context.transfer; end
         
     | 
| 
       47 
     | 
    
         
            -
                  def config; @context.config; end
         
     | 
| 
       48 
     | 
    
         
            -
                  def formatter; @context.formatter; end
         
     | 
| 
       49 
     | 
    
         
            -
                  def persistency; @context.persistency; end
         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
                  def add_manual_header(has_options = true)
         
     | 
| 
       52 
     | 
    
         
            -
                    # manual header for all plugins
         
     | 
| 
       53 
     | 
    
         
            -
                    options.parser.separator('')
         
     | 
| 
       54 
     | 
    
         
            -
                    options.parser.separator("COMMAND: #{self.class.name.split('::').last.downcase}")
         
     | 
| 
       55 
     | 
    
         
            -
                    options.parser.separator("SUBCOMMANDS: #{self.class.const_get(:ACTIONS).map(&:to_s).sort.join(' ')}")
         
     | 
| 
       56 
     | 
    
         
            -
                    options.parser.separator('OPTIONS:') if has_options
         
     | 
| 
       57 
     | 
    
         
            -
                  end
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                  # Must be called AFTER the instance action:
         
     | 
| 
       60 
     | 
    
         
            -
                  # ... folder browse _call_instance_identifier
         
     | 
| 
       61 
     | 
    
         
            -
                  #
         
     | 
| 
       62 
     | 
    
         
            -
                  # @param description [String] description of the identifier
         
     | 
| 
       63 
     | 
    
         
            -
                  # @param as_option   [Symbol] option name to use if identifier is an option
         
     | 
| 
       64 
     | 
    
         
            -
                  # @param block       [Proc] block to search for identifier based on attribute value
         
     | 
| 
       65 
     | 
    
         
            -
                  # @return   [String, Array] identifier or list of ids
         
     | 
| 
       66 
     | 
    
         
            -
                  def instance_identifier(description: 'identifier', as_option: nil, &block)
         
     | 
| 
       67 
     | 
    
         
            -
                    if as_option.nil?
         
     | 
| 
       68 
     | 
    
         
            -
                      res_id = options.get_next_argument(description, multiple: options.get_option(:bulk)) if res_id.nil?
         
     | 
| 
       69 
     | 
    
         
            -
                    else
         
     | 
| 
       70 
     | 
    
         
            -
                      res_id = options.get_option(as_option)
         
     | 
| 
       71 
     | 
    
         
            -
                    end
         
     | 
| 
       72 
     | 
    
         
            -
                    # can be an Array
         
     | 
| 
       73 
     | 
    
         
            -
                    if res_id.is_a?(String) && (m = res_id.match(REGEX_LOOKUP_ID_BY_FIELD))
         
     | 
| 
       74 
     | 
    
         
            -
                      if block
         
     | 
| 
       75 
     | 
    
         
            -
                        res_id = yield(m[1], ExtendedValue.instance.evaluate(m[2]))
         
     | 
| 
       76 
     | 
    
         
            -
                      else
         
     | 
| 
       77 
     | 
    
         
            -
                        raise Cli::BadArgument, "Percent syntax for #{description} not supported in this context"
         
     | 
| 
       78 
     | 
    
         
            -
                      end
         
     | 
| 
       79 
     | 
    
         
            -
                    end
         
     | 
| 
       80 
     | 
    
         
            -
                    return res_id
         
     | 
| 
       81 
     | 
    
         
            -
                  end
         
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
                  # For create and delete operations: execute one actin or multiple if bulk is yes
         
     | 
| 
       84 
     | 
    
         
            -
                  # @param command   [Symbol] operation: :create, :delete, ...
         
     | 
| 
       85 
     | 
    
         
            -
                  # @param descr     [String] description of the value
         
     | 
| 
       86 
     | 
    
         
            -
                  # @param values    [Object] the value(s), or the type of value to get from user
         
     | 
| 
       87 
     | 
    
         
            -
                  # @param id_result [String] key in result hash to use as identifier
         
     | 
| 
       88 
     | 
    
         
            -
                  # @param fields    [Array]  fields to display
         
     | 
| 
       89 
     | 
    
         
            -
                  # @param &block    [Proc]   block to execute for each value
         
     | 
| 
       90 
     | 
    
         
            -
                  def do_bulk_operation(command:, descr: nil, values: Hash, id_result: 'id', fields: :default)
         
     | 
| 
       91 
     | 
    
         
            -
                    Aspera.assert(block_given?){'missing block'}
         
     | 
| 
       92 
     | 
    
         
            -
                    is_bulk = options.get_option(:bulk)
         
     | 
| 
       93 
     | 
    
         
            -
                    case values
         
     | 
| 
       94 
     | 
    
         
            -
                    when :identifier
         
     | 
| 
       95 
     | 
    
         
            -
                      values = instance_identifier(description: descr)
         
     | 
| 
       96 
     | 
    
         
            -
                    when Class
         
     | 
| 
       97 
     | 
    
         
            -
                      values = value_create_modify(command: command, description: descr, type: values, bulk: is_bulk)
         
     | 
| 
       98 
     | 
    
         
            -
                    end
         
     | 
| 
       99 
     | 
    
         
            -
                    # if not bulk, there is a single value
         
     | 
| 
       100 
     | 
    
         
            -
                    params = is_bulk ? values : [values]
         
     | 
| 
       101 
     | 
    
         
            -
                    Log.log.warn('Empty list given for bulk operation') if params.empty?
         
     | 
| 
       102 
     | 
    
         
            -
                    Log.dump(:bulk_operation, params)
         
     | 
| 
       103 
     | 
    
         
            -
                    result_list = []
         
     | 
| 
       104 
     | 
    
         
            -
                    params.each do |param|
         
     | 
| 
       105 
     | 
    
         
            -
                      # init for delete
         
     | 
| 
       106 
     | 
    
         
            -
                      result = {id_result => param}
         
     | 
| 
       107 
     | 
    
         
            -
                      begin
         
     | 
| 
       108 
     | 
    
         
            -
                        # execute custom code
         
     | 
| 
       109 
     | 
    
         
            -
                        res = yield(param)
         
     | 
| 
       110 
     | 
    
         
            -
                        # if block returns a hash, let's use this (create)
         
     | 
| 
       111 
     | 
    
         
            -
                        result = res if res.is_a?(Hash)
         
     | 
| 
       112 
     | 
    
         
            -
                        # TODO: remove when faspio gw api fixes this
         
     | 
| 
       113 
     | 
    
         
            -
                        result = res.first if res.is_a?(Array) && res.first.is_a?(Hash)
         
     | 
| 
       114 
     | 
    
         
            -
                        # create -> created
         
     | 
| 
       115 
     | 
    
         
            -
                        result['status'] = "#{command}#{'e' unless command.to_s.end_with?('e')}d".gsub(/yed$/, 'ied')
         
     | 
| 
       116 
     | 
    
         
            -
                      rescue StandardError => e
         
     | 
| 
       117 
     | 
    
         
            -
                        raise e if options.get_option(:bfail)
         
     | 
| 
       118 
     | 
    
         
            -
                        result['status'] = e.to_s
         
     | 
| 
       119 
     | 
    
         
            -
                      end
         
     | 
| 
       120 
     | 
    
         
            -
                      result_list.push(result)
         
     | 
| 
       121 
     | 
    
         
            -
                    end
         
     | 
| 
       122 
     | 
    
         
            -
                    display_fields = [id_result, 'status']
         
     | 
| 
       123 
     | 
    
         
            -
                    if is_bulk
         
     | 
| 
       124 
     | 
    
         
            -
                      return Main.result_object_list(result_list, fields: display_fields)
         
     | 
| 
       125 
     | 
    
         
            -
                    else
         
     | 
| 
       126 
     | 
    
         
            -
                      display_fields = fields unless fields.eql?(:default)
         
     | 
| 
       127 
     | 
    
         
            -
                      return Main.result_single_object(result_list.first, fields: display_fields)
         
     | 
| 
       128 
     | 
    
         
            -
                    end
         
     | 
| 
       129 
     | 
    
         
            -
                  end
         
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
                  # Operations: Create, Delete, Show, List, Modify
         
     | 
| 
       132 
     | 
    
         
            -
                  # @param api            [Rest]    api to use
         
     | 
| 
       133 
     | 
    
         
            -
                  # @param entity         [String]  sub path in URL to resource relative to base url
         
     | 
| 
       134 
     | 
    
         
            -
                  # @param command        [Symbol]  command to execute: create show list modify delete
         
     | 
| 
       135 
     | 
    
         
            -
                  # @param display_fields [Array]   fields to display by default
         
     | 
| 
       136 
     | 
    
         
            -
                  # @param items_key      [String]  result is in a sub key of the json
         
     | 
| 
       137 
     | 
    
         
            -
                  # @param delete_style   [String]  if set, the delete operation by array in payload
         
     | 
| 
       138 
     | 
    
         
            -
                  # @param id_as_arg      [String]  if set, the id is provided as url argument ?<id_as_arg>=<id>
         
     | 
| 
       139 
     | 
    
         
            -
                  # @param is_singleton   [Boolean] if true, entity is the full path to the resource
         
     | 
| 
       140 
     | 
    
         
            -
                  # @param tclo           [Bool]    if set, :list use paging with total_count, limit, offset
         
     | 
| 
       141 
     | 
    
         
            -
                  # @param block          [Proc]    block to search for identifier based on attribute value
         
     | 
| 
       142 
     | 
    
         
            -
                  # @return result suitable for CLI result
         
     | 
| 
       143 
     | 
    
         
            -
                  def entity_execute(
         
     | 
| 
       144 
     | 
    
         
            -
                    api:,
         
     | 
| 
       145 
     | 
    
         
            -
                    entity:,
         
     | 
| 
       146 
     | 
    
         
            -
                    command: nil,
         
     | 
| 
       147 
     | 
    
         
            -
                    display_fields: nil,
         
     | 
| 
       148 
     | 
    
         
            -
                    items_key: nil,
         
     | 
| 
       149 
     | 
    
         
            -
                    delete_style: nil,
         
     | 
| 
       150 
     | 
    
         
            -
                    id_as_arg: false,
         
     | 
| 
       151 
     | 
    
         
            -
                    is_singleton: false,
         
     | 
| 
       152 
     | 
    
         
            -
                    list_query: nil,
         
     | 
| 
       153 
     | 
    
         
            -
                    tclo: false,
         
     | 
| 
       154 
     | 
    
         
            -
                    &block
         
     | 
| 
       155 
     | 
    
         
            -
                  )
         
     | 
| 
       156 
     | 
    
         
            -
                    command = options.get_next_command(ALL_OPS) if command.nil?
         
     | 
| 
       157 
     | 
    
         
            -
                    if is_singleton
         
     | 
| 
       158 
     | 
    
         
            -
                      one_res_path = entity
         
     | 
| 
       159 
     | 
    
         
            -
                    elsif INSTANCE_OPS.include?(command)
         
     | 
| 
       160 
     | 
    
         
            -
                      one_res_id = instance_identifier(&block)
         
     | 
| 
       161 
     | 
    
         
            -
                      one_res_path = "#{entity}/#{one_res_id}"
         
     | 
| 
       162 
     | 
    
         
            -
                      one_res_path = "#{entity}?#{id_as_arg}=#{one_res_id}" if id_as_arg
         
     | 
| 
       163 
     | 
    
         
            -
                    end
         
     | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
     | 
    
         
            -
                    case command
         
     | 
| 
       166 
     | 
    
         
            -
                    when :create
         
     | 
| 
       167 
     | 
    
         
            -
                      raise BadArgument, 'cannot create singleton' if is_singleton
         
     | 
| 
       168 
     | 
    
         
            -
                      return do_bulk_operation(command: command, descr: 'data', fields: display_fields) do |params|
         
     | 
| 
       169 
     | 
    
         
            -
                        api.create(entity, params)
         
     | 
| 
       170 
     | 
    
         
            -
                      end
         
     | 
| 
       171 
     | 
    
         
            -
                    when :delete
         
     | 
| 
       172 
     | 
    
         
            -
                      raise BadArgument, 'cannot delete singleton' if is_singleton
         
     | 
| 
       173 
     | 
    
         
            -
                      if !delete_style.nil?
         
     | 
| 
       174 
     | 
    
         
            -
                        one_res_id = [one_res_id] unless one_res_id.is_a?(Array)
         
     | 
| 
       175 
     | 
    
         
            -
                        Aspera.assert_type(one_res_id, Array, type: Cli::BadArgument)
         
     | 
| 
       176 
     | 
    
         
            -
                        api.call(
         
     | 
| 
       177 
     | 
    
         
            -
                          operation:    'DELETE',
         
     | 
| 
       178 
     | 
    
         
            -
                          subpath:      entity,
         
     | 
| 
       179 
     | 
    
         
            -
                          content_type: Rest::MIME_JSON,
         
     | 
| 
       180 
     | 
    
         
            -
                          body:         {delete_style => one_res_id},
         
     | 
| 
       181 
     | 
    
         
            -
                          headers:      {'Accept' => Rest::MIME_JSON}
         
     | 
| 
       182 
     | 
    
         
            -
                        )
         
     | 
| 
       183 
     | 
    
         
            -
                        return Main.result_status('deleted')
         
     | 
| 
       184 
     | 
    
         
            -
                      end
         
     | 
| 
       185 
     | 
    
         
            -
                      return do_bulk_operation(command: command, values: one_res_id) do |one_id|
         
     | 
| 
       186 
     | 
    
         
            -
                        api.delete("#{entity}/#{one_id}", query_read_delete)
         
     | 
| 
       187 
     | 
    
         
            -
                        {'id' => one_id}
         
     | 
| 
       188 
     | 
    
         
            -
                      end
         
     | 
| 
       189 
     | 
    
         
            -
                    when :show
         
     | 
| 
       190 
     | 
    
         
            -
                      return Main.result_single_object(api.read(one_res_path), fields: display_fields)
         
     | 
| 
       191 
     | 
    
         
            -
                    when :list
         
     | 
| 
       192 
     | 
    
         
            -
                      if tclo
         
     | 
| 
       193 
     | 
    
         
            -
                        data, total = list_entities_limit_offset_total_count(api: api, entity:, items_key: items_key, query: list_query)
         
     | 
| 
       194 
     | 
    
         
            -
                        return Main.result_object_list(data, total: total, fields: display_fields)
         
     | 
| 
       195 
     | 
    
         
            -
                      end
         
     | 
| 
       196 
     | 
    
         
            -
                      resp = api.call(operation: 'GET', subpath: entity, headers: {'Accept' => Rest::MIME_JSON}, query: query_read_delete)
         
     | 
| 
       197 
     | 
    
         
            -
                      return Main.result_empty if resp[:http].code == '204'
         
     | 
| 
       198 
     | 
    
         
            -
                      data = resp[:data]
         
     | 
| 
       199 
     | 
    
         
            -
                      # TODO: not generic : which application is this for ?
         
     | 
| 
       200 
     | 
    
         
            -
                      if resp[:http]['Content-Type'].start_with?('application/vnd.api+json')
         
     | 
| 
       201 
     | 
    
         
            -
                        Log.log.debug('is vnd.api')
         
     | 
| 
       202 
     | 
    
         
            -
                        data = data[entity]
         
     | 
| 
       203 
     | 
    
         
            -
                      end
         
     | 
| 
       204 
     | 
    
         
            -
                      data = data[items_key] if items_key
         
     | 
| 
       205 
     | 
    
         
            -
                      case data
         
     | 
| 
       206 
     | 
    
         
            -
                      when Hash
         
     | 
| 
       207 
     | 
    
         
            -
                        return Main.result_single_object(data, fields: display_fields)
         
     | 
| 
       208 
     | 
    
         
            -
                      when Array
         
     | 
| 
       209 
     | 
    
         
            -
                        return Main.result_object_list(data, fields: display_fields) if data.empty? || data.first.is_a?(Hash)
         
     | 
| 
       210 
     | 
    
         
            -
                        return Main.result_value_list(data)
         
     | 
| 
       211 
     | 
    
         
            -
                      else
         
     | 
| 
       212 
     | 
    
         
            -
                        raise "An error occurred: unexpected result type for list: #{data.class}"
         
     | 
| 
       213 
     | 
    
         
            -
                      end
         
     | 
| 
       214 
     | 
    
         
            -
                    when :modify
         
     | 
| 
       215 
     | 
    
         
            -
                      parameters = value_create_modify(command: command)
         
     | 
| 
       216 
     | 
    
         
            -
                      property = options.get_option(:property)
         
     | 
| 
       217 
     | 
    
         
            -
                      parameters = {property => parameters} unless property.nil?
         
     | 
| 
       218 
     | 
    
         
            -
                      api.update(one_res_path, parameters)
         
     | 
| 
       219 
     | 
    
         
            -
                      return Main.result_status('modified')
         
     | 
| 
       220 
     | 
    
         
            -
                    else
         
     | 
| 
       221 
     | 
    
         
            -
                      raise "unknown action: #{command}"
         
     | 
| 
       222 
     | 
    
         
            -
                    end
         
     | 
| 
       223 
     | 
    
         
            -
                  end
         
     | 
| 
       224 
     | 
    
         
            -
             
     | 
| 
       225 
     | 
    
         
            -
                  # Query parameters in URL suitable for REST: list/GET and delete/DELETE
         
     | 
| 
       226 
     | 
    
         
            -
                  def query_read_delete(default: nil)
         
     | 
| 
       227 
     | 
    
         
            -
                    query = options.get_option(:query)
         
     | 
| 
       228 
     | 
    
         
            -
                    # dup default, as it could be frozen
         
     | 
| 
       229 
     | 
    
         
            -
                    query = default.dup if query.nil?
         
     | 
| 
       230 
     | 
    
         
            -
                    Log.log.debug{"query_read_delete=#{query}".bg_red}
         
     | 
| 
       231 
     | 
    
         
            -
                    begin
         
     | 
| 
       232 
     | 
    
         
            -
                      # check it is suitable
         
     | 
| 
       233 
     | 
    
         
            -
                      URI.encode_www_form(query) unless query.nil?
         
     | 
| 
       234 
     | 
    
         
            -
                    rescue StandardError => e
         
     | 
| 
       235 
     | 
    
         
            -
                      raise Cli::BadArgument, "Query must be an extended value (Hash, Array) which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
         
     | 
| 
       236 
     | 
    
         
            -
                    end
         
     | 
| 
       237 
     | 
    
         
            -
                    return query
         
     | 
| 
       238 
     | 
    
         
            -
                  end
         
     | 
| 
       239 
     | 
    
         
            -
             
     | 
| 
       240 
     | 
    
         
            -
                  # Retrieves an extended value from command line, used for creation or modification of entities
         
     | 
| 
       241 
     | 
    
         
            -
                  # @param command [Symbol] command name for error message
         
     | 
| 
       242 
     | 
    
         
            -
                  # @param type [Class] expected type of value, either a Class, an Array of Class
         
     | 
| 
       243 
     | 
    
         
            -
                  # @param bulk [Boolean] if true, value must be an Array of <type>
         
     | 
| 
       244 
     | 
    
         
            -
                  # @param default [Object] default value if not provided
         
     | 
| 
       245 
     | 
    
         
            -
                  def value_create_modify(command:, description: nil, type: Hash, bulk: false, default: nil)
         
     | 
| 
       246 
     | 
    
         
            -
                    value = options.get_next_argument(
         
     | 
| 
       247 
     | 
    
         
            -
                      "parameters for #{command}#{" (#{description})" unless description.nil?}", mandatory: default.nil?,
         
     | 
| 
       248 
     | 
    
         
            -
                      validation: bulk ? Array : type
         
     | 
| 
       249 
     | 
    
         
            -
                    )
         
     | 
| 
       250 
     | 
    
         
            -
                    value = default if value.nil?
         
     | 
| 
       251 
     | 
    
         
            -
                    unless type.nil?
         
     | 
| 
       252 
     | 
    
         
            -
                      type = [type] unless type.is_a?(Array)
         
     | 
| 
       253 
     | 
    
         
            -
                      Aspera.assert(type.all?(Class)){"check types must be a Class, not #{type.map(&:class).join(',')}"}
         
     | 
| 
       254 
     | 
    
         
            -
                      if bulk
         
     | 
| 
       255 
     | 
    
         
            -
                        Aspera.assert_type(value, Array, type: Cli::BadArgument)
         
     | 
| 
       256 
     | 
    
         
            -
                        value.each do |v|
         
     | 
| 
       257 
     | 
    
         
            -
                          Aspera.assert_values(v.class, type, type: Cli::BadArgument)
         
     | 
| 
       258 
     | 
    
         
            -
                        end
         
     | 
| 
       259 
     | 
    
         
            -
                      else
         
     | 
| 
       260 
     | 
    
         
            -
                        Aspera.assert_values(value.class, type, type: Cli::BadArgument)
         
     | 
| 
       261 
     | 
    
         
            -
                      end
         
     | 
| 
       262 
     | 
    
         
            -
                    end
         
     | 
| 
       263 
     | 
    
         
            -
                    return value
         
     | 
| 
       264 
     | 
    
         
            -
                  end
         
     | 
| 
       265 
     | 
    
         
            -
             
     | 
| 
       266 
     | 
    
         
            -
                  # Get a (full or partial) list of all entities of a given type with query: offset/limit
         
     | 
| 
       267 
     | 
    
         
            -
                  # @param `api`       [Rest]          the API object
         
     | 
| 
       268 
     | 
    
         
            -
                  # @param `entity`    [String,Symbol] the API endpoint of entity to list
         
     | 
| 
       269 
     | 
    
         
            -
                  # @param `items_key` [String]        key in the result to get the list of items
         
     | 
| 
       270 
     | 
    
         
            -
                  # @param `query`     [Hash,nil]      additional query parameters
         
     | 
| 
       271 
     | 
    
         
            -
                  # @return [Array] items, total_count
         
     | 
| 
       272 
     | 
    
         
            -
                  def list_entities_limit_offset_total_count(
         
     | 
| 
       273 
     | 
    
         
            -
                    api:,
         
     | 
| 
       274 
     | 
    
         
            -
                    entity:,
         
     | 
| 
       275 
     | 
    
         
            -
                    items_key: nil,
         
     | 
| 
       276 
     | 
    
         
            -
                    query: nil
         
     | 
| 
       277 
     | 
    
         
            -
                  )
         
     | 
| 
       278 
     | 
    
         
            -
                    entity = entity.to_s if entity.is_a?(Symbol)
         
     | 
| 
       279 
     | 
    
         
            -
                    items_key = entity.split('/').last if items_key.nil?
         
     | 
| 
       280 
     | 
    
         
            -
                    query = {} if query.nil?
         
     | 
| 
       281 
     | 
    
         
            -
                    Aspera.assert_type(entity, String)
         
     | 
| 
       282 
     | 
    
         
            -
                    Aspera.assert_type(items_key, String)
         
     | 
| 
       283 
     | 
    
         
            -
                    Aspera.assert_type(query, Hash)
         
     | 
| 
       284 
     | 
    
         
            -
                    Log.log.debug{"list_entities t=#{entity} k=#{items_key} q=#{query}"}
         
     | 
| 
       285 
     | 
    
         
            -
                    result = []
         
     | 
| 
       286 
     | 
    
         
            -
                    offset = 0
         
     | 
| 
       287 
     | 
    
         
            -
                    max_items = query.delete(MAX_ITEMS)
         
     | 
| 
       288 
     | 
    
         
            -
                    remain_pages = query.delete(MAX_PAGES)
         
     | 
| 
       289 
     | 
    
         
            -
                    # merge default parameters, by default 100 per page
         
     | 
| 
       290 
     | 
    
         
            -
                    query = {'limit'=> PER_PAGE_DEFAULT}.merge(query)
         
     | 
| 
       291 
     | 
    
         
            -
                    total_count = nil
         
     | 
| 
       292 
     | 
    
         
            -
                    loop do
         
     | 
| 
       293 
     | 
    
         
            -
                      query['offset'] = offset
         
     | 
| 
       294 
     | 
    
         
            -
                      page_result = api.read(entity, query)
         
     | 
| 
       295 
     | 
    
         
            -
                      Aspera.assert_type(page_result[items_key], Array)
         
     | 
| 
       296 
     | 
    
         
            -
                      result.concat(page_result[items_key])
         
     | 
| 
       297 
     | 
    
         
            -
                      # reach the limit set by user ?
         
     | 
| 
       298 
     | 
    
         
            -
                      if !max_items.nil? && (result.length >= max_items)
         
     | 
| 
       299 
     | 
    
         
            -
                        result = result.slice(0, max_items)
         
     | 
| 
       300 
     | 
    
         
            -
                        break
         
     | 
| 
       301 
     | 
    
         
            -
                      end
         
     | 
| 
       302 
     | 
    
         
            -
                      total_count ||= page_result['total_count']
         
     | 
| 
       303 
     | 
    
         
            -
                      break if result.length >= total_count
         
     | 
| 
       304 
     | 
    
         
            -
                      remain_pages -= 1 unless remain_pages.nil?
         
     | 
| 
       305 
     | 
    
         
            -
                      break if remain_pages == 0
         
     | 
| 
       306 
     | 
    
         
            -
                      offset += page_result[items_key].length
         
     | 
| 
       307 
     | 
    
         
            -
                      formatter.long_operation_running
         
     | 
| 
       308 
     | 
    
         
            -
                    end
         
     | 
| 
       309 
     | 
    
         
            -
                    formatter.long_operation_terminated
         
     | 
| 
       310 
     | 
    
         
            -
                    return result, total_count
         
     | 
| 
       311 
     | 
    
         
            -
                  end
         
     | 
| 
       312 
     | 
    
         
            -
             
     | 
| 
       313 
     | 
    
         
            -
                  # Lookup an entity id from its name
         
     | 
| 
       314 
     | 
    
         
            -
                  # @param entity    [String] the type of entity to lookup, by default it is the path, and it is also the field name in result
         
     | 
| 
       315 
     | 
    
         
            -
                  # @param value     [String] the value to lookup
         
     | 
| 
       316 
     | 
    
         
            -
                  # @param field     [String] the field to match, by default it is 'name'
         
     | 
| 
       317 
     | 
    
         
            -
                  # @param items_key [String] key in the result to get the list of items (override entity)
         
     | 
| 
       318 
     | 
    
         
            -
                  # @param query     [Hash]   additional query parameters
         
     | 
| 
       319 
     | 
    
         
            -
                  def lookup_entity_by_field(api:, entity:, value:, field: 'name', items_key: nil, query: :default)
         
     | 
| 
       320 
     | 
    
         
            -
                    if query.eql?(:default)
         
     | 
| 
       321 
     | 
    
         
            -
                      Aspera.assert(field.eql?('name')){'Default query is on name only'}
         
     | 
| 
       322 
     | 
    
         
            -
                      query = {'q'=> value}
         
     | 
| 
       323 
     | 
    
         
            -
                    end
         
     | 
| 
       324 
     | 
    
         
            -
                    found = list_entities_limit_offset_total_count(api: api, entity: entity, items_key: items_key, query: query).first.select{ |i| i[field].eql?(value)}
         
     | 
| 
       325 
     | 
    
         
            -
                    case found.length
         
     | 
| 
       326 
     | 
    
         
            -
                    when 0 then raise "No #{entity} with #{field} = #{value}"
         
     | 
| 
       327 
     | 
    
         
            -
                    when 1 then return found.first
         
     | 
| 
       328 
     | 
    
         
            -
                    else raise "Found #{found.length} #{entity} with #{field} = #{value}"
         
     | 
| 
       329 
     | 
    
         
            -
                    end
         
     | 
| 
       330 
     | 
    
         
            -
                  end
         
     | 
| 
       331 
     | 
    
         
            -
                end
         
     | 
| 
       332 
     | 
    
         
            -
              end
         
     | 
| 
       333 
     | 
    
         
            -
            end
         
     |