aspera-cli 4.0.0.pre1
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 +7 -0
- data/README.md +3592 -0
- data/bin/ascli +7 -0
- data/bin/asession +89 -0
- data/docs/Makefile +59 -0
- data/docs/README.erb.md +3012 -0
- data/docs/README.md +13 -0
- data/docs/diagrams.txt +49 -0
- data/docs/secrets.make +38 -0
- data/docs/test_env.conf +117 -0
- data/docs/transfer_spec.html +99 -0
- data/examples/aoc.rb +17 -0
- data/examples/proxy.pac +60 -0
- data/examples/transfer.rb +115 -0
- data/lib/aspera/api_detector.rb +60 -0
- data/lib/aspera/ascmd.rb +151 -0
- data/lib/aspera/ats_api.rb +43 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +38 -0
- data/lib/aspera/cli/extended_value.rb +88 -0
- data/lib/aspera/cli/formater.rb +238 -0
- data/lib/aspera/cli/listener/line_dump.rb +17 -0
- data/lib/aspera/cli/listener/logger.rb +20 -0
- data/lib/aspera/cli/listener/progress.rb +52 -0
- data/lib/aspera/cli/listener/progress_multi.rb +91 -0
- data/lib/aspera/cli/main.rb +304 -0
- data/lib/aspera/cli/manager.rb +440 -0
- data/lib/aspera/cli/plugin.rb +90 -0
- data/lib/aspera/cli/plugins/alee.rb +24 -0
- data/lib/aspera/cli/plugins/ats.rb +231 -0
- data/lib/aspera/cli/plugins/bss.rb +71 -0
- data/lib/aspera/cli/plugins/config.rb +806 -0
- data/lib/aspera/cli/plugins/console.rb +62 -0
- data/lib/aspera/cli/plugins/cos.rb +106 -0
- data/lib/aspera/cli/plugins/faspex.rb +377 -0
- data/lib/aspera/cli/plugins/faspex5.rb +93 -0
- data/lib/aspera/cli/plugins/node.rb +438 -0
- data/lib/aspera/cli/plugins/oncloud.rb +937 -0
- data/lib/aspera/cli/plugins/orchestrator.rb +169 -0
- data/lib/aspera/cli/plugins/preview.rb +464 -0
- data/lib/aspera/cli/plugins/server.rb +216 -0
- data/lib/aspera/cli/plugins/shares.rb +63 -0
- data/lib/aspera/cli/plugins/shares2.rb +114 -0
- data/lib/aspera/cli/plugins/sync.rb +65 -0
- data/lib/aspera/cli/plugins/xnode.rb +115 -0
- data/lib/aspera/cli/transfer_agent.rb +251 -0
- data/lib/aspera/cli/version.rb +5 -0
- data/lib/aspera/colors.rb +39 -0
- data/lib/aspera/command_line_builder.rb +137 -0
- data/lib/aspera/fasp/aoc.rb +24 -0
- data/lib/aspera/fasp/connect.rb +99 -0
- data/lib/aspera/fasp/error.rb +21 -0
- data/lib/aspera/fasp/error_info.rb +60 -0
- data/lib/aspera/fasp/http_gw.rb +81 -0
- data/lib/aspera/fasp/installation.rb +240 -0
- data/lib/aspera/fasp/listener.rb +11 -0
- data/lib/aspera/fasp/local.rb +377 -0
- data/lib/aspera/fasp/manager.rb +69 -0
- data/lib/aspera/fasp/node.rb +88 -0
- data/lib/aspera/fasp/parameters.rb +235 -0
- data/lib/aspera/fasp/resume_policy.rb +76 -0
- data/lib/aspera/fasp/uri.rb +51 -0
- data/lib/aspera/faspex_gw.rb +196 -0
- data/lib/aspera/hash_ext.rb +28 -0
- data/lib/aspera/log.rb +80 -0
- data/lib/aspera/nagios.rb +71 -0
- data/lib/aspera/node.rb +14 -0
- data/lib/aspera/oauth.rb +319 -0
- data/lib/aspera/on_cloud.rb +421 -0
- data/lib/aspera/open_application.rb +72 -0
- data/lib/aspera/persistency_action_once.rb +42 -0
- data/lib/aspera/persistency_folder.rb +91 -0
- data/lib/aspera/preview/file_types.rb +300 -0
- data/lib/aspera/preview/generator.rb +258 -0
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/options.rb +35 -0
- data/lib/aspera/preview/utils.rb +131 -0
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/proxy_auto_config.erb.js +287 -0
- data/lib/aspera/proxy_auto_config.rb +34 -0
- data/lib/aspera/rest.rb +296 -0
- data/lib/aspera/rest_call_error.rb +13 -0
- data/lib/aspera/rest_error_analyzer.rb +98 -0
- data/lib/aspera/rest_errors_aspera.rb +58 -0
- data/lib/aspera/ssh.rb +53 -0
- data/lib/aspera/sync.rb +82 -0
- data/lib/aspera/temp_file_manager.rb +37 -0
- data/lib/aspera/uri_reader.rb +25 -0
- metadata +288 -0
| @@ -0,0 +1,216 @@ | |
| 1 | 
            +
            require 'aspera/cli/basic_auth_plugin'
         | 
| 2 | 
            +
            require 'aspera/ascmd'
         | 
| 3 | 
            +
            require 'aspera/ssh'
         | 
| 4 | 
            +
            require 'aspera/nagios'
         | 
| 5 | 
            +
            require 'tempfile'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Aspera
         | 
| 8 | 
            +
              module Cli
         | 
| 9 | 
            +
                module Plugins
         | 
| 10 | 
            +
                  # implement basic remote access with FASP/SSH
         | 
| 11 | 
            +
                  class Server < BasicAuthPlugin
         | 
| 12 | 
            +
                    class LocalExecutor
         | 
| 13 | 
            +
                      def execute(cmd,input=nil)
         | 
| 14 | 
            +
                        `#{cmd}`
         | 
| 15 | 
            +
                      end
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    def initialize(env)
         | 
| 19 | 
            +
                      super(env)
         | 
| 20 | 
            +
                      self.options.add_opt_simple(:ssh_keys,'ssh key path list (Array or single)')
         | 
| 21 | 
            +
                      self.options.add_opt_simple(:ssh_options,'ssh options (Hash)')
         | 
| 22 | 
            +
                      self.options.add_opt_simple(:cmd_prefix,'prefix to add for as cmd execution, e.g. sudo or /opt/aspera/bin ')
         | 
| 23 | 
            +
                      self.options.set_option(:ssh_keys,[])
         | 
| 24 | 
            +
                      self.options.set_option(:ssh_options,{})
         | 
| 25 | 
            +
                      self.options.parse_options!
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    def key_symb_to_str_single(source)
         | 
| 29 | 
            +
                      return source.inject({}){|memo,(k,v)| memo[k.to_s] = v; memo}
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    def key_symb_to_str_list(source)
         | 
| 33 | 
            +
                      return source.map{|o| key_symb_to_str_single(o)}
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    def asctl_parse(text)
         | 
| 37 | 
            +
                      r=/:\s*/
         | 
| 38 | 
            +
                      return text.split("\n").map do |line|
         | 
| 39 | 
            +
                        # console
         | 
| 40 | 
            +
                        line.gsub!(/(SessionDataCollector)/,'\1 ')
         | 
| 41 | 
            +
                        # orchestrator
         | 
| 42 | 
            +
                        line.gsub!(/ with pid:.*/,'')
         | 
| 43 | 
            +
                        line.gsub!(/ is /,': ')
         | 
| 44 | 
            +
                        x=line.split(r)
         | 
| 45 | 
            +
                        next unless x.length.eql?(2)
         | 
| 46 | 
            +
                        y={'process'=>x.first,'state'=>x.last}
         | 
| 47 | 
            +
                        # console
         | 
| 48 | 
            +
                        y['state'].gsub!(/\.+$/,'')
         | 
| 49 | 
            +
                        # console
         | 
| 50 | 
            +
                        y['process'].gsub!(/^.+::/,'')
         | 
| 51 | 
            +
                        # faspex
         | 
| 52 | 
            +
                        y['process'].gsub!(/^Faspex /,'')
         | 
| 53 | 
            +
                        # faspex
         | 
| 54 | 
            +
                        y['process'].gsub!(/ Background/,'')
         | 
| 55 | 
            +
                        y['process'].gsub!(/serving orchestrator on port /,'')
         | 
| 56 | 
            +
                        # console
         | 
| 57 | 
            +
                        r=/\s+/ if y['process'].eql?('Console')
         | 
| 58 | 
            +
                        # orchestrator
         | 
| 59 | 
            +
                        y['process'].gsub!(/^  -> /,'')
         | 
| 60 | 
            +
                        y['process'].gsub!(/ Process/,'')
         | 
| 61 | 
            +
                        y
         | 
| 62 | 
            +
                      end.select{|i|!i.nil?}
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    ACTIONS=[:nagios,:nodeadmin,:userdata,:configurator,:ctl,:download,:upload,:browse,:delete,:rename].concat(Aspera::AsCmd::OPERATIONS)
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    def execute_action
         | 
| 68 | 
            +
                      server_uri=URI.parse(self.options.get_option(:url,:mandatory))
         | 
| 69 | 
            +
                      Log.log.debug("URI : #{server_uri}, port=#{server_uri.port}, scheme:#{server_uri.scheme}")
         | 
| 70 | 
            +
                      shell_executor=nil
         | 
| 71 | 
            +
                      case server_uri.scheme
         | 
| 72 | 
            +
                      when 'ssh'
         | 
| 73 | 
            +
                        server_transfer_spec={
         | 
| 74 | 
            +
                          'remote_host'=>server_uri.hostname,
         | 
| 75 | 
            +
                          'remote_user'=>self.options.get_option(:username,:mandatory),
         | 
| 76 | 
            +
                        }
         | 
| 77 | 
            +
                        ssh_options=self.options.get_option(:ssh_options,:optional)
         | 
| 78 | 
            +
                        raise 'expecting a Hash for ssh_options' unless ssh_options.is_a?(Hash)
         | 
| 79 | 
            +
                        if !server_uri.port.nil?
         | 
| 80 | 
            +
                          ssh_options[:port]=server_uri.port
         | 
| 81 | 
            +
                          server_transfer_spec['ssh_port']=server_uri.port
         | 
| 82 | 
            +
                        end
         | 
| 83 | 
            +
                        cred_set=false
         | 
| 84 | 
            +
                        password=self.options.get_option(:password,:optional)
         | 
| 85 | 
            +
                        if !password.nil?
         | 
| 86 | 
            +
                          ssh_options[:password]=password
         | 
| 87 | 
            +
                          server_transfer_spec['remote_password']=password
         | 
| 88 | 
            +
                          cred_set=true
         | 
| 89 | 
            +
                        end
         | 
| 90 | 
            +
                        ssh_keys=self.options.get_option(:ssh_keys,:optional)
         | 
| 91 | 
            +
                        if !ssh_keys.nil?
         | 
| 92 | 
            +
                          raise 'expecting single value or array for ssh_keys' unless ssh_keys.is_a?(Array) or ssh_keys.is_a?(String)
         | 
| 93 | 
            +
                          ssh_keys=[ssh_keys] if ssh_keys.is_a?(String)
         | 
| 94 | 
            +
                          ssh_keys.map!{|p|File.expand_path(p)}
         | 
| 95 | 
            +
                          Log.log.debug("ssh keys=#{ssh_keys}")
         | 
| 96 | 
            +
                          ssh_options[:keys]=ssh_keys
         | 
| 97 | 
            +
                          server_transfer_spec['EX_ssh_key_paths']=ssh_keys
         | 
| 98 | 
            +
                          ssh_keys.each do |k|
         | 
| 99 | 
            +
                            Log.log.warn("no such key file: #{k}") unless File.exist?(k)
         | 
| 100 | 
            +
                          end
         | 
| 101 | 
            +
                          cred_set=true
         | 
| 102 | 
            +
                        end
         | 
| 103 | 
            +
                        raise 'either password or key must be provided' if !cred_set
         | 
| 104 | 
            +
                        shell_executor=Ssh.new(server_transfer_spec['remote_host'],server_transfer_spec['remote_user'],ssh_options)
         | 
| 105 | 
            +
                      when 'local'
         | 
| 106 | 
            +
                        shell_executor=LocalExecutor.new
         | 
| 107 | 
            +
                      else
         | 
| 108 | 
            +
                        raise CliError,'Only ssh scheme is supported in url' if !server_uri.scheme.eql?('ssh')
         | 
| 109 | 
            +
                      end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                      # get command and set aliases
         | 
| 112 | 
            +
                      command=self.options.get_next_command(ACTIONS)
         | 
| 113 | 
            +
                      command=:ls if command.eql?(:browse)
         | 
| 114 | 
            +
                      command=:rm if command.eql?(:delete)
         | 
| 115 | 
            +
                      command=:mv if command.eql?(:rename)
         | 
| 116 | 
            +
                      case command
         | 
| 117 | 
            +
                      when :nagios
         | 
| 118 | 
            +
                        nagios=Nagios.new
         | 
| 119 | 
            +
                        command_nagios=self.options.get_next_command([ :app_services, :transfer ])
         | 
| 120 | 
            +
                        case command_nagios
         | 
| 121 | 
            +
                        when :app_services
         | 
| 122 | 
            +
                          # will not work with aspshell, requires Linux/bash
         | 
| 123 | 
            +
                          procs=shell_executor.execute('ps -A -o comm').split("\n")
         | 
| 124 | 
            +
                          Log.log.debug("found: #{procs}")
         | 
| 125 | 
            +
                          ['asperanoded','asperaredisd'].each do |name|
         | 
| 126 | 
            +
                            nagios.add_critical('general',"missing process #{name}") unless procs.include?(name)
         | 
| 127 | 
            +
                          end
         | 
| 128 | 
            +
                          nagios.add_ok('daemons','ok') if nagios.data.empty?
         | 
| 129 | 
            +
                          return nagios.result
         | 
| 130 | 
            +
                        when :transfer
         | 
| 131 | 
            +
                          file = Tempfile.new('transfer_test')
         | 
| 132 | 
            +
                          filepath=file.path
         | 
| 133 | 
            +
                          file.write("This is a test file for transfer test")
         | 
| 134 | 
            +
                          file.close
         | 
| 135 | 
            +
                          probe_ts=server_transfer_spec.merge({
         | 
| 136 | 
            +
                            'direction'     => 'send',
         | 
| 137 | 
            +
                            'cookie'        => 'aspera.sync', # hide in console
         | 
| 138 | 
            +
                            'resume_policy' => 'none',
         | 
| 139 | 
            +
                            'paths'         => [{'source'=>filepath,'destination'=>'.fasping'}]
         | 
| 140 | 
            +
                          })
         | 
| 141 | 
            +
                          statuses=self.transfer.start(probe_ts,{:src=>:direct})
         | 
| 142 | 
            +
                          file.unlink
         | 
| 143 | 
            +
                          if TransferAgent.session_status(statuses).eql?(:success)
         | 
| 144 | 
            +
                            nagios.add_ok('transfer','ok')
         | 
| 145 | 
            +
                          else
         | 
| 146 | 
            +
                            nagios.add_critical('transfer',statuses.select{|i|!i.eql?(:success)}.first.to_s)
         | 
| 147 | 
            +
                          end
         | 
| 148 | 
            +
                        else raise "ERROR"
         | 
| 149 | 
            +
                        end
         | 
| 150 | 
            +
                        return nagios.result
         | 
| 151 | 
            +
                      when :nodeadmin,:userdata,:configurator,:ctl
         | 
| 152 | 
            +
                        realcmd='as'+command.to_s
         | 
| 153 | 
            +
                        prefix=self.options.get_option(:cmd_prefix,:optional)
         | 
| 154 | 
            +
                        if !prefix.nil?
         | 
| 155 | 
            +
                          realcmd="#{prefix}#{realcmd}"
         | 
| 156 | 
            +
                        end
         | 
| 157 | 
            +
                        args = self.options.get_next_argument("#{realcmd} arguments",:multiple)
         | 
| 158 | 
            +
                        result=shell_executor.execute(args.unshift(realcmd))
         | 
| 159 | 
            +
                        case command
         | 
| 160 | 
            +
                        when :ctl
         | 
| 161 | 
            +
                          return {:type=>:object_list,:data=>asctl_parse(result)}#
         | 
| 162 | 
            +
                        when :configurator
         | 
| 163 | 
            +
                          lines=result.split("\n")
         | 
| 164 | 
            +
                          Log.log.debug(`type asconfigurator`)
         | 
| 165 | 
            +
                          result=lines
         | 
| 166 | 
            +
                          if lines.first.eql?('success')
         | 
| 167 | 
            +
                            lines.shift
         | 
| 168 | 
            +
                            result={}
         | 
| 169 | 
            +
                            lines.each do |line|
         | 
| 170 | 
            +
                              Log.log.debug("#{line}")
         | 
| 171 | 
            +
                              data=line.split(',').map{|i|i.gsub(/^"/,'').gsub(/"$/,'')}.map{|i|case i;when'AS_NULL';nil;when'true';true;when'false';false;else i;end}
         | 
| 172 | 
            +
                              Log.log.debug("#{data}")
         | 
| 173 | 
            +
                              section=data.shift
         | 
| 174 | 
            +
                              datapart=result[section]||={}
         | 
| 175 | 
            +
                              if section.eql?('user')
         | 
| 176 | 
            +
                                name=data.shift
         | 
| 177 | 
            +
                                datapart=datapart[name]||={}
         | 
| 178 | 
            +
                              end
         | 
| 179 | 
            +
                              datapart=datapart[data.shift]={}
         | 
| 180 | 
            +
                              datapart['default']=data.pop
         | 
| 181 | 
            +
                              datapart['value']=data.pop
         | 
| 182 | 
            +
                            end
         | 
| 183 | 
            +
                            return {:type=>:single_object,:data=>result,:fields=>['section','name','value','default'],:option_expand_last=>true}
         | 
| 184 | 
            +
                          end
         | 
| 185 | 
            +
                        end
         | 
| 186 | 
            +
                        return Main.result_status(result)
         | 
| 187 | 
            +
                      when :upload
         | 
| 188 | 
            +
                        return Main.result_transfer(self.transfer.start(server_transfer_spec.merge('direction'=>'send'),{:src=>:direct}))
         | 
| 189 | 
            +
                      when :download
         | 
| 190 | 
            +
                        return Main.result_transfer(self.transfer.start(server_transfer_spec.merge('direction'=>'receive'),{:src=>:direct}))
         | 
| 191 | 
            +
                      when *Aspera::AsCmd::OPERATIONS
         | 
| 192 | 
            +
                        args=self.options.get_next_argument('ascmd command arguments',:multiple,:optional)
         | 
| 193 | 
            +
                        ascmd=Aspera::AsCmd.new(shell_executor)
         | 
| 194 | 
            +
                        begin
         | 
| 195 | 
            +
                          result=ascmd.send(:execute_single,command,args)
         | 
| 196 | 
            +
                          case command
         | 
| 197 | 
            +
                          when :mkdir;  return Main.result_success
         | 
| 198 | 
            +
                          when :mv;     return Main.result_success
         | 
| 199 | 
            +
                          when :cp;     return Main.result_success
         | 
| 200 | 
            +
                          when :rm;     return Main.result_success
         | 
| 201 | 
            +
                          when :ls;     return {:type=>:object_list,:data=>key_symb_to_str_list(result),:fields=>['zmode','zuid','zgid','size','mtime','name']}
         | 
| 202 | 
            +
                          when :info;   return {:type=>:single_object,:data=>key_symb_to_str_single(result)}
         | 
| 203 | 
            +
                          when :df;     return {:type=>:object_list,:data=>key_symb_to_str_list(result)}
         | 
| 204 | 
            +
                          when :du;     return {:type=>:single_object,:data=>key_symb_to_str_single(result)}
         | 
| 205 | 
            +
                          when :md5sum; return {:type=>:single_object,:data=>key_symb_to_str_single(result)}
         | 
| 206 | 
            +
                          end
         | 
| 207 | 
            +
                        rescue Aspera::AsCmd::Error => e
         | 
| 208 | 
            +
                          raise CliBadArgument,e.extended_message
         | 
| 209 | 
            +
                        end
         | 
| 210 | 
            +
                      else raise "internal error: unexpected action"
         | 
| 211 | 
            +
                      end
         | 
| 212 | 
            +
                    end # execute_action
         | 
| 213 | 
            +
                  end # Server
         | 
| 214 | 
            +
                end # Plugins
         | 
| 215 | 
            +
              end # Cli
         | 
| 216 | 
            +
            end # Aspera
         | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            require 'aspera/cli/plugins/node'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Aspera
         | 
| 4 | 
            +
              module Cli
         | 
| 5 | 
            +
                module Plugins
         | 
| 6 | 
            +
                  class Shares < BasicAuthPlugin
         | 
| 7 | 
            +
                    def initialize(env)
         | 
| 8 | 
            +
                      super(env)
         | 
| 9 | 
            +
                      #self.options.parse_options!
         | 
| 10 | 
            +
                    end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    ACTIONS=[ :repository,:admin ]
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    def execute_action
         | 
| 15 | 
            +
                      command=self.options.get_next_command(ACTIONS)
         | 
| 16 | 
            +
                      case command
         | 
| 17 | 
            +
                      when :repository
         | 
| 18 | 
            +
                        api_shares_node=basic_auth_api('node_api')
         | 
| 19 | 
            +
                        command=self.options.get_next_command(Node::COMMON_ACTIONS)
         | 
| 20 | 
            +
                        case command
         | 
| 21 | 
            +
                        when *Node::COMMON_ACTIONS; Node.new(@agents.merge(skip_basic_auth_options: true,node_api: api_shares_node)).execute_action(command)
         | 
| 22 | 
            +
                        else raise "INTERNAL ERROR, unknown command: [#{command}]"
         | 
| 23 | 
            +
                        end
         | 
| 24 | 
            +
                      when :admin
         | 
| 25 | 
            +
                        api_shares_admin=basic_auth_api('api/v1')
         | 
| 26 | 
            +
                        command=self.options.get_next_command([:user,:share])
         | 
| 27 | 
            +
                        case command
         | 
| 28 | 
            +
                        when :user
         | 
| 29 | 
            +
                          command=self.options.get_next_command([:list,:id])
         | 
| 30 | 
            +
                          case command
         | 
| 31 | 
            +
                          when :list
         | 
| 32 | 
            +
                            return {:type=>:object_list,:data=>api_shares_admin.read('data/users')[:data],:fields=>['username','email','directory_user','urn']}
         | 
| 33 | 
            +
                          when :id
         | 
| 34 | 
            +
                            res_id=self.options.get_next_argument('user id')
         | 
| 35 | 
            +
                            command=self.options.get_next_command([:app_authorizations,:authorize_share])
         | 
| 36 | 
            +
                            case command
         | 
| 37 | 
            +
                            when :app_authorizations
         | 
| 38 | 
            +
                              return {:type=>:single_object,:data=>api_shares_admin.read("data/users/#{res_id}/app_authorizations")[:data]}
         | 
| 39 | 
            +
                            when :share
         | 
| 40 | 
            +
                              share_name=self.options.get_next_argument('share name')
         | 
| 41 | 
            +
                              all_shares=api_shares_admin.read('data/shares')[:data]
         | 
| 42 | 
            +
                              share_id=all_shares.select{|s| s['name'].eql?(share_name)}.first['id']
         | 
| 43 | 
            +
                              return {:type=>:single_object,:data=>api_shares_admin.create("data/shares/#{share_id}/user_permissions")[:data]}
         | 
| 44 | 
            +
                            end
         | 
| 45 | 
            +
                          end
         | 
| 46 | 
            +
                        when :share
         | 
| 47 | 
            +
                          command=self.options.get_next_command([:list,:name])
         | 
| 48 | 
            +
                          all_shares=api_shares_admin.read('data/shares')[:data]
         | 
| 49 | 
            +
                          case command
         | 
| 50 | 
            +
                          when :list
         | 
| 51 | 
            +
                            return {:type=>:object_list,:data=>all_shares,:fields=>['id','name','status','status_message']}
         | 
| 52 | 
            +
                          when :name
         | 
| 53 | 
            +
                            share_name=self.options.get_next_argument('share name')
         | 
| 54 | 
            +
                            share_id=all_shares.select{|s| s['name'].eql?(share_name)}.first['id']
         | 
| 55 | 
            +
                            raise "TODO"
         | 
| 56 | 
            +
                          end
         | 
| 57 | 
            +
                        end
         | 
| 58 | 
            +
                      end
         | 
| 59 | 
            +
                    end # execute action
         | 
| 60 | 
            +
                  end # Shares
         | 
| 61 | 
            +
                end # Plugins
         | 
| 62 | 
            +
              end # Cli
         | 
| 63 | 
            +
            end # Aspera
         | 
| @@ -0,0 +1,114 @@ | |
| 1 | 
            +
            require 'aspera/cli/plugins/node'
         | 
| 2 | 
            +
            require 'uri'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Aspera
         | 
| 5 | 
            +
              module Cli
         | 
| 6 | 
            +
                module Plugins
         | 
| 7 | 
            +
                  class Shares2 < BasicAuthPlugin
         | 
| 8 | 
            +
                    def initialize(env)
         | 
| 9 | 
            +
                      super(env)
         | 
| 10 | 
            +
                      self.options.add_opt_simple(:organization,"organization")
         | 
| 11 | 
            +
                      self.options.add_opt_simple(:project,"project")
         | 
| 12 | 
            +
                      self.options.add_opt_simple(:share,"share")
         | 
| 13 | 
            +
                      self.options.parse_options!
         | 
| 14 | 
            +
                      return if env[:man_only]
         | 
| 15 | 
            +
                      unless env[:man_only]
         | 
| 16 | 
            +
                        # get parameters
         | 
| 17 | 
            +
                        shares2_api_base_url=self.options.get_option(:url,:mandatory)
         | 
| 18 | 
            +
                        shares2_username=self.options.get_option(:username,:mandatory)
         | 
| 19 | 
            +
                        shares2_password=self.options.get_option(:password,:mandatory)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                        # create object for REST calls to Shares2
         | 
| 22 | 
            +
                        @api_shares2_oauth=Rest.new({
         | 
| 23 | 
            +
                          :base_url => shares2_api_base_url,
         | 
| 24 | 
            +
                          :auth     => {
         | 
| 25 | 
            +
                          :type      => :oauth2,
         | 
| 26 | 
            +
                          :base_url  => shares2_api_base_url+'/oauth2',
         | 
| 27 | 
            +
                          :grant     => :header_userpass,
         | 
| 28 | 
            +
                          :user_name => shares2_username,
         | 
| 29 | 
            +
                          :user_pass => shares2_password
         | 
| 30 | 
            +
                          }})
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                        @api_node=Rest.new({
         | 
| 33 | 
            +
                          :base_url => shares2_api_base_url+'/node_api',
         | 
| 34 | 
            +
                          :auth     => {
         | 
| 35 | 
            +
                          :type     => :basic,
         | 
| 36 | 
            +
                          :username => shares2_username,
         | 
| 37 | 
            +
                          :password => shares2_password}})
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    # path_prefix is either "" or "res/id/"
         | 
| 42 | 
            +
                    # adds : prefix+"res/id/"
         | 
| 43 | 
            +
                    # modify parameter string
         | 
| 44 | 
            +
                    def set_resource_path_by_id_or_name(resource_path,resource_sym)
         | 
| 45 | 
            +
                      res_id=self.options.get_option(resource_sym,:mandatory)
         | 
| 46 | 
            +
                      # lets get the class path
         | 
| 47 | 
            +
                      resource_path<<resource_sym.to_s+'s'
         | 
| 48 | 
            +
                      # is this an integer ? or a name
         | 
| 49 | 
            +
                      if res_id.to_i.to_s != res_id
         | 
| 50 | 
            +
                        all=@api_shares2_oauth.read(resource_path)[:data]
         | 
| 51 | 
            +
                        one=all.select{|i|i['name'].start_with?(res_id)}
         | 
| 52 | 
            +
                        Log.log.debug(one)
         | 
| 53 | 
            +
                        raise CliBadArgument,"No matching name for #{res_id} in #{all}" if one.empty?
         | 
| 54 | 
            +
                        raise CliBadArgument,"More than one match: #{one}" if one.length > 1
         | 
| 55 | 
            +
                        res_id=one.first['id'].to_s
         | 
| 56 | 
            +
                      end
         | 
| 57 | 
            +
                      Log.log.debug("res_id=#{res_id}")
         | 
| 58 | 
            +
                      resource_path<<'/'+res_id+'/'
         | 
| 59 | 
            +
                      return resource_path
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    # path_prefix is empty or ends with slash
         | 
| 63 | 
            +
                    def process_entity_action(resource_sym,path_prefix)
         | 
| 64 | 
            +
                      resource_path=path_prefix+resource_sym.to_s+'s'
         | 
| 65 | 
            +
                      operations=[:list,:create,:delete]
         | 
| 66 | 
            +
                      command=self.options.get_next_command(operations)
         | 
| 67 | 
            +
                      case command
         | 
| 68 | 
            +
                      when :create
         | 
| 69 | 
            +
                        params=self.options.get_next_argument("creation data (json structure)")
         | 
| 70 | 
            +
                        resp=@api_shares2_oauth.create(resource_path,params)
         | 
| 71 | 
            +
                        return {:data=>resp[:data],:type => :other_struct}
         | 
| 72 | 
            +
                      when :list
         | 
| 73 | 
            +
                        default_fields=['id','name']
         | 
| 74 | 
            +
                        query=self.options.get_option(:query,:optional)
         | 
| 75 | 
            +
                        args=query.nil? ? nil : {'json_query'=>query}
         | 
| 76 | 
            +
                        Log.log.debug("#{args}".bg_red)
         | 
| 77 | 
            +
                        return {:data=>@api_shares2_oauth.read(resource_path,args)[:data],:fields=>default_fields,:type=>:object_list}
         | 
| 78 | 
            +
                      when :delete
         | 
| 79 | 
            +
                        @api_shares2_oauth.delete(set_resource_path_by_id_or_name(path_prefix,resource_sym))
         | 
| 80 | 
            +
                        return Main.result_status('deleted')
         | 
| 81 | 
            +
                      when :info
         | 
| 82 | 
            +
                        return {:type=>:other_struct,:data=>@api_shares2_oauth.read(set_resource_path_by_id_or_name(path_prefix,resource_sym),args)[:data]}
         | 
| 83 | 
            +
                      else raise :ERROR
         | 
| 84 | 
            +
                      end
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                    ACTIONS=[ :repository,:organization,:project,:team,:share,:appinfo,:userinfo,:admin]
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                    def execute_action
         | 
| 90 | 
            +
                      command=self.options.get_next_command(ACTIONS)
         | 
| 91 | 
            +
                      case command
         | 
| 92 | 
            +
                      when :repository
         | 
| 93 | 
            +
                        command=self.options.get_next_command(Node::COMMON_ACTIONS)
         | 
| 94 | 
            +
                        return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: @api_node)).execute_action(command)
         | 
| 95 | 
            +
                      when :appinfo
         | 
| 96 | 
            +
                        node_info=@api_node.call({:operation=>'GET',:subpath=>'app',:headers=>{'Accept'=>'application/json','Content-Type'=>'application/json'}})[:data]
         | 
| 97 | 
            +
                        return { :type=>:single_object ,:data => node_info }
         | 
| 98 | 
            +
                      when :userinfo
         | 
| 99 | 
            +
                        node_info=@api_node.call({:operation=>'GET',:subpath=>'current_user',:headers=>{'Accept'=>'application/json','Content-Type'=>'application/json'}})[:data]
         | 
| 100 | 
            +
                        return { :type=>:single_object ,:data => node_info }
         | 
| 101 | 
            +
                      when :organization,:project,:share,:team
         | 
| 102 | 
            +
                        prefix=''
         | 
| 103 | 
            +
                        set_resource_path_by_id_or_name(prefix,:organization) if [:project,:team,:share].include?(command)
         | 
| 104 | 
            +
                        set_resource_path_by_id_or_name(prefix,:project) if [:share].include?(command)
         | 
| 105 | 
            +
                        process_entity_action(command,prefix)
         | 
| 106 | 
            +
                      when :admin
         | 
| 107 | 
            +
                        command=self.options.get_next_command([:users,:groups,:nodes])
         | 
| 108 | 
            +
                        return self.entity_action(@api_shares2_oauth,"system/#{command}",nil,:id)
         | 
| 109 | 
            +
                      end # command
         | 
| 110 | 
            +
                    end # execute_action
         | 
| 111 | 
            +
                  end # Files
         | 
| 112 | 
            +
                end # Plugins
         | 
| 113 | 
            +
              end # Cli
         | 
| 114 | 
            +
            end # Aspera
         | 
| @@ -0,0 +1,65 @@ | |
| 1 | 
            +
            require 'aspera/cli/plugin'
         | 
| 2 | 
            +
            require 'aspera/sync'
         | 
| 3 | 
            +
            require 'aspera/log'
         | 
| 4 | 
            +
            require 'open3'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Aspera
         | 
| 7 | 
            +
              module Cli
         | 
| 8 | 
            +
                module Plugins
         | 
| 9 | 
            +
                  # list and download connect client versions, select FASP implementation
         | 
| 10 | 
            +
                  class Sync < Plugin
         | 
| 11 | 
            +
                    def initialize(env)
         | 
| 12 | 
            +
                      super(env)
         | 
| 13 | 
            +
                      self.options.add_opt_simple(:parameters,"extended value for session set definition")
         | 
| 14 | 
            +
                      self.options.add_opt_simple(:session_name,"name of session to use for admin commands, by default first one")
         | 
| 15 | 
            +
                      self.options.parse_options!
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    ACTIONS=[ :start, :admin ]
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def execute_action
         | 
| 21 | 
            +
                      command=self.options.get_next_command(ACTIONS)
         | 
| 22 | 
            +
                      case command
         | 
| 23 | 
            +
                      when :start
         | 
| 24 | 
            +
                        env_args=Aspera::Sync.new(self.options.get_option(:parameters,:mandatory)).compute_args
         | 
| 25 | 
            +
                        async_bin='async'
         | 
| 26 | 
            +
                        Log.log.debug("execute: #{env_args[:env].map{|k,v| "#{k}=\"#{v}\""}.join(' ')} \"#{async_bin}\" \"#{env_args[:args].join('" "')}\"")
         | 
| 27 | 
            +
                        res=system(env_args[:env],[async_bin,async_bin],*env_args[:args])
         | 
| 28 | 
            +
                        Log.log.debug("result=#{res}")
         | 
| 29 | 
            +
                        case res
         | 
| 30 | 
            +
                        when true; return Main.result_success
         | 
| 31 | 
            +
                        when false; raise "failed: #{$?}"
         | 
| 32 | 
            +
                        when nil; return Main.result_status("not started: #{$?}")
         | 
| 33 | 
            +
                        else raise "internal error: unspecified case"
         | 
| 34 | 
            +
                        end
         | 
| 35 | 
            +
                      when :admin
         | 
| 36 | 
            +
                        p=self.options.get_option(:parameters,:mandatory)
         | 
| 37 | 
            +
                        n=self.options.get_option(:session_name,:optional)
         | 
| 38 | 
            +
                        cmdline=['asyncadmin','--quiet']
         | 
| 39 | 
            +
                        if n.nil?
         | 
| 40 | 
            +
                          session=p['sessions'].first
         | 
| 41 | 
            +
                        else
         | 
| 42 | 
            +
                          session=p['sessions'].select{|s|s['name'].eql?(n)}.first
         | 
| 43 | 
            +
                        end
         | 
| 44 | 
            +
                        cmdline.push('--name='+session['name'])
         | 
| 45 | 
            +
                        if session.has_key?('local_db_dir')
         | 
| 46 | 
            +
                          cmdline.push('--local-db-dir='+session['local_db_dir'])
         | 
| 47 | 
            +
                        else
         | 
| 48 | 
            +
                          cmdline.push('--local-dir='+session['local_dir'])
         | 
| 49 | 
            +
                        end
         | 
| 50 | 
            +
                        command2=self.options.get_next_command([:status])
         | 
| 51 | 
            +
                        case command2
         | 
| 52 | 
            +
                        when :status
         | 
| 53 | 
            +
                          stdout, stderr, status = Open3.capture3(*cmdline)
         | 
| 54 | 
            +
                          Log.log.debug("status=#{status}, stderr=#{stderr}")
         | 
| 55 | 
            +
                          items=stdout.split("\n").inject({}){|m,l|i=l.split(/:  */);m[i.first.lstrip]=i.last.lstrip;m}
         | 
| 56 | 
            +
                          return {:type=>:single_object,:data=>items}
         | 
| 57 | 
            +
                        else raise "error"
         | 
| 58 | 
            +
                        end # command
         | 
| 59 | 
            +
                      else raise "error"
         | 
| 60 | 
            +
                      end # command
         | 
| 61 | 
            +
                    end # execute_action
         | 
| 62 | 
            +
                  end # Sync
         | 
| 63 | 
            +
                end # Plugins
         | 
| 64 | 
            +
              end # Cli
         | 
| 65 | 
            +
            end # Aspera
         |