aspera-cli 4.19.0 → 4.20.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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +20 -0
  4. data/CONTRIBUTING.md +16 -4
  5. data/README.md +344 -164
  6. data/bin/asession +26 -19
  7. data/examples/build_exec +65 -76
  8. data/examples/build_exec_rubyc +40 -0
  9. data/examples/get_proto_file.rb +7 -0
  10. data/lib/aspera/agent/alpha.rb +8 -8
  11. data/lib/aspera/agent/base.rb +2 -18
  12. data/lib/aspera/agent/connect.rb +14 -13
  13. data/lib/aspera/agent/direct.rb +23 -24
  14. data/lib/aspera/agent/httpgw.rb +2 -3
  15. data/lib/aspera/agent/node.rb +10 -10
  16. data/lib/aspera/agent/trsdk.rb +17 -20
  17. data/lib/aspera/api/alee.rb +15 -0
  18. data/lib/aspera/api/aoc.rb +126 -97
  19. data/lib/aspera/api/ats.rb +1 -1
  20. data/lib/aspera/api/cos_node.rb +1 -1
  21. data/lib/aspera/api/httpgw.rb +15 -10
  22. data/lib/aspera/api/node.rb +33 -12
  23. data/lib/aspera/ascmd.rb +56 -48
  24. data/lib/aspera/ascp/installation.rb +99 -42
  25. data/lib/aspera/ascp/management.rb +3 -2
  26. data/lib/aspera/ascp/products.rb +12 -0
  27. data/lib/aspera/assert.rb +10 -5
  28. data/lib/aspera/cli/formatter.rb +27 -17
  29. data/lib/aspera/cli/hints.rb +2 -1
  30. data/lib/aspera/cli/info.rb +12 -10
  31. data/lib/aspera/cli/main.rb +16 -13
  32. data/lib/aspera/cli/manager.rb +5 -0
  33. data/lib/aspera/cli/plugin.rb +15 -29
  34. data/lib/aspera/cli/plugins/alee.rb +3 -3
  35. data/lib/aspera/cli/plugins/aoc.rb +222 -194
  36. data/lib/aspera/cli/plugins/ats.rb +16 -14
  37. data/lib/aspera/cli/plugins/config.rb +53 -45
  38. data/lib/aspera/cli/plugins/console.rb +3 -3
  39. data/lib/aspera/cli/plugins/faspex.rb +11 -21
  40. data/lib/aspera/cli/plugins/faspex5.rb +44 -42
  41. data/lib/aspera/cli/plugins/faspio.rb +2 -2
  42. data/lib/aspera/cli/plugins/httpgw.rb +1 -1
  43. data/lib/aspera/cli/plugins/node.rb +153 -95
  44. data/lib/aspera/cli/plugins/orchestrator.rb +14 -13
  45. data/lib/aspera/cli/plugins/preview.rb +8 -9
  46. data/lib/aspera/cli/plugins/server.rb +5 -9
  47. data/lib/aspera/cli/plugins/shares.rb +2 -2
  48. data/lib/aspera/cli/sync_actions.rb +2 -2
  49. data/lib/aspera/cli/transfer_agent.rb +12 -14
  50. data/lib/aspera/cli/transfer_progress.rb +35 -17
  51. data/lib/aspera/cli/version.rb +1 -1
  52. data/lib/aspera/command_line_builder.rb +3 -4
  53. data/lib/aspera/coverage.rb +13 -1
  54. data/lib/aspera/environment.rb +34 -18
  55. data/lib/aspera/faspex_gw.rb +2 -2
  56. data/lib/aspera/json_rpc.rb +1 -1
  57. data/lib/aspera/keychain/macos_security.rb +7 -12
  58. data/lib/aspera/log.rb +3 -4
  59. data/lib/aspera/oauth/base.rb +39 -45
  60. data/lib/aspera/oauth/factory.rb +11 -4
  61. data/lib/aspera/oauth/generic.rb +4 -8
  62. data/lib/aspera/oauth/jwt.rb +3 -3
  63. data/lib/aspera/oauth/url_json.rb +1 -2
  64. data/lib/aspera/oauth/web.rb +5 -2
  65. data/lib/aspera/persistency_action_once.rb +16 -8
  66. data/lib/aspera/preview/utils.rb +5 -16
  67. data/lib/aspera/rest.rb +100 -76
  68. data/lib/aspera/transfer/faux_file.rb +4 -4
  69. data/lib/aspera/transfer/parameters.rb +14 -16
  70. data/lib/aspera/transfer/spec.rb +12 -12
  71. data/lib/aspera/transfer/sync.rb +1 -5
  72. data/lib/aspera/transfer/uri.rb +1 -1
  73. data/lib/aspera/uri_reader.rb +1 -1
  74. data/lib/aspera/web_auth.rb +166 -17
  75. data/lib/aspera/web_server_simple.rb +4 -3
  76. data/lib/transfer_pb.rb +84 -0
  77. data/lib/transfer_services_pb.rb +82 -0
  78. data.tar.gz.sig +0 -0
  79. metadata +24 -5
  80. metadata.gz.sig +0 -0
data/bin/asession CHANGED
@@ -1,20 +1,24 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- # Laurent Martin/2017
5
- $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib")
4
+ gem_lib_folder = File.join(File.dirname(File.dirname(File.realpath(__FILE__))), 'lib')
5
+ Kernel.load(File.join(gem_lib_folder, 'aspera/coverage.rb'))
6
+ $LOAD_PATH.unshift(gem_lib_folder)
6
7
  require 'aspera/agent/direct'
7
8
  require 'aspera/cli/extended_value'
8
9
  require 'aspera/ascp/installation'
9
10
  require 'aspera/log'
10
11
  require 'json'
11
12
  # extended transfer spec parameter (only used in asession)
12
- # Change log level
13
+ PARAM_SPEC = 'spec'
14
+ # log level
13
15
  PARAM_LOG_LEVEL = 'loglevel'
16
+ # transfer agent options
17
+ PARAM_AGENT = 'agent'
14
18
  # by default go to /tmp/username.filelist
15
19
  PARAM_TMP_FILE_LIST_FOLDER = 'file_list_folder'
20
+ PARAM_SDK = 'sdk'
16
21
  # place transfer spec in that
17
- PARAM_SPEC = 'spec'
18
22
  SAMPLE_DEMO = '"remote_host":"demo.asperasoft.com","remote_user":"asperaweb","ssh_port":33001,"remote_password":"demoaspera"'
19
23
  SAMPLE_DEMO2 = '"direction":"receive","destination_root":"./test.dir"'
20
24
  def assert_usage(assertion, error_message)
@@ -23,28 +27,30 @@ def assert_usage(assertion, error_message)
23
27
  $stderr.puts('USAGE')
24
28
  $stderr.puts(' asession')
25
29
  $stderr.puts(' asession -h|--help')
26
- $stderr.puts(' asession <session spec extended value>')
30
+ $stderr.puts(' asession [<session spec extended value>]')
27
31
  $stderr.puts(' ')
28
32
  $stderr.puts(' If no argument is provided, default will be used: @json:@stdin')
29
33
  $stderr.puts(' -h, --help display this message')
30
- $stderr.puts(' <session spec extended value> a dictionary value (Hash)')
34
+ $stderr.puts(' <session spec extended value> a dictionary (Hash)')
31
35
  $stderr.puts(' The value can be either:')
32
36
  $stderr.puts(" the JSON description itself, e.g. @json:'{\"xx\":\"yy\",...}'")
33
37
  $stderr.puts(' @json:@stdin, if the JSON is provided from stdin')
34
38
  $stderr.puts(' @json:@file:<path>, if the JSON is provided from a file')
35
- $stderr.puts(" Parameter #{PARAM_SPEC} is mandatory, it contains the transfer spec")
39
+ $stderr.puts(' The following keys are recognized in session spec:')
40
+ $stderr.puts(" #{PARAM_SPEC} : mandatory, contains the transfer spec")
41
+ $stderr.puts(" #{PARAM_LOG_LEVEL} : modify log level (to stderr)")
42
+ $stderr.puts(" #{PARAM_AGENT} : modify transfer agent parameters, e.g. ascp_args")
43
+ $stderr.puts(" #{PARAM_TMP_FILE_LIST_FOLDER} : location of temporary files")
44
+ $stderr.puts(" #{PARAM_SDK} : location of SDK (ascp)")
36
45
  $stderr.puts(' Asynchronous commands can be provided on STDIN, examples:')
37
46
  $stderr.puts(' {"type":"START","source":"/aspera-test-dir-tiny/200KB.2"}')
38
47
  $stderr.puts(' {"type":"START","source":"xx","destination":"yy"}')
39
48
  $stderr.puts(' {"type":"DONE"}')
40
- $stderr.puts(%Q(Note: debug information can be placed on STDERR, using the "#{PARAM_LOG_LEVEL}" parameter in session spec (debug=0)))
41
49
  $stderr.puts('EXAMPLES')
42
50
  $stderr.puts(%Q( asession @json:'{"#{PARAM_SPEC}":{#{SAMPLE_DEMO},#{SAMPLE_DEMO2},"paths":[{"source":"/aspera-test-dir-tiny/200KB.1"}]}}'))
43
51
  $stderr.puts(%Q( echo '{"#{PARAM_SPEC}":{"remote_host":...}}'|asession @json:@stdin))
44
52
  Process.exit(0)
45
53
  end
46
- Aspera::Ascp::Installation.instance.sdk_folder = File.join(Dir.home, '.aspera', 'sdk')
47
-
48
54
  parameter_source_err_msg = ' (argument), did you specify: "@json:" ?'
49
55
  # by default assume JSON input on stdin if no argument
50
56
  if ARGV.empty?
@@ -62,23 +68,24 @@ rescue
62
68
  assert_usage(false, "Cannot parse argument: #{session_argument}")
63
69
  end
64
70
  # ensure right type
65
- assert_usage(session_spec.is_a?(Hash), "The value must be a hash table#{parameter_source_err_msg}")
66
- assert_usage(session_spec[PARAM_SPEC].is_a?(Hash), "the value must contain key #{PARAM_SPEC}")
71
+ assert_usage(session_spec.is_a?(Hash), "The value must be a Hash#{parameter_source_err_msg}")
72
+ assert_usage(session_spec[PARAM_SPEC].is_a?(Hash), "The value must contain key #{PARAM_SPEC} with Hash value")
67
73
  # additional debug capability
68
- if session_spec.key?(PARAM_LOG_LEVEL)
69
- Aspera::Log.instance.level = session_spec[PARAM_LOG_LEVEL]
70
- end
74
+ Aspera::Log.instance.level = session_spec[PARAM_LOG_LEVEL] if session_spec.key?(PARAM_LOG_LEVEL)
71
75
  # possibly override temp folder
72
76
  if session_spec.key?(PARAM_TMP_FILE_LIST_FOLDER)
73
77
  Aspera::Transfer::Parameters.file_list_folder = session_spec[PARAM_TMP_FILE_LIST_FOLDER]
74
78
  end
75
- session_spec['agent'] = {} unless session_spec.key?('agent')
76
- session_spec['agent']['quiet'] = true
77
- session_spec['agent']['management_cb'] = ->(event) do
79
+ session_spec[PARAM_SDK] = File.join(Dir.home, '.aspera', 'sdk') unless session_spec.key?(PARAM_SDK)
80
+ Aspera::Ascp::Installation.instance.sdk_folder = session_spec[PARAM_SDK]
81
+ session_spec[PARAM_AGENT] = {} unless session_spec.key?(PARAM_AGENT)
82
+ agent_params = session_spec[PARAM_AGENT]
83
+ agent_params['quiet'] = true
84
+ agent_params['management_cb'] = ->(event) do
78
85
  puts JSON.generate(Aspera::Ascp::Management.enhanced_event_format(event))
79
86
  end
80
87
  # get local agent (ascp), disable ascp output on stdout to not mix with JSON events
81
- client = Aspera::Agent::Direct.new(**session_spec['agent'].symbolize_keys)
88
+ client = Aspera::Agent::Direct.new(**agent_params.symbolize_keys)
82
89
  # start transfer (asynchronous)
83
90
  job_id = client.start_transfer(session_spec[PARAM_SPEC])
84
91
  # async commands
data/examples/build_exec CHANGED
@@ -1,85 +1,74 @@
1
1
  #!/bin/bash
2
-
2
+ # Glibc for various OS: https://gist.github.com/wagenet/35adca1a032cec2999d47b6c40aa45b1
3
+ # https://distrowatch.com/table.php?distribution=redhat
4
+ # RHEL 8 : glibc 2.28
5
+ # RHEL 9 : glibc 2.34
6
+ # https://distrowatch.com/table.php?distribution=ubuntu
7
+ # Ubuntu 18.10 cosmic : glibc 2.28
8
+ # Ubuntu 21.10 impish : gblic 2.34
9
+ # https://www.ibm.com/docs/en/ahts/4.4.x?topic=release-notes
10
+ # ascp 4.4.5 : gblic 2.28
11
+ # dwarfs requires boost >= 1.65
12
+ # boost requires cmake >= 3.30
3
13
  set -e
4
14
 
5
- if test $# -ne 2; then
6
- echo "Usage: $0 <CLI_TARGET_EXECUTABLE> <CLI_ENTRY_SCRIPT>" 1>&2
15
+ if test $# -ne 5; then
16
+ echo "Usage: $0 <CLI_EXECUTABLE> <CLI_PATH> <GEM_NAME> <GEM_VERSION> <DIR_TMP>" 1>&2
7
17
  exit 1
8
18
  fi
9
19
 
10
- CLI_TARGET_EXECUTABLE=$1
11
- CLI_ENTRY_SCRIPT=$(realpath $2)
12
- CLI_EXEC_NAME=$(basename $CLI_TARGET_EXECUTABLE)
13
- CLI_ROOT=$(dirname $(dirname $CLI_ENTRY_SCRIPT))
20
+ CLI_EXECUTABLE=$1
21
+ CLI_PATH=$(realpath $2)
22
+ GEM_NAME=$3
23
+ GEM_VERSION=$4
24
+ DIR_TMP=$(realpath $5)
14
25
 
15
- echo "Project folder: $CLI_ROOT"
16
- echo "Executable: $CLI_TARGET_EXECUTABLE"
17
- echo "Exec Name: $CLI_EXEC_NAME"
18
- echo "Entry: $CLI_ENTRY_SCRIPT"
26
+ echo "Building: $(basename $CLI_EXECUTABLE)"
19
27
 
20
- # tebako press --root=$(TB_WORK_DIR) --entry-point=ascli --output=$(TB_WORK_DIR)/$(CLI_TARGET_EXECUTABLE) --Ruby=3.2.4
28
+ # tebako compilation
29
+ tebako_env=$DIR_TMP/tebako-env
30
+ # project files (gem)
31
+ tebako_root=$DIR_TMP/tebako-root
32
+ # only provide the name, not path
33
+ tebako_entry=$(basename $CLI_PATH)
34
+ tebako_output=$CLI_EXECUTABLE
21
35
 
22
- if true;then
23
- tebako_command=tebako
24
- tebako_args="--root=$CLI_ROOT --entry-point=ascli --output=$CLI_TARGET_EXECUTABLE --Ruby=3.3.3"
25
- case $(uname -s) in
26
- Darwin)
27
- brew update
28
- brew install gnu-sed bash pkg-config bison flex binutils libffi gdbm zlib \
29
- ncurses double-conversion boost jemalloc glog libevent libsodium lz4 xz \
30
- libyaml openssl@3
31
- # brew install m4
32
- # boost fmt
33
- #export PATH=$(dirname $(brew ls m4|grep '/m4$'|head -n 1)):$PATH
34
- #export PATH=$(dirname $(brew ls binutils|grep '/ar$'|head -n 1)):$PATH
35
- #tebako_bin=$CLI_ROOT/tmp/tbkbin
36
- tebako_root=$CLI_ROOT/../tebako-tmp
37
- #export PATH=$tebako_bin:$PATH
38
- mkdir -p $tebako_root
39
- #mkdir -p $tebako_bin
40
- # need ar from apple
41
- #rm -f $tebako_bin/ar
42
- #ln -s /usr/bin/ar $tebako_bin
43
- export PATH=$(echo $PATH|tr : \\n|grep -v /binutils/|tr \\n :)
44
- #tebako setup --Ruby=3.3.4 --prefix=$tebako_root
45
- tebako press --Ruby=3.3.4 --prefix=$tebako_root --root=$CLI_ROOT/examples/tebako --entry-point=ascli --output=$CLI_TARGET_EXECUTABLE
46
- #tebako press --Ruby=3.3.4 --prefix=$tebako_root --root=$CLI_ROOT --entry-point=$CLI_ENTRY_SCRIPT --output=$CLI_TARGET_EXECUTABLE
47
- exit 0
48
- ;;
49
- Linux)
50
- work_dir=/mnt/w
51
- tebako press --root=$work_dir --entry-point=ascli --output=$work_dir/ascli.exe --Ruby=3.3.3
52
- tebako_prefix="podman run -it --rm -v $PWD:$work_dir ghcr.io/tamatebako/tebako-ubuntu-20.04:0.8.6"
53
- tebako_opts=--patchelf
54
- ;;
55
- *)
56
- echo "This OS is not supported." >&2
57
- exit 1
58
- ;;
59
- esac
60
- command $tebako_command $tebako_args
61
- else
62
- # https://github.com/you54f/ruby-packer
63
- # https://github.com/YOU54F/ruby-packer/releases
64
- set -e
65
- FOLDER="$(dirname $0)/../tmp"
66
- RUBYC="$FOLDER/rubyc"
67
- if test ! -e "$RUBYC"; then
68
- mkdir -p "$FOLDER"
69
- case $(uname -sm|tr ' ' -) in
70
- Darwin-arm64)
71
- curl -L https://github.com/YOU54F/ruby-packer/releases/download/rel-20230812/rubyc-Darwin-arm64.tar.gz | tar -xz -C "$FOLDER"
72
- mv "$FOLDER/rubyc-Darwin-arm64" "$RUBYC"
73
- ;;
74
- Linux-x86_64)
75
- curl -L https://github.com/YOU54F/ruby-packer/releases/download/rel-20230812/rubyc-Linux-x86_64.tar.gz | tar -xz -C "$FOLDER"
76
- mv "$FOLDER/rubyc-Linux-x86_64" "$RUBYC"
77
- ;;
78
- *)
79
- echo "This architecture is not supported." >&2
80
- exit 1
81
- ;;
82
- esac
83
- fi
84
- exec "$RUBYC" -o "$CLI_TARGET_EXECUTABLE" "$CLI_ENTRY_SCRIPT"
85
- fi
36
+ container_tag=alpine-3.17
37
+ #container_tag=ubuntu-20.04
38
+
39
+ gem install tebako
40
+ mkdir -p $tebako_env $tebako_root
41
+ (cd $tebako_root && gem fetch $GEM_NAME:$GEM_VERSION)
42
+ case $(uname -s) in
43
+ Darwin)
44
+ brew update
45
+ # install tools
46
+ brew install bash binutils bison flex gnu-sed lz4 pkg-config xz
47
+ # install libs
48
+ brew install boost double-conversion fmt gdbm glog jemalloc libevent libffi libsodium libyaml ncurses openssl@3 zlib
49
+ # make sure tools are reachable
50
+ export PATH=/opt/homebrew/opt/flex/bin:/opt/homebrew/opt/bison/bin:$PATH
51
+ # remove binutils from path so that macos `ar` is used
52
+ export PATH=$(echo $PATH|tr : \\n|grep -v /binutils/|tr \\n :)
53
+ ;;
54
+ Linux)
55
+ tebako_root=/mnt/w
56
+ tebako_prefix="podman run -it --rm -v $PWD:$tebako_root ghcr.io/tamatebako/tebako-${container_tag}:0.8.6"
57
+ tebako_opts=--patchelf
58
+ tebako_output=$tebako_root/$(basename $CLI_EXECUTABLE)
59
+ ;;
60
+ LinuxLocal)
61
+ dnf module reset ruby
62
+ dnf module install ruby:3.3
63
+ dnf install -y cmake git bash sudo autoconf boost-devel flex bison make clang binutils-devel libevent-devel libacl-devel sed python3 pkgconfig curl lz4-devel openssl-devel zlib-devel xz zip unzip tar xz-devel elfutils-devel libffi-devel gdbm-devel ncurses-devel readline-devel ruby-devel gettext-devel brotli-devel clang libxslt-devel
64
+ echo TODO
65
+ exit 1
66
+ dnf install
67
+ ;;
68
+ *)
69
+ echo "This OS is not supported." >&2
70
+ exit 1
71
+ ;;
72
+ esac
73
+ set -x
74
+ exec $tebako_prefix tebako press --root=$tebako_root --entry-point=$tebako_entry --output=$tebako_output --prefix=$tebako_env $tebako_opts
@@ -0,0 +1,40 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ if test $# -ne 5; then
6
+ echo "Usage: $0 <CLI_EXECUTABLE> <CLI_PATH> <GEM_NAME> <GEM_VERSION> <DIR_TMP>" 1>&2
7
+ exit 1
8
+ fi
9
+
10
+ CLI_EXECUTABLE=$1
11
+ CLI_PATH=$(realpath $2)
12
+ GEM_NAME=$3
13
+ GEM_VERSION=$4
14
+ DIR_TMP=$(realpath $5)
15
+
16
+ echo "Building: $(basename $CLI_EXECUTABLE)"
17
+
18
+ # https://github.com/you54f/ruby-packer
19
+ # https://github.com/you54f/ruby-packer/releases
20
+ set -e
21
+ FOLDER="$(dirname $0)/../tmp"
22
+ RUBYC="$FOLDER/rubyc"
23
+ if test ! -e "$RUBYC"; then
24
+ mkdir -p "$FOLDER"
25
+ case $(uname -sm|tr ' ' -) in
26
+ Darwin-arm64)
27
+ curl -L https://github.com/YOU54F/ruby-packer/releases/download/rel-20230812/rubyc-Darwin-arm64.tar.gz | tar -xz -C "$FOLDER"
28
+ mv "$FOLDER/rubyc-Darwin-arm64" "$RUBYC"
29
+ ;;
30
+ Linux-x86_64)
31
+ curl -L https://github.com/YOU54F/ruby-packer/releases/download/rel-20230812/rubyc-Linux-x86_64.tar.gz | tar -xz -C "$FOLDER"
32
+ mv "$FOLDER/rubyc-Linux-x86_64" "$RUBYC"
33
+ ;;
34
+ *)
35
+ echo "This architecture is not supported." >&2
36
+ exit 1
37
+ ;;
38
+ esac
39
+ fi
40
+ exec "$RUBYC" -o "$CLI_EXECUTABLE" "$CLI_PATH"
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Retrieve `transfer.proto` from the web
5
+ $LOAD_PATH.unshift(File.join(File.dirname(File.dirname(File.realpath(__FILE__))), 'lib'))
6
+ require 'aspera/ascp/installation'
7
+ Aspera::Ascp::Installation.instance.install_sdk(folder: ARGV.first, backup: false, with_exe: false) {|name| '/' if name.end_with?('transfer.proto')}
@@ -82,29 +82,29 @@ module Aspera
82
82
  transfer = @client_app_api.get_transfer(app_id: @application_id, transfer_id: @xfer_id)
83
83
  case transfer['status']
84
84
  when 'initiating', 'queued'
85
- notify_progress(session_id: nil, type: :pre_start, info: transfer['status'])
85
+ notify_progress(:pre_start, session_id: nil, info: transfer['status'])
86
86
  when 'running'
87
87
  if !started
88
- notify_progress(session_id: @xfer_id, type: :session_start)
88
+ notify_progress(:session_start, session_id: @xfer_id)
89
89
  started = true
90
90
  end
91
91
  if !pre_calc && (transfer['bytes_expected'] != 0)
92
- notify_progress(type: :session_size, session_id: @xfer_id, info: transfer['bytes_expected'])
92
+ notify_progress(:session_size, session_id: @xfer_id, info: transfer['bytes_expected'])
93
93
  pre_calc = true
94
94
  else
95
- notify_progress(type: :transfer, session_id: @xfer_id, info: transfer['bytes_written'])
95
+ notify_progress(:transfer, session_id: @xfer_id, info: transfer['bytes_written'])
96
96
  end
97
97
  when 'completed'
98
- notify_progress(type: :end, session_id: @xfer_id)
98
+ notify_progress(:end, session_id: @xfer_id)
99
99
  break
100
100
  when 'failed'
101
- notify_progress(type: :end, session_id: @xfer_id)
101
+ notify_progress(:end, session_id: @xfer_id)
102
102
  raise Transfer::Error, transfer['error_desc']
103
103
  when 'cancelled'
104
- notify_progress(type: :end, session_id: @xfer_id)
104
+ notify_progress(:end, session_id: @xfer_id)
105
105
  raise Transfer::Error, 'Transfer cancelled by user'
106
106
  else
107
- notify_progress(type: :end, session_id: @xfer_id)
107
+ notify_progress(:end, session_id: @xfer_id)
108
108
  raise Transfer::Error, "unknown status: #{transfer['status']}: #{transfer['error_desc']}"
109
109
  end
110
110
  sleep(1)
@@ -14,22 +14,6 @@ module Aspera
14
14
  Aspera::Agent.const_get(agent.to_s.capitalize).new(**options)
15
15
  end
16
16
 
17
- # compute options from user provided and default options
18
- def to_move_options(default:, options:)
19
- result = options.symbolize_keys
20
- available = default.map{|k, v|"#{k}(#{v})"}.join(', ')
21
- result.each_key do |k|
22
- Aspera.assert_values(k, default.keys){"transfer agent parameter: #{k}"}
23
- # check it is the expected type: too limiting, as we can have an Integer or Float, or symbol and string
24
- # raise "Invalid value for transfer agent parameter: #{k}, expect #{default[k].class.name}" unless default[k].nil? || v.is_a?(default[k].class)
25
- end
26
- default.each do |k, v|
27
- raise "Missing required agent parameter: #{k}. Parameters: #{available}" if v.eql?(:required) && !result.key?(k)
28
- result[k] = v unless result.key?(k)
29
- end
30
- return result
31
- end
32
-
33
17
  # discover available agents
34
18
  def agent_list
35
19
  base_class = File.basename(__FILE__)
@@ -58,8 +42,8 @@ module Aspera
58
42
  @progress = progress
59
43
  end
60
44
 
61
- def notify_progress(**parameters)
62
- @progress&.event(**parameters)
45
+ def notify_progress(*pos_args, **kw_args)
46
+ @progress&.event(*pos_args, **kw_args)
63
47
  end
64
48
  end
65
49
  end
@@ -24,11 +24,12 @@ module Aspera
24
24
  Log.log.debug{"found: #{connect_url}"}
25
25
  @connect_api = Rest.new(
26
26
  base_url: "#{connect_url}/v5/connect", # could use v6 also now
27
- headers: {'Origin' => Rest.user_agent})
28
- connect_info = @connect_api.read('info/version')[:data]
27
+ headers: {'Origin' => RestParameters.instance.user_agent})
28
+ connect_info = @connect_api.read('info/version')
29
29
  Log.log.info('Connect was reached') if method_index > 0
30
30
  Log.log.debug{Log.dump(:connect_version, connect_info)}
31
31
  rescue StandardError => e # Errno::ECONNREFUSED
32
+ Log.log.debug{"Exception: #{e}"}
32
33
  start_url = CONNECT_START_URIS[method_index]
33
34
  method_index += 1
34
35
  raise StandardError, "Unable to start connect #{method_index} times" if start_url.nil?
@@ -51,7 +52,7 @@ module Aspera
51
52
  'title' => 'Select Files',
52
53
  'suggestedName' => '',
53
54
  'allowMultipleSelection' => true,
54
- 'allowedFileTypes' => ''})[:data]
55
+ 'allowedFileTypes' => ''})
55
56
  transfer_spec['paths'] = selection['dataTransfer']['files'].map { |i| {'source' => i['name']}}
56
57
  end
57
58
  @request_id = SecureRandom.uuid
@@ -67,7 +68,7 @@ module Aspera
67
68
  'transfer_spec' => transfer_spec
68
69
  }]}
69
70
  # asynchronous anyway
70
- res = @connect_api.create('transfers/start', connect_transfer_args)[:data]
71
+ res = @connect_api.create('transfers/start', connect_transfer_args)
71
72
  @xfer_id = res['transfer_specs'].first['transfer_spec']['tags'][Transfer::Spec::TAG_RESERVED]['xfer_id']
72
73
  end
73
74
 
@@ -78,7 +79,7 @@ module Aspera
78
79
  session_id = @xfer_id
79
80
  begin
80
81
  loop do
81
- tr_info = @connect_api.create("transfers/info/#{@xfer_id}", connect_activity_args)[:data]
82
+ tr_info = @connect_api.create("transfers/info/#{@xfer_id}", connect_activity_args)
82
83
  Log.log.trace1{Log.dump(:tr_info, tr_info)}
83
84
  if tr_info['transfer_info'].is_a?(Hash)
84
85
  transfer = tr_info['transfer_info']
@@ -89,29 +90,29 @@ module Aspera
89
90
  # TODO: get session id
90
91
  case transfer['status']
91
92
  when 'initiating', 'queued'
92
- notify_progress(session_id: nil, type: :pre_start, info: transfer['status'])
93
+ notify_progress(:pre_start, session_id: nil, info: transfer['status'])
93
94
  when 'running'
94
95
  if !started
95
- notify_progress(session_id: session_id, type: :session_start)
96
+ notify_progress(:session_start, session_id: session_id)
96
97
  started = true
97
98
  end
98
99
  if !pre_calc && (transfer['bytes_expected'] != 0)
99
- notify_progress(type: :session_size, session_id: session_id, info: transfer['bytes_expected'])
100
+ notify_progress(:session_size, session_id: session_id, info: transfer['bytes_expected'])
100
101
  pre_calc = true
101
102
  else
102
- notify_progress(type: :transfer, session_id: session_id, info: transfer['bytes_written'])
103
+ notify_progress(:transfer, session_id: session_id, info: transfer['bytes_written'])
103
104
  end
104
105
  when 'completed'
105
- notify_progress(type: :end, session_id: session_id)
106
+ notify_progress(:end, session_id: session_id)
106
107
  break
107
108
  when 'failed'
108
- notify_progress(type: :end, session_id: session_id)
109
+ notify_progress(:end, session_id: session_id)
109
110
  raise Transfer::Error, transfer['error_desc']
110
111
  when 'cancelled'
111
- notify_progress(type: :end, session_id: session_id)
112
+ notify_progress(:end, session_id: session_id)
112
113
  raise Transfer::Error, 'Transfer cancelled by user'
113
114
  else
114
- notify_progress(type: :end, session_id: session_id)
115
+ notify_progress(:end, session_id: session_id)
115
116
  raise Transfer::Error, "unknown status: #{transfer['status']}: #{transfer['error_desc']}"
116
117
  end
117
118
  end
@@ -151,7 +151,7 @@ module Aspera
151
151
  args:
152
152
  )
153
153
  Aspera.assert_type(session, Hash)
154
- notify_progress(session_id: nil, type: :pre_start, info: 'starting')
154
+ notify_progress(:pre_start, session_id: nil, info: 'starting')
155
155
  begin
156
156
  command_pid = nil
157
157
  # we use Socket directly, instead of TCPServer, as it gives access to lower level options
@@ -169,7 +169,7 @@ module Aspera
169
169
  # get location of command executable (ascp, async)
170
170
  command_path = Ascp::Installation.instance.path(name)
171
171
  command_pid = Environment.secure_spawn(env: env, exec: command_path, args: command_arguments)
172
- notify_progress(session_id: nil, type: :pre_start, info: "waiting for #{name} to start")
172
+ notify_progress(:pre_start, session_id: nil, info: "waiting for #{name} to start")
173
173
  mgt_server_socket.listen(1)
174
174
  # TODO: timeout does not work when Process.spawn is used... until process exits, then it works
175
175
  Log.log.debug{"before select, timeout: #{@spawn_timeout_sec}"}
@@ -197,24 +197,23 @@ module Aspera
197
197
  Log.log.error((event['Description']).to_s) if event['Type'].eql?('FILEERROR') # cspell:disable-line
198
198
  end
199
199
  Log.log.debug('management io closed')
200
- last_event = processor.last_event
201
200
  # check that last status was received before process exit
202
- if last_event.is_a?(Hash)
203
- case last_event['Type']
204
- when 'ERROR'
205
- if /bearer token/i.match?(last_event['Description']) &&
206
- session[:token_regenerator].respond_to?(:refreshed_transfer_token)
207
- # regenerate token here, expired, or error on it
208
- # Note: in multi-session, each session will have a different one.
209
- Log.log.warn('Regenerating token for transfer')
210
- env['ASPERA_SCP_TOKEN'] = session[:token_regenerator].refreshed_transfer_token
211
- end
212
- raise Transfer::Error.new(last_event['Description'], last_event['Code'].to_i)
213
- when 'DONE'
214
- nil
215
- else
216
- raise "unexpected last event type: #{last_event['Type']}"
201
+ last_event = processor.last_event
202
+ raise Transfer::Error, "internal: no management event (#{last_event.class})" unless last_event.is_a?(Hash)
203
+ case last_event['Type']
204
+ when 'ERROR'
205
+ if /bearer token/i.match?(last_event['Description']) &&
206
+ session[:token_regenerator].respond_to?(:refreshed_transfer_token)
207
+ # regenerate token here, expired, or error on it
208
+ # Note: in multi-session, each session will have a different one.
209
+ Log.log.warn('Regenerating token for transfer')
210
+ env['ASPERA_SCP_TOKEN'] = session[:token_regenerator].refreshed_transfer_token
217
211
  end
212
+ raise Transfer::Error.new(last_event['Description'], last_event['Code'].to_i)
213
+ when 'DONE'
214
+ nil
215
+ else
216
+ raise Transfer::Error, "unexpected last event type: #{last_event['Type']}, #{last_event['Description']}"
218
217
  end
219
218
  rescue SystemCallError => e
220
219
  # Process.spawn failed, or socket error
@@ -253,24 +252,24 @@ module Aspera
253
252
  when 'INIT'
254
253
  @pre_calc_sent = false
255
254
  @pre_calc_last_size = nil
256
- notify_progress(session_id: session_id, type: :session_start)
255
+ notify_progress(:session_start, session_id: session_id)
257
256
  when 'NOTIFICATION' # sent from remote
258
257
  if event.key?('PreTransferBytes')
259
258
  @pre_calc_sent = true
260
- notify_progress(session_id: session_id, type: :session_size, info: event['PreTransferBytes'])
259
+ notify_progress(:session_size, session_id: session_id, info: event['PreTransferBytes'])
261
260
  end
262
261
  when 'STATS' # during transfer
263
262
  @pre_calc_last_size = event['TransferBytes'].to_i + event['StartByte'].to_i
264
- notify_progress(session_id: session_id, type: :transfer, info: @pre_calc_last_size)
263
+ notify_progress(:transfer, session_id: session_id, info: @pre_calc_last_size)
265
264
  when 'DONE', 'ERROR' # end of session
266
265
  total_size = event['TransferBytes'].to_i + event['StartByte'].to_i
267
266
  if !@pre_calc_sent && !total_size.zero?
268
- notify_progress(session_id: session_id, type: :session_size, info: total_size)
267
+ notify_progress(:session_size, session_id: session_id, info: total_size)
269
268
  end
270
269
  if @pre_calc_last_size != total_size
271
- notify_progress(session_id: session_id, type: :transfer, info: total_size)
270
+ notify_progress(:transfer, session_id: session_id, info: total_size)
272
271
  end
273
- notify_progress(session_id: session_id, type: :end)
272
+ notify_progress(:end, session_id: session_id)
274
273
  # cspell:disable
275
274
  when 'SESSION'
276
275
  when 'ARGSTOP'
@@ -23,8 +23,7 @@ module Aspera
23
23
  @gw_api.upload(transfer_spec)
24
24
  when Transfer::Spec::DIRECTION_RECEIVE
25
25
  @gw_api.download(transfer_spec)
26
- else
27
- raise "unexpected direction: [#{transfer_spec['direction']}]"
26
+ else Aspera.error_unexpected_value(transfer_spec['direction']){'direction'}
28
27
  end
29
28
  end
30
29
 
@@ -54,7 +53,7 @@ module Aspera
54
53
  api_version: api_version,
55
54
  upload_chunk_size: upload_chunk_size,
56
55
  synchronous: synchronous,
57
- notify_cb: ->(**event) { notify_progress(**event) }
56
+ notify_cb: ->(*pa, **ka) { notify_progress(*pa, **ka) }
58
57
  )
59
58
  end
60
59
  end
@@ -78,7 +78,7 @@ module Aspera
78
78
  if !transfer_spec['wss_enabled'] && transfer_spec['remote_host'].eql?(URI.parse(node_api_.base_url).host)
79
79
  transfer_spec['remote_host'] = '127.0.0.1'
80
80
  end
81
- resp = node_api_.create('ops/transfers', transfer_spec)[:data]
81
+ resp = node_api_.create('ops/transfers', transfer_spec)
82
82
  @transfer_id = resp['id']
83
83
  Log.log.debug{"tr_id=#{@transfer_id}"}
84
84
  return @transfer_id
@@ -92,31 +92,31 @@ module Aspera
92
92
  # lets emulate management events to display progress bar
93
93
  loop do
94
94
  # status is empty sometimes with status 200...
95
- transfer_data = node_api_.read("ops/transfers/#{@transfer_id}")[:data] || {'status' => 'unknown'} rescue {'status' => 'waiting(api error)'}
95
+ transfer_data = node_api_.read("ops/transfers/#{@transfer_id}") || {'status' => 'unknown'} rescue {'status' => 'waiting(api error)'}
96
96
  case transfer_data['status']
97
97
  when 'waiting', 'partially_completed', 'unknown', 'waiting(read error)'
98
- notify_progress(session_id: nil, type: :pre_start, info: transfer_data['status'])
98
+ notify_progress(:pre_start, session_id: nil, info: transfer_data['status'])
99
99
  when 'running'
100
100
  if !session_started
101
- notify_progress(session_id: @transfer_id, type: :session_start)
101
+ notify_progress(:session_start, session_id: @transfer_id)
102
102
  session_started = true
103
103
  end
104
104
  message = transfer_data['status']
105
105
  message = "#{message} (#{transfer_data['error_desc']})" if !transfer_data['error_desc']&.empty?
106
- notify_progress(session_id: nil, type: :pre_start, info: message)
106
+ notify_progress(:pre_start, session_id: nil, info: message)
107
107
  if bytes_expected.nil? &&
108
108
  transfer_data['precalc'].is_a?(Hash) &&
109
109
  transfer_data['precalc']['status'].eql?('ready')
110
110
  bytes_expected = transfer_data['precalc']['bytes_expected']
111
- notify_progress(type: :session_size, session_id: @transfer_id, info: bytes_expected)
111
+ notify_progress(:session_size, session_id: @transfer_id, info: bytes_expected)
112
112
  end
113
- notify_progress(type: :transfer, session_id: @transfer_id, info: transfer_data['bytes_transferred'])
113
+ notify_progress(:transfer, session_id: @transfer_id, info: transfer_data['bytes_transferred'])
114
114
  when 'completed'
115
- notify_progress(type: :transfer, session_id: @transfer_id, info: bytes_expected) if bytes_expected
116
- notify_progress(type: :end, session_id: @transfer_id)
115
+ notify_progress(:transfer, session_id: @transfer_id, info: bytes_expected) if bytes_expected
116
+ notify_progress(:end, session_id: @transfer_id)
117
117
  break
118
118
  when 'failed'
119
- notify_progress(type: :end, session_id: @transfer_id)
119
+ notify_progress(:end, session_id: @transfer_id)
120
120
  # Bug in HSTS ? transfer is marked failed, but there is no reason
121
121
  break if transfer_data['error_code'].eql?(0) && transfer_data['error_desc'].empty?
122
122
  raise Transfer::Error, "status: #{transfer_data['status']}. code: #{transfer_data['error_code']}. description: #{transfer_data['error_desc']}"