aspera-cli 4.3.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/docs/doc_tools.rb ADDED
@@ -0,0 +1,58 @@
1
+ # get transfer spec parameter description
2
+ $LOAD_PATH.unshift(ENV["INCL_DIR_GEM"])
3
+ require 'aspera/fasp/parameters'
4
+
5
+ # check that required env vars exist, and files
6
+ %w{EXENAME GEMSPEC INCL_USAGE INCL_COMMANDS INCL_ASESSION INCL_DIR_GEM}.each do |e|
7
+ raise "missing env var #{e}" unless ENV.has_key?(e)
8
+ raise "missing file #{ENV[e]}" unless File.exist?(ENV[e]) or !e.start_with?('INCL_')
9
+ end
10
+
11
+ # set values used in ERB
12
+ # just command name
13
+ def cmd;ENV['EXENAME'];end
14
+
15
+ # used in text with formatting of command
16
+ def tool;'`'+cmd+'`';end
17
+
18
+ # prefix for env vars
19
+ def evp;cmd.upcase+'_';end
20
+
21
+ # just the name for "option preset"
22
+ def opprst;'option preset';end
23
+
24
+ # name with link
25
+ def prst;'['+opprst+'](#lprt)';end
26
+
27
+ # name with link (plural)
28
+ def prsts;'['+opprst+'s](#lprt)';end
29
+
30
+ # in title
31
+ def prstt;opprst.capitalize;end
32
+
33
+ def gemspec;Gem::Specification::load(ENV['GEMSPEC']) or raise "error loading #{ENV["GEMSPEC"]}";end
34
+
35
+ def geminstadd;gemspec.version.to_s.match(/\.[^0-9]/)?' --pre':'';end
36
+
37
+ # transfer spec description generation
38
+ def spec_table
39
+ r='<table><tr><th>Field</th><th>Type</th>'
40
+ Aspera::Fasp::Parameters::SUPPORTED_AGENTS_SHORT.each do |c|
41
+ r << '<th>'<<c.to_s.upcase<<'</th>'
42
+ end
43
+ r << '<th>Description</th></tr>'
44
+ Aspera::Fasp::Parameters.man_table.each do |p|
45
+ p[:description] << (p[:description].empty? ? '' : "\n") << "(" << p[:cli] << ")" unless p[:cli].to_s.empty?
46
+ p.delete(:cli)
47
+ p.keys.each{|c|p[c]='&nbsp;' if p[c].to_s.empty?}
48
+ p[:description].gsub!("\n",'<br/>')
49
+ p[:type].gsub!(',','<br/>')
50
+ r << '<tr><td>'<<p[:name]<<'</td><td>'<<p[:type]<<'</td>'
51
+ Aspera::Fasp::Parameters::SUPPORTED_AGENTS_SHORT.each do |c|
52
+ r << '<td>'<<p[c]<<'</td>'
53
+ end
54
+ r << '<td>'<<p[:description]<<'</td></tr>'
55
+ end
56
+ r << '</table>'
57
+ return r
58
+ end
data/lib/aspera/aoc.rb CHANGED
@@ -2,6 +2,7 @@ require 'aspera/log'
2
2
  require 'aspera/rest'
3
3
  require 'aspera/hash_ext'
4
4
  require 'aspera/data_repository'
5
+ require 'aspera/node'
5
6
  require 'base64'
6
7
 
7
8
  module Aspera
@@ -24,9 +25,9 @@ module Aspera
24
25
  JWT_AUDIENCE='https://api.asperafiles.com/api/v1/oauth2/token'
25
26
  OAUTH_API_SUBPATH='api/v1/oauth2'
26
27
  DEFAULT_TSPEC_INFO={
27
- 'remote_user' => 'xfer',
28
- 'ssh_port' => 33001,
29
- 'fasp_port' => 33001
28
+ 'remote_user' => Node::ACCESS_KEY_TRANSFER_USER,
29
+ 'ssh_port' => Node::SSH_PORT_DEFAULT,
30
+ 'fasp_port' => Node::UDP_PORT_DEFAULT
30
31
  }
31
32
 
32
33
  private_constant :PRODUCT_NAME,:PROD_DOMAIN,:MAX_REDIRECT,:CLIENT_APPS,:PATHS_PUBLIC_LINK,:JWT_AUDIENCE,:OAUTH_API_SUBPATH,:DEFAULT_TSPEC_INFO
@@ -2,10 +2,15 @@ module Aspera
2
2
  module Cli
3
3
  # base class for plugins modules
4
4
  class Plugin
5
+ # operation without id
5
6
  GLOBAL_OPS=[:create,:list]
7
+ # operation on specific instance
6
8
  INSTANCE_OPS=[:modify,:delete,:show]
7
9
  ALL_OPS=[GLOBAL_OPS,INSTANCE_OPS].flatten
8
- #private_constant :GLOBAL_OPS,:INSTANCE_OPS,:ALL_OPS
10
+ # max number of items for list command
11
+ MAX_ITEMS='max'
12
+ # max number of pages for list command
13
+ MAX_PAGES='pmax'
9
14
 
10
15
  @@done=false
11
16
 
@@ -28,7 +33,7 @@ module Aspera
28
33
  end
29
34
  end
30
35
 
31
- def entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default=nil,subkey=false)
36
+ def entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default=nil,use_subkey=false)
32
37
  if INSTANCE_OPS.include?(command)
33
38
  begin
34
39
  one_res_id=self.options.get_option(id_symb,:mandatory)
@@ -54,10 +59,11 @@ module Aspera
54
59
  when :list
55
60
  resp=rest_api.read(res_class_path,parameters)
56
61
  data=resp[:data]
62
+ # TODO: not generic : which application is this for ?
57
63
  if resp[:http]['Content-Type'].start_with?('application/vnd.api+json')
58
- data=resp[:data][res_class_path]
64
+ data=data[res_class_path]
59
65
  end
60
- data=data[res_class_path] if subkey
66
+ data=data[res_class_path] if use_subkey
61
67
  return {:type => :object_list, :data=>data, :fields=>display_fields}
62
68
  when :modify
63
69
  property=self.options.get_option(:property,:optional)
@@ -74,12 +80,13 @@ module Aspera
74
80
  end
75
81
 
76
82
  # implement generic rest operations on given resource path
77
- def entity_action(rest_api,res_class_path,display_fields,id_symb,id_default=nil,subkey=false)
83
+ def entity_action(rest_api,res_class_path,display_fields,id_symb,id_default=nil,use_subkey=false)
78
84
  #res_name=res_class_path.gsub(%r{^.*/},'').gsub(%r{s$},'').gsub('_',' ')
79
85
  command=self.options.get_next_command(ALL_OPS)
80
- return entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default,subkey)
86
+ return entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default,use_subkey)
81
87
  end
82
88
 
89
+ # shortcuts for plugin environment
83
90
  def options; return @agents[:options];end
84
91
 
85
92
  def transfer; return @agents[:transfer];end
@@ -205,7 +205,7 @@ module Aspera
205
205
  node_api.call({:operation=>'GET',:subpath=>"files/#{node_file[:file_id]}/content",:save_to_file=>File.join(self.transfer.destination_folder('receive'),file_name)})
206
206
  return Main.result_status("downloaded: #{file_name}")
207
207
  when :v3
208
- # Note: other "common" actions are unauthorized with user scope
208
+ # Note: other common actions are unauthorized with user scope
209
209
  command_legacy=self.options.get_next_command(Node::SIMPLE_ACTIONS)
210
210
  # TODO: shall we support all methods here ? what if there is a link ?
211
211
  node_api=@api_aoc.get_node_api(top_node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
@@ -224,14 +224,14 @@ module Aspera
224
224
  items=node_api.read("files/#{node_file[:file_id]}")[:data]
225
225
  return {:type=>:single_object,:data=>items}
226
226
  when :modify
227
- update_param=self.options.get_next_argument("update data (Hash)")
227
+ update_param=self.options.get_next_argument('update data (Hash)')
228
228
  res=node_api.update("files/#{node_file[:file_id]}",update_param)[:data]
229
229
  return {:type=>:single_object,:data=>res}
230
230
  when :permission
231
231
  command_perm=self.options.get_next_command([:list,:create])
232
232
  case command_perm
233
233
  when :list
234
- # generic options : TODO: as arg ?
234
+ # generic options : TODO: as arg ? option_url_query
235
235
  list_options||={'include'=>['[]','access_level','permission_count']}
236
236
  # special value: ALL will show all permissions
237
237
  if !VAL_ALL.eql?(node_file[:file_id])
@@ -239,11 +239,10 @@ module Aspera
239
239
  list_options['file_id']=node_file[:file_id]
240
240
  list_options['inherited']||=false
241
241
  end
242
- #option_url_query
243
242
  items=node_api.read('permissions',list_options)[:data]
244
243
  return {:type=>:object_list,:data=>items}
245
244
  when :create
246
- #create_param=self.options.get_next_argument("creation data (Hash)")
245
+ #create_param=self.options.get_next_argument('creation data (Hash)')
247
246
  set_workspace_info
248
247
  access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
249
248
  node_file[:node_info]
@@ -266,14 +265,14 @@ module Aspera
266
265
  return {:type=>:single_object,:data=>item}
267
266
  else raise "internal error:shall not reach here (#{command_perm})"
268
267
  end
269
- raise "internal error:shall not reach here"
268
+ raise 'internal error:shall not reach here'
270
269
  else raise "internal error:shall not reach here (#{command_node_file})"
271
270
  end
272
- raise "internal error:shall not reach here"
271
+ raise 'internal error:shall not reach here'
273
272
  when :permissions
274
273
 
275
274
  end # command_repo
276
- raise "ERR"
275
+ raise 'ERR'
277
276
  end # execute_node_gen4_command
278
277
 
279
278
  # build constructor option list for AoC based on options of CLI
@@ -304,15 +303,15 @@ module Aspera
304
303
 
305
304
  ws_name=self.options.get_option(:workspace,:optional)
306
305
  if ws_name.nil?
307
- Log.log.debug("using default workspace".green)
306
+ Log.log.debug('using default workspace'.green)
308
307
  if @default_workspace_id.eql?(nil)
309
- raise CliError,"no default workspace defined for user, please specify workspace"
308
+ raise CliError,'no default workspace defined for user, please specify workspace'
310
309
  end
311
310
  # get default workspace
312
311
  @workspace_id=@default_workspace_id
313
312
  else
314
313
  # lookup another workspace
315
- wss=@api_aoc.read("workspaces",{'q'=>ws_name})[:data]
314
+ wss=@api_aoc.read('workspaces',{'q'=>ws_name})[:data]
316
315
  wss=wss.select { |i| i['name'].eql?(ws_name) }
317
316
  case wss.length
318
317
  when 0
@@ -320,14 +319,14 @@ module Aspera
320
319
  when 1
321
320
  @workspace_id=wss.first['id']
322
321
  else
323
- raise "unexpected case"
322
+ raise 'unexpected case'
324
323
  end
325
324
  end
326
325
  @workspace_data=@api_aoc.read("workspaces/#{@workspace_id}")[:data]
327
326
  Log.log.debug("workspace_id=#{@workspace_id},@workspace_data=#{@workspace_data}".red)
328
327
 
329
328
  @workspace_name||=@workspace_data['name']
330
- Log.log.info("current workspace is "+@workspace_name.red)
329
+ Log.log.info('current workspace is '+@workspace_name.red)
331
330
 
332
331
  # display workspace
333
332
  self.format.display_status("Current Workspace: #{@workspace_name.red}#{@workspace_id == @default_workspace_id ? ' (default)' : ''}")
@@ -343,7 +342,7 @@ module Aspera
343
342
  end
344
343
  home_node_id||=@workspace_data['home_node_id']||@workspace_data['node_id']
345
344
  home_file_id||=@workspace_data['home_file_id']
346
- raise "node_id must be defined" if home_node_id.to_s.empty?
345
+ raise 'node_id must be defined' if home_node_id.to_s.empty?
347
346
  @home_node_file={
348
347
  node_info: @api_aoc.read("nodes/#{home_node_id}")[:data],
349
348
  file_id: home_file_id
@@ -355,7 +354,7 @@ module Aspera
355
354
 
356
355
  def do_bulk_operation(ids_or_one,success_msg,id_result='id',&do_action)
357
356
  ids_or_one=[ids_or_one] unless self.options.get_option(:bulk)
358
- raise "expecting Array" unless ids_or_one.is_a?(Array)
357
+ raise 'expecting Array' unless ids_or_one.is_a?(Array)
359
358
  result_list=[]
360
359
  ids_or_one.each do |id|
361
360
  one={id_result=>id}
@@ -411,7 +410,8 @@ module Aspera
411
410
 
412
411
  # private
413
412
  def option_url_query(default)
414
- query=self.options.get_option(:query,:optional)||default
413
+ query=self.options.get_option(:query,:optional)
414
+ query=default if query.nil?
415
415
  Log.log.debug("Query=#{query}".bg_red)
416
416
  begin
417
417
  # check it is suitable
@@ -428,6 +428,37 @@ module Aspera
428
428
  end
429
429
  end
430
430
 
431
+ # Call @api_aoc.read with same parameters, but use paging if necessary to get all results
432
+ def read_with_paging(resource_class_path,base_query)
433
+ raise "Query must be Hash" unless base_query.is_a?(Hash)
434
+ # set default large page if user does not specify own parameters. AoC Caps to 1000 anyway
435
+ base_query['per_page']=1000 unless base_query.has_key?('per_page')
436
+ max_items=base_query[MAX_ITEMS]
437
+ base_query.delete(MAX_ITEMS)
438
+ max_pages=base_query[MAX_PAGES]
439
+ base_query.delete(MAX_PAGES)
440
+ item_list=[]
441
+ total_count=nil
442
+ current_page=base_query['page']
443
+ current_page=1 if current_page.nil?
444
+ page_count=0
445
+ loop do
446
+ query=base_query.clone
447
+ query['page']=current_page
448
+ result=@api_aoc.read(resource_class_path,query)
449
+ total_count=result[:http]['X-Total-Count']
450
+ page_count+=1
451
+ current_page+=1
452
+ add_items=result[:data]
453
+ break if add_items.empty?
454
+ # append new items to full list
455
+ item_list += add_items
456
+ break if !max_pages.nil? and page_count > max_pages
457
+ break if !max_items.nil? and item_list.count > max_items
458
+ end
459
+ return item_list,total_count
460
+ end
461
+
431
462
  def execute_admin_action
432
463
  @api_aoc.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
433
464
  command_admin=self.options.get_next_command([ :ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers ])
@@ -517,11 +548,11 @@ module Aspera
517
548
  when 'organizations'; c_user_info['organization_id']
518
549
  when 'users'; c_user_info['id']
519
550
  when 'nodes'; c_user_info['id']
520
- else raise "organizations or users for option --name"
551
+ else raise 'organizations or users for option --name'
521
552
  end
522
553
  #
523
554
  filter=self.options.get_option(:query,:optional) || {}
524
- raise "query must be Hash" unless filter.is_a?(Hash)
555
+ raise 'query must be Hash' unless filter.is_a?(Hash)
525
556
  filter['limit']||=100
526
557
  if self.options.get_option(:once_only,:mandatory)
527
558
  saved_date=[]
@@ -547,13 +578,13 @@ module Aspera
547
578
  return {:type=>:object_list,:data=>events}
548
579
  end
549
580
  when :resource
550
- resource_type=self.options.get_next_argument('resource',[:self,:organization,:user,:group,:client,:contact,:dropbox,:node,:operation,:package,:saml_configuration, :workspace, :dropbox_membership,:short_link,:workspace_membership,:apps_new,:client_registration_token,:client_access_key,:kms_profile])
581
+ resource_type=self.options.get_next_argument('resource',[:self,:organization,:user,:group,:client,:contact,:dropbox,:node,:operation,:package,:saml_configuration, :workspace, :dropbox_membership,:short_link,:workspace_membership,:application,:client_registration_token,:client_access_key,:kms_profile])
551
582
  # get path on API
552
583
  resource_class_path=case resource_type
553
584
  when :self,:organization
554
- "#{resource_type}"
555
- when :apps_new
556
- "admin/#{resource_type}"
585
+ resource_type
586
+ when :application
587
+ 'admin/apps_new'
557
588
  when :dropbox
558
589
  resource_type.to_s+'es'
559
590
  when :client_registration_token,:client_access_key
@@ -582,13 +613,13 @@ module Aspera
582
613
  res_id=@home_node_file[:node_info]['id']
583
614
  end
584
615
  if !res_name.nil?
585
- Log.log.warn("name overrides id") unless res_id.nil?
616
+ Log.log.warn('name overrides id') unless res_id.nil?
586
617
  matching=@api_aoc.read(resource_class_path,{:q=>res_name})[:data]
587
- raise CliError,"no resource match name" if matching.empty?
618
+ raise CliError,'no resource match name' if matching.empty?
588
619
  raise CliError,"several resources match name (#{matching.join(',')})" unless matching.length.eql?(1)
589
620
  res_id=matching.first['id']
590
621
  end
591
- raise CliBadArgument,"provide either id or name" if res_id.nil?
622
+ raise CliBadArgument,'provide either id or name' if res_id.nil?
592
623
  resource_instance_path="#{resource_class_path}/#{res_id}"
593
624
  end
594
625
  resource_instance_path=resource_class_path if singleton_object
@@ -598,26 +629,29 @@ module Aspera
598
629
  id_result='token' if resource_class_path.eql?('admin/client_registration_tokens')
599
630
  # TODO: report inconsistency: creation url is !=, and does not return id.
600
631
  resource_class_path='admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
601
- list_or_one=self.options.get_next_argument("creation data (Hash)")
632
+ list_or_one=self.options.get_next_argument('creation data (Hash)')
602
633
  return do_bulk_operation(list_or_one,'created',id_result)do|params|
603
- raise "expecting Hash" unless params.is_a?(Hash)
634
+ raise 'expecting Hash' unless params.is_a?(Hash)
604
635
  @api_aoc.create(resource_class_path,params)[:data]
605
636
  end
606
637
  when :list
607
- default_fields=['id','name']
608
- list_query=nil
638
+ default_fields=['id']
639
+ default_query={}
609
640
  case resource_type
610
- when :node; default_fields.push('host','access_key')
641
+ when :application; default_query={:organization_apps=>true};default_fields.push('app_type','app_name','available','direct_authorizations_allowed','workspace_authorizations_allowed')
642
+ when :client,:client_access_key,:dropbox,:group,:package,:saml_configuration,:workspace; default_fields.push('name')
643
+ when :client_registration_token; default_fields.push('value','data.client_subject_scopes','created_at')
644
+ when :contact; default_fields=['email','name','source_id','source_type']
645
+ when :node; default_fields.push('name','host','access_key')
611
646
  when :operation; default_fields=nil
612
- when :contact; default_fields=["email","name","source_id","source_type"]
613
- when :apps_new; list_query={:organization_apps=>true};default_fields=['app_type','available']
614
- when :client_registration_token; default_fields=['id','value','data.client_subject_scopes','created_at']
647
+ when :short_link; default_fields.push('short_url','data.url_token_data.purpose')
648
+ when :user; default_fields.push('name','email')
615
649
  end
616
- result=@api_aoc.read(resource_class_path,option_url_query(list_query))
617
- count_msg="Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}"
618
- count_msg=count_msg.bg_red unless result[:data].length.eql?(result[:http]['X-Total-Count'].to_i)
650
+ item_list,total_count=read_with_paging(resource_class_path,option_url_query(default_query))
651
+ count_msg="Items: #{item_list.length}/#{total_count}"
652
+ count_msg=count_msg.bg_red unless item_list.length.eql?(total_count.to_i)
619
653
  self.format.display_status(count_msg)
620
- return {:type=>:object_list,:data=>result[:data],:fields=>default_fields}
654
+ return {:type=>:object_list,:data=>item_list,:fields=>default_fields}
621
655
  when :show
622
656
  object=@api_aoc.read(resource_instance_path)[:data]
623
657
  fields=object.keys.select{|k|!k.eql?('certificate')}
@@ -647,8 +681,8 @@ module Aspera
647
681
  when :shared_folders
648
682
  read_params = case resource_type
649
683
  when :workspace;{'access_id'=>"ASPERA_ACCESS_KEY_ADMIN_WS_#{res_id}",'access_type'=>'user'}
650
- when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>"ASPERA_ACCESS_KEY_ADMIN"}
651
- else raise "error"
684
+ when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>'ASPERA_ACCESS_KEY_ADMIN'}
685
+ else raise 'error'
652
686
  end
653
687
  res_data=@api_aoc.read("#{resource_class_path}/#{res_id}/permissions",read_params)[:data]
654
688
  fields=case resource_type
@@ -688,7 +722,7 @@ module Aspera
688
722
  create_data.deep_merge!(user_create_data)
689
723
  Log.dump(:data,create_data)
690
724
  raise :ERROR
691
- else raise "unknown command"
725
+ else raise 'unknown command'
692
726
  end
693
727
  when :usage_reports
694
728
  return {:type=>:object_list,:data=>@api_aoc.read('usage_reports',{:workspace_id=>@workspace_id})[:data]}
@@ -719,7 +753,7 @@ module Aspera
719
753
  when :workspaces
720
754
  return {:type=>:object_list,:data=>@api_aoc.read('workspaces')[:data],:fields=>['id','name']}
721
755
  # when :settings
722
- # return {:type=>:object_list,:data=>@api_aoc.read("client_settings/")[:data]}
756
+ # return {:type=>:object_list,:data=>@api_aoc.read('client_settings/')[:data]}
723
757
  when :shared_inboxes
724
758
  query=option_url_query(nil)
725
759
  if query.nil?
@@ -764,7 +798,7 @@ module Aspera
764
798
  resolve_package_recipients(package_creation,'recipients')
765
799
  resolve_package_recipients(package_creation,'bcc_recipients')
766
800
 
767
- # create a new package with one file
801
+ # create a new package container
768
802
  package_info=@api_aoc.create('packages',package_creation)[:data]
769
803
 
770
804
  # get node information for the node on which package must be created
@@ -775,7 +809,7 @@ module Aspera
775
809
 
776
810
  # execute transfer
777
811
  node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
778
- # raise esception if at least one error
812
+ # raise exception if at least one error
779
813
  Main.result_transfer(transfer_start(AoC::PACKAGES_APP,'send',node_file,AoC.package_tags(package_info,'upload')))
780
814
  # return all info on package
781
815
  return { :type=>:single_object, :data =>package_info}
@@ -826,8 +860,10 @@ module Aspera
826
860
  package_info=@api_aoc.read("packages/#{package_id}")[:data]
827
861
  return { :type=>:single_object, :data =>package_info }
828
862
  when :list
829
- # list all packages ('page'=>1,'per_page'=>10,)'sort'=>'-sent_at',
830
- packages=@api_aoc.read('packages',{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
863
+ query=option_url_query({'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true})
864
+ raise 'option must be Hash' unless query.is_a?(Hash)
865
+ query['workspace_id']||=@workspace_id
866
+ packages=@api_aoc.read('packages',query)[:data]
831
867
  return {:type=>:object_list,:data=>packages,:fields=>['id','name','bytes_transferred']}
832
868
  when :delete
833
869
  list_or_one=self.options.get_option(:id,:mandatory)
@@ -910,9 +946,9 @@ module Aspera
910
946
  end
911
947
  return result
912
948
  end # files command
913
- throw "Error: shall not reach this line"
949
+ throw 'Error: shall not reach this line'
914
950
  when :automation
915
- Log.log.warn("BETA: work under progress")
951
+ Log.log.warn('BETA: work under progress')
916
952
  # automation api is not in the same place
917
953
  automation_rest_params=@api_aoc.params.clone
918
954
  automation_rest_params[:base_url].gsub!('/api/','/automation/')
@@ -935,9 +971,9 @@ module Aspera
935
971
  wf_command=self.options.get_next_command([:list,:create,:show])
936
972
  wf_id=self.options.get_option(:id,:mandatory)
937
973
  step=automation_api.create('steps',{'workflow_id'=>wf_id})[:data]
938
- automation_api.update("workflows/#{wf_id}",{'step_order'=>[step["id"]]})
939
- action=automation_api.create('actions',{'step_id'=>step["id"],'type'=>'manual'})[:data]
940
- automation_api.update("steps/#{step["id"]}",{'action_order'=>[action["id"]]})
974
+ automation_api.update("workflows/#{wf_id}",{'step_order'=>[step['id']]})
975
+ action=automation_api.create('actions',{'step_id'=>step['id'],'type'=>'manual'})[:data]
976
+ automation_api.update("steps/#{step['id']}",{'action_order'=>[action['id']]})
941
977
  wf=automation_api.read("workflows/#{wf_id}")[:data]
942
978
  return {:type=>:single_object,:data=>wf}
943
979
  end
@@ -953,7 +989,7 @@ module Aspera
953
989
  else
954
990
  raise "internal error: #{command}"
955
991
  end # action
956
- raise RuntimeError, "internal error: command shall return"
992
+ raise RuntimeError, 'internal error: command shall return'
957
993
  end
958
994
 
959
995
  private :c_user_info,:aoc_params,:set_workspace_info,:set_home_node_file,:do_bulk_operation,:resolve_package_recipients,:option_url_query,:assert_public_link_types,:execute_admin_action