aspera-cli 4.10.0 → 4.12.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 (97) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/BUGS.md +19 -0
  4. data/CHANGELOG.md +528 -0
  5. data/CONTRIBUTING.md +143 -0
  6. data/README.md +977 -589
  7. data/bin/ascli +4 -4
  8. data/bin/asession +12 -12
  9. data/docs/test_env.conf +29 -19
  10. data/examples/aoc.rb +6 -6
  11. data/examples/dascli +18 -16
  12. data/examples/faspex4.rb +15 -15
  13. data/examples/node.rb +12 -12
  14. data/examples/proxy.pac +2 -2
  15. data/examples/server.rb +12 -12
  16. data/lib/aspera/aoc.rb +344 -272
  17. data/lib/aspera/ascmd.rb +56 -54
  18. data/lib/aspera/ats_api.rb +4 -4
  19. data/lib/aspera/cli/basic_auth_plugin.rb +15 -12
  20. data/lib/aspera/cli/extended_value.rb +9 -9
  21. data/lib/aspera/cli/{formater.rb → formatter.rb} +69 -69
  22. data/lib/aspera/cli/listener/line_dump.rb +1 -1
  23. data/lib/aspera/cli/listener/logger.rb +1 -1
  24. data/lib/aspera/cli/listener/progress.rb +5 -6
  25. data/lib/aspera/cli/listener/progress_multi.rb +16 -21
  26. data/lib/aspera/cli/main.rb +72 -73
  27. data/lib/aspera/cli/manager.rb +112 -112
  28. data/lib/aspera/cli/plugin.rb +68 -48
  29. data/lib/aspera/cli/plugins/alee.rb +4 -4
  30. data/lib/aspera/cli/plugins/aoc.rb +322 -720
  31. data/lib/aspera/cli/plugins/ats.rb +50 -52
  32. data/lib/aspera/cli/plugins/bss.rb +10 -10
  33. data/lib/aspera/cli/plugins/config.rb +514 -410
  34. data/lib/aspera/cli/plugins/console.rb +12 -12
  35. data/lib/aspera/cli/plugins/cos.rb +18 -20
  36. data/lib/aspera/cli/plugins/faspex.rb +134 -136
  37. data/lib/aspera/cli/plugins/faspex5.rb +235 -70
  38. data/lib/aspera/cli/plugins/node.rb +378 -309
  39. data/lib/aspera/cli/plugins/orchestrator.rb +52 -49
  40. data/lib/aspera/cli/plugins/preview.rb +129 -120
  41. data/lib/aspera/cli/plugins/server.rb +137 -83
  42. data/lib/aspera/cli/plugins/shares.rb +77 -52
  43. data/lib/aspera/cli/plugins/sync.rb +13 -33
  44. data/lib/aspera/cli/transfer_agent.rb +61 -61
  45. data/lib/aspera/cli/version.rb +2 -1
  46. data/lib/aspera/colors.rb +3 -3
  47. data/lib/aspera/command_line_builder.rb +78 -74
  48. data/lib/aspera/cos_node.rb +31 -29
  49. data/lib/aspera/data_repository.rb +1 -1
  50. data/lib/aspera/environment.rb +30 -28
  51. data/lib/aspera/fasp/agent_base.rb +17 -15
  52. data/lib/aspera/fasp/agent_connect.rb +34 -32
  53. data/lib/aspera/fasp/agent_direct.rb +70 -73
  54. data/lib/aspera/fasp/agent_httpgw.rb +79 -74
  55. data/lib/aspera/fasp/agent_node.rb +26 -26
  56. data/lib/aspera/fasp/agent_trsdk.rb +20 -20
  57. data/lib/aspera/fasp/error.rb +3 -2
  58. data/lib/aspera/fasp/error_info.rb +11 -8
  59. data/lib/aspera/fasp/installation.rb +80 -80
  60. data/lib/aspera/fasp/listener.rb +2 -2
  61. data/lib/aspera/fasp/parameters.rb +103 -92
  62. data/lib/aspera/fasp/parameters.yaml +313 -214
  63. data/lib/aspera/fasp/resume_policy.rb +10 -10
  64. data/lib/aspera/fasp/transfer_spec.rb +22 -2
  65. data/lib/aspera/fasp/uri.rb +7 -7
  66. data/lib/aspera/faspex_gw.rb +80 -159
  67. data/lib/aspera/faspex_postproc.rb +77 -0
  68. data/lib/aspera/hash_ext.rb +3 -3
  69. data/lib/aspera/id_generator.rb +5 -5
  70. data/lib/aspera/keychain/encrypted_hash.rb +23 -28
  71. data/lib/aspera/keychain/macos_security.rb +21 -20
  72. data/lib/aspera/log.rb +13 -13
  73. data/lib/aspera/nagios.rb +24 -23
  74. data/lib/aspera/node.rb +217 -38
  75. data/lib/aspera/oauth.rb +78 -74
  76. data/lib/aspera/open_application.rb +19 -11
  77. data/lib/aspera/persistency_action_once.rb +4 -4
  78. data/lib/aspera/persistency_folder.rb +13 -13
  79. data/lib/aspera/preview/file_types.rb +8 -8
  80. data/lib/aspera/preview/generator.rb +67 -67
  81. data/lib/aspera/preview/utils.rb +27 -27
  82. data/lib/aspera/proxy_auto_config.js +63 -63
  83. data/lib/aspera/proxy_auto_config.rb +19 -19
  84. data/lib/aspera/rest.rb +65 -67
  85. data/lib/aspera/rest_call_error.rb +2 -1
  86. data/lib/aspera/rest_error_analyzer.rb +22 -21
  87. data/lib/aspera/rest_errors_aspera.rb +16 -16
  88. data/lib/aspera/secret_hider.rb +17 -14
  89. data/lib/aspera/ssh.rb +15 -14
  90. data/lib/aspera/sync.rb +177 -62
  91. data/lib/aspera/temp_file_manager.rb +2 -2
  92. data/lib/aspera/uri_reader.rb +4 -4
  93. data/lib/aspera/web_auth.rb +13 -64
  94. data/lib/aspera/web_server_simple.rb +76 -0
  95. data.tar.gz.sig +0 -0
  96. metadata +11 -6
  97. metadata.gz.sig +0 -0
@@ -1,98 +1,150 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'aspera/cli/basic_auth_plugin'
4
+ require 'aspera/cli/plugins/sync'
4
5
  require 'aspera/ascmd'
5
6
  require 'aspera/fasp/transfer_spec'
6
7
  require 'aspera/ssh'
7
8
  require 'aspera/nagios'
8
9
  require 'tempfile'
10
+ require 'open3'
9
11
 
10
12
  module Aspera
11
13
  module Cli
12
14
  module Plugins
13
15
  # implement basic remote access with FASP/SSH
14
- class Server < BasicAuthPlugin
16
+ class Server < Aspera::Cli::BasicAuthPlugin
17
+ SSH_SCHEME = 'ssh'
18
+ URI_SCHEMES = %w[https local].push(SSH_SCHEME).freeze
19
+ ASCMD_ALIASES = {
20
+ browse: :ls,
21
+ delete: :rm,
22
+ rename: :mv
23
+ }.freeze
24
+ TRANSFER_COMMANDS = %i[sync upload download].freeze
25
+
26
+ private_constant :SSH_SCHEME, :URI_SCHEMES, :ASCMD_ALIASES, :TRANSFER_COMMANDS
27
+
15
28
  class LocalExecutor
16
- def execute(cmd,_input=nil)
17
- Log.log.debug("Executing: #{cmd}")
18
- %x(#{cmd.join(' ')})
29
+ def execute(cmd, line)
30
+ # concatenate arguments, enclose in double quotes
31
+ cmd = cmd.map{|v|%Q("#{v}")}.join(' ') if cmd.is_a?(Array)
32
+ Log.log.debug{"Executing: #{cmd} with '#{line}'"}
33
+ stdout_str, stderr_str, status = Open3.capture3(cmd, stdin_data: line, binmode: true)
34
+ Log.log.debug(">> #{status} -> #{stderr_str}")
35
+ raise "command #{cmd} failed with code #{status.exitstatus} #{stderr_str}" unless status.success?
36
+ return stdout_str
19
37
  end
20
38
  end
21
39
 
22
40
  def initialize(env)
23
41
  super(env)
24
- options.add_opt_simple(:ssh_keys,'SSH key path list (Array or single)')
25
- options.add_opt_simple(:ssh_options,'SSH options (Hash)')
26
- options.set_option(:ssh_keys,[])
27
- options.set_option(:ssh_options,{})
42
+ options.add_opt_simple(:ssh_keys, 'SSH key path list (Array or single)')
43
+ options.add_opt_simple(:ssh_options, 'SSH options (Hash)')
28
44
  options.parse_options!
45
+ @ssh_opts = nil
29
46
  end
30
47
 
31
- def key_symb_to_str_list(source)
32
- return source.map(&:stringify_keys)
33
- end
34
-
35
- ACTIONS = %i[health download upload browse delete rename].concat(Aspera::AsCmd::OPERATIONS).freeze
36
-
37
- def execute_action
38
- server_uri = URI.parse(options.get_option(:url,is_type: :mandatory))
39
- Log.log.debug("URI : #{server_uri}, port=#{server_uri.port}, scheme:#{server_uri.scheme}")
40
- server_transfer_spec = {'remote_host' => server_uri.hostname}
41
- shell_executor = nil
42
- case server_uri.scheme
43
- when 'local'
44
- shell_executor = LocalExecutor.new
45
- when 'https'
46
- raise 'ERROR: transfer spec with token required' unless transfer.option_transfer_spec['token'].is_a?(String)
48
+ # Read command line options
49
+ # @return [Hash] transfer specification
50
+ def options_to_base_transfer_spec
51
+ url = options.get_option(:url, is_type: :mandatory)
52
+ server_transfer_spec = {}
53
+ server_uri = URI.parse(url)
54
+ Log.log.debug{"URI : #{server_uri}, port=#{server_uri.port}, scheme:#{server_uri.scheme}"}
55
+ server_transfer_spec['remote_host'] = server_uri.hostname
56
+ unless URI_SCHEMES.include?(server_uri.scheme)
57
+ Log.log.warn{"Scheme [#{server_uri.scheme}] not supported in #{url}, use one of: #{URI_SCHEMES.join(', ')}. Defaulting to #{SSH_SCHEME}."}
58
+ server_uri.scheme = SSH_SCHEME
59
+ end
60
+ if server_uri.scheme.eql?('local')
61
+ # Using local execution (mostly for testing)
62
+ return server_transfer_spec
63
+ elsif transfer.option_transfer_spec['token'].is_a?(String) && server_uri.scheme.eql?('https')
47
64
  server_transfer_spec['wss_enabled'] = true
48
65
  server_transfer_spec['wss_port'] = server_uri.port
49
- else # when 'ssh'
50
- Log.log.error("Scheme #{server_uri.scheme} not supported. Assuming SSH.") if !server_uri.scheme.eql?('ssh')
51
- if options.get_option(:username).nil?
52
- options.set_option(:username,Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER)
53
- Log.log.info("Using default transfer user: #{Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER}")
54
- end
55
- server_transfer_spec['remote_user'] = options.get_option(:username,is_type: :mandatory)
56
- ssh_options = options.get_option(:ssh_options)
57
- raise 'expecting a Hash for ssh_options' unless ssh_options.is_a?(Hash)
58
- ssh_options = ssh_options.symbolize_keys
59
- if !server_uri.port.nil?
60
- ssh_options[:port] = server_uri.port
61
- server_transfer_spec['ssh_port'] = server_uri.port
62
- end
63
- cred_set = false
64
- password = options.get_option(:password)
65
- if !password.nil?
66
- ssh_options[:password] = password
67
- server_transfer_spec['remote_password'] = password
68
- cred_set = true
69
- end
70
- ssh_keys = options.get_option(:ssh_keys)
71
- if !ssh_keys.nil?
72
- raise 'expecting single value or array for ssh_keys' unless ssh_keys.is_a?(Array) || ssh_keys.is_a?(String)
73
- ssh_keys = [ssh_keys] if ssh_keys.is_a?(String)
74
- ssh_keys.map!{|p|File.expand_path(p)}
75
- Log.log.debug("ssh keys=#{ssh_keys}")
76
- if !ssh_keys.empty?
77
- ssh_options[:keys] = ssh_keys
78
- server_transfer_spec['EX_ssh_key_paths'] = ssh_keys
79
- ssh_keys.each do |k|
80
- Log.log.warn("no such key file: #{k}") unless File.exist?(k)
81
- end
82
- cred_set = true
66
+ # Using WSS
67
+ return server_transfer_spec
68
+ end
69
+ if !server_uri.scheme.eql?(SSH_SCHEME)
70
+ Log.log.warn('URL scheme is https but no token was provided in transfer spec.')
71
+ Log.log.warn("If you want to access the server, not using WSS for session, then use a URL with scheme \"#{SSH_SCHEME}\" and proper SSH port")
72
+ assumed_url = "#{SSH_SCHEME}://#{server_transfer_spec['remote_host']}:#{Aspera::Fasp::TransferSpec::SSH_PORT}"
73
+ Log.log.warn{"Assuming proper URL is: #{assumed_url}"}
74
+ server_uri = URI.parse(assumed_url)
75
+ end
76
+ # Scheme is SSH
77
+ if options.get_option(:username).nil?
78
+ options.set_option(:username, Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER)
79
+ Log.log.info{"No username provided: Assuming default transfer user: #{Aspera::Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER}"}
80
+ end
81
+ server_transfer_spec['remote_user'] = options.get_option(:username, is_type: :mandatory)
82
+ ssh_args = options.get_option(:ssh_options)
83
+ ssh_args = {} if ssh_args.nil?
84
+ raise 'expecting a Hash for ssh_options' unless ssh_args.is_a?(Hash)
85
+ @ssh_opts = ssh_args.symbolize_keys
86
+ if !server_uri.port.nil?
87
+ @ssh_opts[:port] = server_uri.port
88
+ server_transfer_spec['ssh_port'] = server_uri.port
89
+ end
90
+ cred_set = false
91
+ password = options.get_option(:password)
92
+ if !password.nil?
93
+ @ssh_opts[:password] = password
94
+ server_transfer_spec['remote_password'] = password
95
+ cred_set = true
96
+ end
97
+ ssh_key_list = options.get_option(:ssh_keys)
98
+ if !ssh_key_list.nil?
99
+ raise 'Expecting single value or array for ssh_keys' unless ssh_key_list.is_a?(Array) || ssh_key_list.is_a?(String)
100
+ ssh_key_list = [ssh_key_list] if ssh_key_list.is_a?(String)
101
+ ssh_key_list.map!{|p|File.expand_path(p)}
102
+ Log.log.debug{"SSH keys=#{ssh_key_list}"}
103
+ if !ssh_key_list.empty?
104
+ @ssh_opts[:keys] = ssh_key_list
105
+ server_transfer_spec['EX_ssh_key_paths'] = ssh_key_list
106
+ ssh_key_list.each do |k|
107
+ Log.log.warn{"No such key file: #{k}"} unless File.exist?(k)
83
108
  end
109
+ cred_set = true
84
110
  end
85
- # if user provided transfer spec has a token, we will use by pass keys
86
- cred_set = true if transfer.option_transfer_spec['token'].is_a?(String)
87
- raise 'either password, key , or transfer spec token must be provided' if !cred_set
88
- shell_executor = Ssh.new(server_transfer_spec['remote_host'],server_transfer_spec['remote_user'],ssh_options)
89
111
  end
112
+ # if user provided transfer spec has a token, we will use bypass keys
113
+ cred_set = true if transfer.option_transfer_spec['token'].is_a?(String)
114
+ raise 'Either password, key , or transfer spec token must be provided' if !cred_set
115
+ return server_transfer_spec
116
+ end
117
+
118
+ def execute_transfer(command, transfer_spec)
119
+ case command
120
+ when :upload, :download
121
+ Fasp::TransferSpec.action_to_direction(transfer_spec, command)
122
+ return Main.result_transfer(transfer.start(transfer_spec))
123
+ when :sync
124
+ sync_plugin = Sync.new(@agents, transfer_spec: transfer_spec)
125
+ return sync_plugin.execute_action
126
+ end
127
+ end
90
128
 
91
- # get command and set aliases
92
- command = options.get_next_command(ACTIONS)
93
- command = :ls if command.eql?(:browse)
94
- command = :rm if command.eql?(:delete)
95
- command = :mv if command.eql?(:rename)
129
+ # actions without ascmd
130
+ BASE_ACTIONS = %i[health].concat(TRANSFER_COMMANDS).freeze
131
+ # all actions
132
+ ACTIONS = [BASE_ACTIONS, Aspera::AsCmd::OPERATIONS, ASCMD_ALIASES.keys].flatten.freeze
133
+
134
+ def execute_action
135
+ server_transfer_spec = options_to_base_transfer_spec
136
+ ascmd_executor = if !@ssh_opts.nil?
137
+ Ssh.new(server_transfer_spec['remote_host'], server_transfer_spec['remote_user'], @ssh_opts)
138
+ elsif server_transfer_spec.key?('wss_enabled')
139
+ nil
140
+ else
141
+ LocalExecutor.new
142
+ end
143
+ # the set of available commands depends on SSH executor availability (i.e. no WSS)
144
+ available_commands = ascmd_executor.nil? ? BASE_ACTIONS : ACTIONS
145
+ # get command and translate aliases
146
+ command = options.get_next_command(available_commands)
147
+ command = ASCMD_ALIASES[command] if ASCMD_ALIASES.key?(command)
96
148
  case command
97
149
  when :health
98
150
  nagios = Nagios.new
@@ -107,35 +159,37 @@ module Aspera
107
159
  'direction' => 'send',
108
160
  'cookie' => 'aspera.sync', # hide in console
109
161
  'resume_policy' => 'none',
110
- 'paths' => [{'source' => filepath,'destination' => '.fasping'}]
162
+ 'paths' => [{'source' => filepath, 'destination' => '.fasping'}]
111
163
  })
112
- statuses = transfer.start(probe_ts,{src: :direct})
164
+ statuses = transfer.start(probe_ts)
113
165
  file.unlink
114
166
  if TransferAgent.session_status(statuses).eql?(:success)
115
- nagios.add_ok('transfer','ok')
167
+ nagios.add_ok('transfer', 'ok')
116
168
  else
117
- nagios.add_critical('transfer',statuses.reject{|i|i.eql?(:success)}.first.to_s)
169
+ nagios.add_critical('transfer', statuses.reject{|i|i.eql?(:success)}.first.to_s)
118
170
  end
119
171
  else raise 'ERROR'
120
172
  end
121
173
  return nagios.result
122
- when :upload
123
- return Main.result_transfer(transfer.start(server_transfer_spec.merge('direction' => Fasp::TransferSpec::DIRECTION_SEND),{src: :direct}))
124
- when :download
125
- return Main.result_transfer(transfer.start(server_transfer_spec.merge('direction' => Fasp::TransferSpec::DIRECTION_RECEIVE),{src: :direct}))
174
+ when *TRANSFER_COMMANDS
175
+ return execute_transfer(command, server_transfer_spec)
126
176
  when *Aspera::AsCmd::OPERATIONS
127
- args = options.get_next_argument('ascmd command arguments',expected: :multiple,mandatory: false)
128
- ascmd = Aspera::AsCmd.new(shell_executor)
177
+ args = options.get_next_argument('ascmd command arguments', expected: :multiple, mandatory: false)
178
+ ascmd = Aspera::AsCmd.new(ascmd_executor)
129
179
  begin
130
- result = ascmd.send(:execute_single,command,args)
180
+ result = ascmd.send(:execute_single, command, args)
131
181
  case command
132
- when :mkdir,:mv,:cp,:rm then return Main.result_success
133
- when :ls then return {type: :object_list,data: key_symb_to_str_list(result),fields: %w[zmode zuid zgid size mtime name]}
134
- when :df then return {type: :object_list,data: key_symb_to_str_list(result)}
135
- when :du,:md5sum,:info then return {type: :single_object,data: result.stringify_keys}
182
+ when :mkdir, :mv, :cp, :rm
183
+ return Main.result_success
184
+ when :ls
185
+ return {type: :object_list, data: result.map(&:stringify_keys), fields: %w[zmode zuid zgid size mtime name]}
186
+ when :df
187
+ return {type: :object_list, data: result.map(&:stringify_keys)}
188
+ when :du, :md5sum, :info
189
+ return {type: :single_object, data: result.stringify_keys}
136
190
  end
137
191
  rescue Aspera::AsCmd::Error => e
138
- raise CliBadArgument,e.extended_message
192
+ raise CliBadArgument, e.extended_message
139
193
  end
140
194
  else raise 'internal error: unexpected action'
141
195
  end
@@ -5,13 +5,15 @@ require 'aspera/cli/plugins/node'
5
5
  module Aspera
6
6
  module Cli
7
7
  module Plugins
8
- class Shares < BasicAuthPlugin
8
+ # Plugin for Aspera Shares v1
9
+ class Shares < Aspera::Cli::BasicAuthPlugin
9
10
  class << self
10
11
  def detect(base_url)
11
12
  api = Rest.new({base_url: base_url})
12
13
  # Shares
13
14
  begin
14
15
  # shall fail: shares requires auth, but we check error message
16
+ # TODO: use ping instead ?
15
17
  api.read('node_api/app')
16
18
  rescue RestCallError => e
17
19
  if e.response.code.to_s.eql?('401') && e.response.body.eql?('{"error":{"user_message":"API user authentication failed"}}')
@@ -22,12 +24,15 @@ module Aspera
22
24
  end
23
25
  end
24
26
 
25
- # def initialize(env)
26
- # super(env)
27
- # end
27
+ def initialize(env)
28
+ super(env)
29
+ options.add_opt_list(:type, %i[any local ldap saml], 'Type of user/group for operations')
30
+ options.set_option(:type, :any)
31
+ options.parse_options!
32
+ end
28
33
 
29
- SAML_IMPORT_MANDATORY=%w[id name_id].freeze
30
- SAML_IMPORT_ALLOWED=[SAML_IMPORT_MANDATORY,%w[email given_name surname]].flatten.freeze
34
+ SAML_IMPORT_MANDATORY = %w[id name_id].freeze
35
+ SAML_IMPORT_ALLOWED = %w[email given_name surname].concat(SAML_IMPORT_MANDATORY).freeze
31
36
 
32
37
  ACTIONS = %i[health repository admin].freeze
33
38
 
@@ -37,72 +42,92 @@ module Aspera
37
42
  when :health
38
43
  nagios = Nagios.new
39
44
  begin
40
- Rest.
41
- new(base_url: options.get_option(:url,is_type: :mandatory)+'/node_api').
42
- call(
45
+ Rest
46
+ .new(base_url: options.get_option(:url, is_type: :mandatory) + '/node_api')
47
+ .call(
43
48
  operation: 'GET',
44
49
  subpath: 'ping',
45
50
  headers: {'content-type': 'application/json'},
46
51
  return_error: true)
47
- nagios.add_ok('shares api','accessible')
52
+ nagios.add_ok('shares api', 'accessible')
48
53
  rescue StandardError => e
49
- nagios.add_critical('node api',e.to_s)
54
+ nagios.add_critical('node api', e.to_s)
50
55
  end
51
56
  return nagios.result
52
57
  when :repository
53
58
  api_shares_node = basic_auth_api('node_api')
54
- command = options.get_next_command(Node::COMMON_ACTIONS)
55
- case command
56
- when *Node::COMMON_ACTIONS then Node.new(@agents.merge(skip_basic_auth_options: true,node_api: api_shares_node)).execute_action(command)
57
- else raise "INTERNAL ERROR, unknown command: [#{command}]"
58
- end
59
+ repo_command = options.get_next_command(Node::COMMANDS_SHARES)
60
+ return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_shares_node)).execute_action(repo_command)
59
61
  when :admin
60
62
  api_shares_admin = basic_auth_api('api/v1')
61
- command = options.get_next_command(%i[user share])
62
- case command
63
- when :user
64
- command = options.get_next_command(%i[list app_authorizations share_permissions saml_import ldap_import])
65
- user_id = instance_identifier if %i[app_authorizations share_permissions].include?(command)
66
- case command
67
- when :list
68
- return {type: :object_list,data: api_shares_admin.read('data/users')[:data],fields: %w[id username email directory_user urn]}
63
+ admin_command = options.get_next_command(%i[user group share node])
64
+ case admin_command
65
+ when :node
66
+ return entity_action(api_shares_admin, 'data/nodes')
67
+ when :user, :group
68
+ entity_type = admin_command
69
+ entities_location = options.get_option(:type, is_type: :mandatory)
70
+ entities_path = "data/#{entities_location}_#{entity_type}s"
71
+ entity_action = nil
72
+ case entities_location
73
+ when :any
74
+ entities_path = "data/#{entity_type}s"
75
+ entity_action = %i[list show delete share_permissions app_authorizations].freeze
76
+ when :local
77
+ entity_action = %i[list show create modify delete].freeze
78
+ when :ldap
79
+ entity_action = %i[add].freeze
80
+ when :saml
81
+ entity_action = %i[import].freeze
82
+ end
83
+ entity_command = options.get_next_command(entity_action)
84
+ entity_path = "#{entities_path}/#{instance_identifier}" if %i[app_authorizations share_permissions].include?(entity_command)
85
+ case entity_command
86
+ when :list, :show, :create, :delete, :modify
87
+ display_fields = entity_type.eql?(:user) ? %w[id username first_name last_name email] : nil
88
+ display_fields.push(:directory_user) if entity_type.eql?(:user) && entities_location.eql?(:any)
89
+ return entity_command(entity_command, api_shares_admin, entities_path, display_fields: display_fields)
69
90
  when :app_authorizations
70
- return {type: :single_object,data: api_shares_admin.read("data/users/#{user_id}/app_authorizations")[:data]}
91
+ case options.get_next_command(%i[modify show])
92
+ when :show
93
+ return {type: :single_object, data: api_shares_admin.read("#{entity_path}/app_authorizations")[:data]}
94
+ when :modify
95
+ parameters = options.get_option(:value, is_type: :mandatory)
96
+ return {type: :single_object, data: api_shares_admin.update("#{entity_path}/app_authorizations", parameters)[:data]}
97
+ end
71
98
  when :share_permissions
72
- #share_name = options.get_next_argument('share name')
73
- #all_shares = api_shares_admin.read('data/shares')[:data]
74
- #share_id = all_shares.find{|s| s['name'].eql?(share_name)}['id']
75
- return {type: :object_list,data: api_shares_admin.read("data/users/#{user_id}/share_permissions")[:data]}
76
- when :saml_import
77
- parameters = options.get_option(:value)
78
- return do_bulk_operation(parameters,'created') do |user_params|
79
- user_params=user_params.transform_keys{|k|k.gsub(/\s+/,'_').downcase}
80
- raise 'expecting Hash' unless user_params.is_a?(Hash)
81
- SAML_IMPORT_MANDATORY.each{|p|raise "missing mandatory field: #{p}" if user_params[p].nil?}
82
- user_params.keys.each do |p|
99
+ case options.get_next_command(%i[list show])
100
+ when :list
101
+ return {type: :object_list, data: api_shares_admin.read("#{entity_path}/share_permissions")[:data]}
102
+ when :show
103
+ return {type: :single_object, data: api_shares_admin.read("#{entity_path}/share_permissions/#{instance_identifier}")[:data]}
104
+ end
105
+ when :import
106
+ parameters = options.get_option(:value, is_type: :mandatory)
107
+ return do_bulk_operation(parameters, 'created') do |entity_parameters|
108
+ entity_parameters = entity_parameters.transform_keys{|k|k.gsub(/\s+/, '_').downcase}
109
+ raise 'expecting Hash' unless entity_parameters.is_a?(Hash)
110
+ SAML_IMPORT_MANDATORY.each{|p|raise "missing mandatory field: #{p}" if entity_parameters[p].nil?}
111
+ entity_parameters.each_key do |p|
83
112
  raise "unsupported field: #{p}, use: #{SAML_IMPORT_ALLOWED.join(',')}" unless SAML_IMPORT_ALLOWED.include?(p)
84
113
  end
85
- api_shares_admin.create('data/saml_users/import',user_params)[:data]
114
+ api_shares_admin.create("#{entities_path}/import", entity_parameters)[:data]
86
115
  end
87
- when :ldap_import
116
+ when :add
88
117
  parameters = options.get_option(:value)
89
- return do_bulk_operation(parameters,'created') do |user_name|
90
- raise 'expecting string (user name), have #{user_params.class}' unless user_params.is_a?(String)
91
- api_shares_admin.create('data/ldap_users',{'user'=>user_name})[:data]
118
+ return do_bulk_operation(parameters, 'created') do |entity_name|
119
+ raise "expecting string (name), have #{entity_name.class}" unless entity_name.is_a?(String)
120
+ api_shares_admin.create(entities_path, {entity_type=>entity_name})[:data]
92
121
  end
93
122
  end
94
123
  when :share
95
- command = options.get_next_command(%i[list user_permissions])
96
- share_id = instance_identifier if %i[user_permissions].include?(command)
97
- all_shares = api_shares_admin.read('data/shares')[:data]
98
- case command
99
- when :list
100
- return {type: :object_list,data: all_shares,fields: %w[id name status status_message]}
101
- when :user_permissions
102
- #share_name = options.get_next_argument('share name')
103
- #share_id = all_shares.find{|s| s['name'].eql?(share_name)}['id']
104
- #raise "NOT IMPLEMENTED: #{share_name} #{share_id}"
105
- return {type: :object_list,data: api_shares_admin.read("data/shares/#{share_id}/user_permissions")[:data]}
124
+ share_command = options.get_next_command(%i[user_permissions group_permissions].concat(Plugin::ALL_OPS))
125
+ case share_command
126
+ when *Plugin::ALL_OPS
127
+ return entity_command(share_command, api_shares_admin, 'data/shares')
128
+ # return {type: :object_list, data: all_shares, fields: %w[id name status status_message]}
129
+ when :user_permissions, :group_permissions
130
+ return entity_action(api_shares_admin, "data/shares/#{instance_identifier}/#{share_command}")
106
131
  end
107
132
  end
108
133
  end
@@ -9,13 +9,16 @@ require 'open3'
9
9
  module Aspera
10
10
  module Cli
11
11
  module Plugins
12
- # list and download connect client versions, select FASP implementation
13
- class Sync < Plugin
14
- def initialize(env)
12
+ # Execute Aspera Sync
13
+ class Sync < Aspera::Cli::Plugin
14
+ def initialize(env, transfer_spec: nil)
15
15
  super(env)
16
- options.add_opt_simple(:parameters,'extended value for session set definition')
17
- options.add_opt_simple(:session_name,'name of session to use for admin commands, by default first one')
16
+ options.add_opt_simple(:sync_info, 'Information for sync instance and sessions (Hash)')
17
+ options.add_opt_simple(:sync_session, 'Name of session to use for admin commands. default: first in parameters')
18
18
  options.parse_options!
19
+ return if env[:man_only]
20
+ @params = options.get_option(:sync_info, is_type: :mandatory)
21
+ Aspera::Sync.update_parameters_with_transfer_spec(@params, transfer_spec) unless transfer_spec.nil?
19
22
  end
20
23
 
21
24
  ACTIONS = %i[start admin].freeze
@@ -24,38 +27,15 @@ module Aspera
24
27
  command = options.get_next_command(ACTIONS)
25
28
  case command
26
29
  when :start
27
- env_args = Aspera::Sync.new(options.get_option(:parameters,is_type: :mandatory)).compute_args
28
- async_bin = 'async'
29
- Log.log.debug("execute: #{env_args[:env].map{|k,v| "#{k}=\"#{v}\""}.join(' ')} \"#{async_bin}\" \"#{env_args[:args].join('" "')}\"")
30
- res = system(env_args[:env],[async_bin,async_bin],*env_args[:args])
31
- Log.log.debug("result=#{res}")
32
- case res
33
- when true then return Main.result_success
34
- when false then raise "failed: #{$CHILD_STATUS}"
35
- when nil then return Main.result_status("not started: #{$CHILD_STATUS}")
36
- else raise 'internal error: unspecified case'
37
- end
30
+ Aspera::Sync.new(@params).start
31
+ return Main.result_success
38
32
  when :admin
39
- p = options.get_option(:parameters,is_type: :mandatory)
40
- n = options.get_option(:session_name)
41
- cmdline = ['asyncadmin','--quiet']
42
- session = n.nil? ? p['sessions'].first : p['sessions'].find{|s|s['name'].eql?(n)}
43
- cmdline.push('--name=' + session['name'])
44
- if session.has_key?('local_db_dir')
45
- cmdline.push('--local-db-dir=' + session['local_db_dir'])
46
- else
47
- cmdline.push('--local-dir=' + session['local_dir'])
48
- end
33
+ sync_admin = Aspera::SyncAdmin.new(@params, options.get_option(:sync_session))
49
34
  command2 = options.get_next_command([:status])
50
35
  case command2
51
36
  when :status
52
- stdout, stderr, status = Open3.capture3(*cmdline)
53
- Log.log.debug("status=#{status}, stderr=#{stderr}")
54
- items = stdout.split("\n").each_with_object({}){|l,m|i = l.split(/: */);m[i.first.lstrip] = i.last.lstrip;}
55
- return {type: :single_object,data: items}
56
- else raise 'error'
57
- end # command
58
- else raise 'error'
37
+ return {type: :single_object, data: sync_admin.status}
38
+ end # command2
59
39
  end # command
60
40
  end # execute_action
61
41
  end # Sync