prize 0.1.3 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3543934605bf4546fd1d189991fe2858eb28de2c33aef427b79743f59645f541
4
- data.tar.gz: 55975f3103e24701e27a76420eefa87f24c0b9d1d093bd130ff6afb233aef90a
3
+ metadata.gz: 1d04ff48aa10ea8ecf7c4d3883752b6082e14e9dbe395d1ca15aa5079a388f76
4
+ data.tar.gz: 503e2b620eaa9d999da44c1d3b4a4be599e07b1285bde96d2a2bb89faa5af7b7
5
5
  SHA512:
6
- metadata.gz: 831a82c2e98ecce891cdb1cef9bb05fa375e0fc77fc16c7e7375cf3a006b50111edc6327e5842cc514bb209381fe1393bde9bec04c62f0be9a0e2b06e67a92ce
7
- data.tar.gz: bc26873ce4457c95558c1d6c3f5e411a6ca2f9c43c9f28ff1cfb4b5175dbec15e5114e09f56595841def61069dd868148364aa0b3964d48ef2f8e0a4ede2719f
6
+ metadata.gz: 2a0c33a24361053e8d42fbcc3e12e046c750412ddae22bac7e682962e7c25b6808726abd130b7d96b8d70dfb5fb3e5410a098f8e7cdd774dad54945399da36e0
7
+ data.tar.gz: 773e13e85c2b228f89510808958ee3194272fcc8847a03606ec015fc0023ca6e22f0b9f86f89f905fbcf141377458d5dcc965bba5002ed79a113503c2f123234
data/.gitignore CHANGED
@@ -6,6 +6,3 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
-
10
- # rspec failure tracking
11
- .rspec_status
data/CODE_OF_CONDUCT.md CHANGED
@@ -68,7 +68,7 @@ members of the project's leadership.
68
68
  ## Attribution
69
69
 
70
70
  This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [http://contributor-covenant.org/version/1/4][version]
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
72
 
73
- [homepage]: http://contributor-covenant.org
74
- [version]: http://contributor-covenant.org/version/1/4/
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
3
  # Specify your gem's dependencies in prize.gemspec
6
4
  gemspec
5
+
6
+ gem "rake", "~> 12.0"
data/Gemfile.lock CHANGED
@@ -1,62 +1,64 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prize (0.1.3)
5
- activesupport
6
- hiredis (>= 0.6.0)
7
- pry (>= 0.12.0)
8
- redis (>= 4.0.0)
4
+ prize (0.3.1)
5
+ activesupport (~> 6.0.3)
6
+ hiredis (~> 0.6.0)
7
+ net-ssh-gateway (~> 2.0.0)
8
+ pry (~> 0.13.1)
9
+ pry-byebug (~> 3.9.0)
10
+ pry-doc (>= 1.0.0)
11
+ rainbow (~> 3.0.0)
12
+ redis (~> 4.0.0)
9
13
  thor (~> 0.20.0)
10
14
 
11
15
  GEM
12
16
  remote: https://rubygems.org/
13
17
  specs:
14
- activesupport (6.0.0)
18
+ activesupport (6.0.4.4)
15
19
  concurrent-ruby (~> 1.0, >= 1.0.2)
16
20
  i18n (>= 0.7, < 2)
17
21
  minitest (~> 5.1)
18
22
  tzinfo (~> 1.1)
19
- zeitwerk (~> 2.1, >= 2.1.8)
20
- coderay (1.1.2)
21
- concurrent-ruby (1.1.5)
22
- diff-lcs (1.3)
23
+ zeitwerk (~> 2.2, >= 2.2.2)
24
+ byebug (11.1.3)
25
+ coderay (1.1.3)
26
+ concurrent-ruby (1.1.9)
23
27
  hiredis (0.6.3)
24
- i18n (1.6.0)
28
+ i18n (1.8.11)
25
29
  concurrent-ruby (~> 1.0)
26
- method_source (0.9.2)
27
- minitest (5.12.2)
28
- pry (0.12.2)
29
- coderay (~> 1.1.0)
30
- method_source (~> 0.9.0)
31
- rake (10.5.0)
32
- redis (4.1.2)
33
- rspec (3.8.0)
34
- rspec-core (~> 3.8.0)
35
- rspec-expectations (~> 3.8.0)
36
- rspec-mocks (~> 3.8.0)
37
- rspec-core (3.8.2)
38
- rspec-support (~> 3.8.0)
39
- rspec-expectations (3.8.4)
40
- diff-lcs (>= 1.2.0, < 2.0)
41
- rspec-support (~> 3.8.0)
42
- rspec-mocks (3.8.1)
43
- diff-lcs (>= 1.2.0, < 2.0)
44
- rspec-support (~> 3.8.0)
45
- rspec-support (3.8.2)
30
+ method_source (1.0.0)
31
+ minitest (5.15.0)
32
+ net-ssh (6.1.0)
33
+ net-ssh-gateway (2.0.0)
34
+ net-ssh (>= 4.0.0)
35
+ pry (0.13.1)
36
+ coderay (~> 1.1)
37
+ method_source (~> 1.0)
38
+ pry-byebug (3.9.0)
39
+ byebug (~> 11.0)
40
+ pry (~> 0.13.0)
41
+ pry-doc (1.3.0)
42
+ pry (~> 0.11)
43
+ yard (~> 0.9.11)
44
+ rainbow (3.0.0)
45
+ rake (12.3.3)
46
+ redis (4.0.3)
46
47
  thor (0.20.3)
47
48
  thread_safe (0.3.6)
48
- tzinfo (1.2.5)
49
+ tzinfo (1.2.9)
49
50
  thread_safe (~> 0.1)
50
- zeitwerk (2.1.10)
51
+ webrick (1.7.0)
52
+ yard (0.9.27)
53
+ webrick (~> 1.7.0)
54
+ zeitwerk (2.5.3)
51
55
 
52
56
  PLATFORMS
53
57
  ruby
54
58
 
55
59
  DEPENDENCIES
56
- bundler (~> 1.17)
57
60
  prize!
58
- rake (~> 10.0)
59
- rspec (~> 3.0)
61
+ rake (~> 12.0)
60
62
 
61
63
  BUNDLED WITH
62
- 1.17.3
64
+ 2.1.2
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2019 Liu Xiang
3
+ Copyright (c) 2020 Liu Xiang
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/Rakefile CHANGED
@@ -1,6 +1,2 @@
1
1
  require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
2
  task :default => :spec
data/exe/prize CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'prize'
3
+ PrizeSetsidWrrapper = File.dirname(File.absolute_path(__FILE__)) + '/prize_setsid_wrapper'
4
+
5
+ require "prize"
4
6
 
5
7
  Prize::Cli.start
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ Process.setsid
4
+
5
+ exec(*ARGV)
data/lib/prize/app.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'net/ssh/gateway'
2
+ require 'redis'
3
+
4
+ module Prize
5
+ class App
6
+
7
+ class << self
8
+ attr_accessor :options, :redis, :redis_client
9
+ end
10
+
11
+ def initialize(options)
12
+ require 'active_support/all'
13
+ @options = options
14
+ load_initializer!
15
+ @redis = Redis.new(connect_options)
16
+ App.options = @options
17
+ App.redis = @redis
18
+ App.redis_client = @redis.instance_variable_get('@client')
19
+ end
20
+
21
+ def connect_options
22
+ opts = @options.to_h.slice(:url, :host, :port, :path, :db, :password, :timeout,
23
+ :connect_timeout, :replica, :cluster)
24
+ if @options.ssh_host
25
+ proxy = start_ssh_proxy!
26
+ opts.merge!(proxy)
27
+ end
28
+ opts
29
+ end
30
+
31
+ def load_initializer!
32
+ if File.exists?(File.expand_path('~/.prizerc'))
33
+ load(File.expand_path('~/.prizerc'))
34
+ end
35
+ end
36
+
37
+ def start_ssh_proxy!
38
+ ssh_config = {
39
+ host: @options.ssh_host,
40
+ forward_host: @options.host || '127.0.0.1',
41
+ forward_port: @options.port || 6379
42
+ }
43
+ @options.ssh_user.try { |e| ssh_config.merge!(user: e) }
44
+ @options.ssh_port.try { |e| ssh_config.merge!(port: e) }
45
+ @options.ssh_password.try { |e| ssh_config.merge!(password: e) }
46
+ @options.ssh_local_port.try { |e| ssh_config.merge!(local_port: e) }
47
+ local_ssh_proxy_port = Prize::SSHProxy.connect(ssh_config)
48
+ {
49
+ host: '127.0.0.1',
50
+ port: local_ssh_proxy_port
51
+ }
52
+ end
53
+
54
+ def run!
55
+ if @options.code.present?
56
+ @redis.instance_eval(@options.code)
57
+ elsif @options.args.present?
58
+ @options.args.each do |rb|
59
+ @redis.instance_eval(IO.read(rb))
60
+ end
61
+ elsif STDIN.isatty
62
+ run_repl!
63
+ else
64
+ @redis.instance_eval(STDIN.read)
65
+ end
66
+ end
67
+
68
+ def run_repl!
69
+ Repl.new
70
+ end
71
+ end
72
+ end
data/lib/prize/cli.rb CHANGED
@@ -1,58 +1,100 @@
1
- require 'thor'
2
- require 'redis'
3
- require 'hiredis'
4
- require 'pry'
1
+ require 'optparse'
2
+ require 'ostruct'
5
3
 
6
4
  module Prize
7
- class Cli < ::Thor
8
-
9
- default_command :main
10
-
11
- desc '', 'Simple Redis CLI client with Pry loaded'
12
- class_option :url, type: :string, aliases: ['-u'], required: false, desc: 'Server URL, for a TCP connection: `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket connection: `unix://[path to Redis socket]`. This overrides all other options.'
13
- class_option :host, type: :string, aliases: ['-h'], required: false, desc: 'Server hostname (default: 127.0.0.1)'
14
- class_option :port, type: :numeric, aliases: ['-p'], required: false, desc: 'Server port (default: 6379)'
15
- class_option :path, type: :string, aliases: ['-s', '--socket'], required: false, desc: 'Server socket (overrides hostname and port)'
16
- class_option :timeout, type: :numeric, required: false, desc: 'Timeout in seconds (default: 5.0)'
17
- class_option :connect_timeout, type: :numeric, required: false, desc: 'Timeout for initial connect in seconds (default: same as timeout)'
18
- class_option :password, type: :string, aliases: ['-a'], required: false, desc: 'Password to authenticate against server'
19
- class_option :db, type: :numeric, aliases: ['-n'], required: false, desc: 'Database number (default: 0)'
20
- class_option :replica, type: :boolean, required: false, desc: 'Whether to use readonly replica nodes in Redis Cluster or not'
21
- class_option :cluster, type: :string, required: false, desc: 'List of cluster nodes to contact, format: URL1,URL2,URL3...'
22
- def main
23
- redis = Redis.new(build_options)
24
- Pry.config.prompt = build_prompt(redis)
25
- if File.exists?(File.expand_path('~/.prizerc'))
26
- Pry.load_file_at_toplevel(File.expand_path('~/.prizerc'))
5
+ class Cli
6
+ class << self
7
+ def start
8
+ parse_options!
9
+ App.new(@options).run!
27
10
  end
28
- Pry.start(redis)
29
- end
30
11
 
31
- no_commands do
32
- def build_options
33
- opts = options.to_h.merge(driver: :hiredis)
34
- opts['cluster'] = opts['cluster'].split(',') if opts['cluster']
35
- opts
36
- end
12
+ def parse_options!
13
+ @options = OpenStruct.new
14
+
15
+
16
+ OptionParser.new do |opts|
17
+ opts.banner = <<~EOF
18
+ Usage: prize [options]
19
+ EOF
20
+
21
+ opts.on('-uURL', '--url=URL', 'Server URL, for a TCP connection: `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket connection: `unix://[path to Redis socket]`. This overrides all other options.') do |url|
22
+ @options.url = url
23
+ end
24
+
25
+ opts.on('-hHOST', '--host=HOST', 'Server hostname (default: 127.0.0.1)') do |host|
26
+ @options.host = host
27
+ end
28
+
29
+ opts.on('-pPORT', '--port=PORT', 'Server port (default: 6379)') do |port|
30
+ @options.port = port.to_i
31
+ end
32
+
33
+ opts.on('-sPATH', '--sock=PATH', 'Server socket (overrides hostname and port)') do |path|
34
+ @options.path = path
35
+ end
36
+
37
+ opts.on('-dDB', '--db=DB', 'Specify database') do |db|
38
+ @options.db = db
39
+ end
40
+
41
+ opts.on('-PPASSWORD', '--password=PASSWORD', 'Specify password') do |password|
42
+ @options.password = password
43
+ end
44
+
45
+ opts.on('', '--timeout=TIMEOUT', 'Timeout in seconds (default: 5.0)') do |timeout|
46
+ @options.timeout = timeout.to_i
47
+ end
48
+
49
+ opts.on('', '--connect-timeout=TIMEOUT', 'Timeout for initial connect in seconds (default: same as timeout)') do |timeout|
50
+ @options.connect_timeout = timeout.to_i
51
+ end
52
+
53
+ opts.on('', '--replica', 'Whether to use readonly replica nodes in Redis Cluster or not') do
54
+ @options.replica = true
55
+ end
56
+
57
+ opts.on('', '--cluster=CLUSTER_URL', 'List of cluster nodes to contact, format: URL1,URL2,URL3...') do |cluster|
58
+ @options.cluster = cluster.split(',')
59
+ end
60
+
61
+ opts.on('-HSSH_HOST', '--ssh-host=SSH_HOST', 'Specify SSH host') do |ssh_host|
62
+ @options.ssh_host = ssh_host
63
+ end
64
+
65
+ opts.on('-OSSH_PORT', '--ssh-port=SSH_PORT', 'Specify SSH port') do |ssh_port|
66
+ @options.ssh_port = ssh_port.to_i
67
+ end
68
+
69
+ opts.on('-USSH_USER', '--ssh-user=SSH_USER', 'Specify SSH user') do |ssh_user|
70
+ @options.ssh_user = ssh_user
71
+ end
72
+
73
+ opts.on('-WSSH_PASSWORD', '--ssh-password=SSH_PASSWORD', 'Specify SSH password') do |ssh_password|
74
+ @options.ssh_password = ssh_password
75
+ end
76
+
77
+ opts.on('-LSSH_LOCAL_PORT', '--ssh-local-port=SSH_LOCAL_PORT', 'Specify local SSH proxy port') do |local_port|
78
+ @options.ssh_local_port = local_port.to_i
79
+ end
80
+
81
+ opts.on('-ECODE', '--eval=CODE', 'evaluate CODE') do |code|
82
+ @options.code = code
83
+ end
84
+
85
+ opts.on('-V', '--version', 'Prints version') do
86
+ puts "PRIZE #{Prize::VERSION}"
87
+ exit
88
+ end
89
+
90
+ opts.on('', '--help', 'Prints this help') do
91
+ puts opts
92
+ exit
93
+ end
94
+
95
+ end.parse!
37
96
 
38
- def build_prompt(redis)
39
- opts = redis.instance_variable_get('@client').options
40
- host = opts[:url] || opts[:path] || "#{opts[:host]}:#{opts[:port]}/#{opts[:db]}"
41
- prompt_fn = proc do |obj, nest_level, _|
42
- p = ""
43
- p += if obj == redis
44
- "Redis<#{host}>:"
45
- else
46
- "#{obj}:"
47
- end
48
- p += "#{nest_level}> "
49
- end
50
-
51
- [prompt_fn,
52
- proc do |obj, nest_level, other|
53
- "*#{prompt_fn.call obj, nest_level, other}"
54
- end
55
- ]
97
+ @options.args = ARGV
56
98
  end
57
99
  end
58
100
  end
@@ -0,0 +1,48 @@
1
+ require 'rainbow'
2
+
3
+ module Prize::Commands
4
+ module Info
5
+ class << self
6
+ def db_info
7
+ <<~EOF
8
+
9
+ Redis Connection Information:
10
+
11
+ Active: #{color_boolean(Prize::App.redis_client.connected?)}
12
+ Host: #{Prize::App.options.host || '127.0.0.1'}
13
+ Port: #{Prize::App.options.port || 6379}
14
+ Password: #{(Prize::App.options.password || '').gsub(/./, '*')}
15
+ Database: #{Prize::App.options.db || 0}
16
+ EOF
17
+ end
18
+
19
+ def ssh_info
20
+ <<~EOF
21
+
22
+ SSH Connection Information:
23
+
24
+ Active: #{color_boolean(Prize::SSHProxy.active?)}
25
+ Host: #{Prize::App.options.ssh_host}
26
+ Port: #{Prize::App.options.ssh_port || ''}
27
+ Username: #{Prize::App.options.ssh_user}
28
+ Password: #{(Prize::App.options.ssh_password || '').gsub(/./, '*')}
29
+ Local Port: #{Prize::SSHProxy.local_ssh_proxy_port}
30
+ EOF
31
+ end
32
+
33
+ private
34
+ def color_boolean(bool)
35
+ if bool
36
+ Rainbow('TRUE').green
37
+ else
38
+ Rainbow('FALSE').red
39
+ end
40
+ end
41
+ end
42
+
43
+ Pry.commands.block_command 'inf' do
44
+ puts Info::db_info
45
+ puts Info::ssh_info if Prize::App.options.ssh_host.present?
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ module Prize::Commands
2
+ module Reconnect
3
+ class << self
4
+ def reconnect
5
+ Prize::SSHProxy.reconnect if Prize::App.options.ssh_host.present?
6
+ Prize::App.redis_client.reconnect unless Prize::App.redis_client.connected?
7
+ end
8
+
9
+ def reconnect!
10
+ Prize::SSHProxy.reconnect! if Prize::App.options.ssh_host.present?
11
+ Prize::App.redis_client.reconnect
12
+ end
13
+ end
14
+
15
+ Pry.commands.block_command 'reconnect' do
16
+ Reconnect.reconnect
17
+ end
18
+
19
+ Pry.commands.block_command 'reconnect!' do
20
+ Reconnect.reconnect!
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ require 'prize/commands/info'
2
+ require 'prize/commands/reconnect'
3
+
4
+ module Prize::Commands
5
+ end
@@ -0,0 +1,18 @@
1
+ class Object
2
+
3
+ def j
4
+ to_json
5
+ end
6
+
7
+ def jj
8
+ JSON.pretty_generate(JSON.parse(to_json))
9
+ end
10
+
11
+ def jp
12
+ puts j
13
+ end
14
+
15
+ def jjp
16
+ puts jj
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def p
3
+ puts self
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'active_support/core_ext/time/conversions'
2
+ require 'active_support/core_ext/object/json'
3
+
4
+ class Time
5
+ DATE_FORMATS ||= {}
6
+ DATE_FORMATS[:default] = '%Y-%m-%d %H:%M:%S'
7
+
8
+ def inspect
9
+ to_s
10
+ end
11
+
12
+ def as_json(*args)
13
+ to_s
14
+ end
15
+ end
data/lib/prize/ext.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'prize/ext/object'
2
+ require 'prize/ext/time'
3
+ require 'prize/ext/string'
data/lib/prize/id.rb ADDED
@@ -0,0 +1,59 @@
1
+ module Prize
2
+ class ID
3
+ @worker_id_bits = 5
4
+ @data_center_id_bits = 5
5
+ @max_worker_id = -1 ^ (-1 << @worker_id_bits)
6
+ @max_data_center_id = -1 ^ (-1 << @data_center_id_bits)
7
+
8
+ @sequence_bits = 12
9
+ @worker_id_shift = @sequence_bits
10
+ @data_center_id_shift = @sequence_bits + @worker_id_shift
11
+ @timestamp_left_shift = @sequence_bits + @worker_id_bits + @data_center_id_bits
12
+ @sequence_mask = -1 ^ (-1 << @sequence_bits)
13
+
14
+ @id_epoch = (Time.new(2018, 1, 1, 0, 0, 0).to_f * 1000).to_i
15
+ @worker_id = 0
16
+ @data_center_id = 0
17
+ @sequence = 0
18
+
19
+ @last_timestamp = -1
20
+
21
+ class << self
22
+ def long
23
+ ts = (Time.now.to_f * 1000).to_i
24
+ if ts < @last_timestamp
25
+ raise 'Clock moved backwards.'
26
+ end
27
+
28
+ if ts == @last_timestamp
29
+ @sequence = (@sequence + 1) & @sequence_mask
30
+ if (@sequence == 0)
31
+ ts = til_next_millis(@last_timestamp)
32
+ end
33
+ else
34
+ @sequence = 0
35
+ end
36
+ @last_timestamp = ts
37
+
38
+ ((ts - @id_epoch) << @timestamp_left_shift) | (@data_center_id << @data_center_id_shift) | (@worker_id << @worker_id_shift) | @sequence
39
+ end
40
+
41
+ def uuid
42
+ require 'securerandom'
43
+ SecureRandom.uuid.gsub('-', '')
44
+ end
45
+
46
+ private
47
+
48
+ def til_next_millis(last_timestamp)
49
+ ts = (Time.now.to_f * 1000).to_i
50
+ while ts <= last_timestamp
51
+ ts = (Time.now.to_f * 1000).to_i
52
+ end
53
+ ts
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ ::ID = Prize::ID
data/lib/prize/repl.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'pry'
2
+ require 'pry-byebug'
3
+ require 'prize/commands'
4
+ require 'rainbow'
5
+
6
+ module Prize
7
+ class Repl
8
+ def initialize
9
+ @redis = App.redis
10
+ Pry.config.prompt = Pry::Prompt.new("", "", prompt)
11
+ Pry.start(@redis)
12
+ end
13
+
14
+ def prompt
15
+ opts = @redis.instance_variable_get('@client').options
16
+ if App.options.ssh_host
17
+ host = "#{App.options.ssh_host}:#{App.options.host || '127.0.0.1'}:#{App.options.port || 6379}/#{opts[:db]}"
18
+ else
19
+ host = opts[:url] || opts[:path] || "#{opts[:host]}:#{opts[:port]}/#{opts[:db]}"
20
+ end
21
+ [proc do |obj, nest_level, _|
22
+ if obj == @redis && nest_level == 0
23
+ nest_level_prompt = ''
24
+ else
25
+ nest_level_prompt = "(#{obj}:#{nest_level})"
26
+ end
27
+ "%s#{Rainbow('@').green}%s#{nest_level_prompt} %s " % [Rainbow('PRIZE').red, Rainbow(host).yellow, Rainbow('❯').green]
28
+ end]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require 'net/ssh/gateway'
2
+ require 'prize/ssh_proxy_patch'
3
+
4
+ module Prize
5
+ class SSHProxy
6
+ class << self
7
+
8
+ attr_accessor :config, :ssh_gateway, :local_ssh_proxy_port
9
+
10
+ def connect(config)
11
+ @config = config
12
+ @ssh_gateway = Net::SSH::Gateway.new(config[:host], config[:user], config.slice(:port, :password).symbolize_keys.merge(keepalive: true, keepalive_interval: 30, loop_wait: 1))
13
+ @local_ssh_proxy_port = @ssh_gateway.open(config[:forward_host], config[:forward_port], config[:local_port])
14
+ end
15
+
16
+ def reconnect
17
+ reconnect! unless @ssh_gateway.active?
18
+ end
19
+
20
+ def reconnect!
21
+ @ssh_gateway.shutdown!
22
+ @ssh_gateway = Net::SSH::Gateway.new(@config[:host], @config[:user], @config.slice(:port, :password).symbolize_keys)
23
+ @ssh_gateway.open(config[:forward_host], config[:forward_port], @local_ssh_proxy_port)
24
+ end
25
+
26
+ def active?
27
+ @ssh_gateway.active?
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,88 @@
1
+ require 'net/ssh/proxy/command'
2
+
3
+ module Net
4
+ module SSH
5
+ module Proxy
6
+ class Command
7
+
8
+ # Return a new socket connected to the given host and port via the
9
+ # proxy that was requested when the socket factory was instantiated.
10
+ def open(host, port, connection_options = nil)
11
+ command_line = @command_line_template.gsub(/%(.)/) {
12
+ case $1
13
+ when 'h'
14
+ host
15
+ when 'p'
16
+ port.to_s
17
+ when 'r'
18
+ remote_user = connection_options && connection_options[:remote_user]
19
+ if remote_user
20
+ remote_user
21
+ else
22
+ raise ArgumentError, "remote user name not available"
23
+ end
24
+ when '%'
25
+ '%'
26
+ else
27
+ raise ArgumentError, "unknown key: #{$1}"
28
+ end
29
+ }
30
+ command_line = '%s %s' % [PrizeSetsidWrrapper, command_line]
31
+ begin
32
+ io = IO.popen(command_line, "r+")
33
+ begin
34
+ if result = IO.select([io], nil, [io], @timeout)
35
+ if result.last.any? || io.eof?
36
+ raise "command failed"
37
+ end
38
+ else
39
+ raise "command timed out"
40
+ end
41
+ rescue StandardError
42
+ close_on_error(io)
43
+ raise
44
+ end
45
+ rescue StandardError => e
46
+ raise ConnectError, "#{e}: #{command_line}"
47
+ end
48
+ @command_line = command_line
49
+ if Gem.win_platform?
50
+ # read_nonblock and write_nonblock are not available on Windows
51
+ # pipe. Use sysread and syswrite as a replacement works.
52
+ def io.send(data, flag)
53
+ syswrite(data)
54
+ end
55
+
56
+ def io.recv(size)
57
+ sysread(size)
58
+ end
59
+ else
60
+ def io.send(data, flag)
61
+ begin
62
+ result = write_nonblock(data)
63
+ rescue IO::WaitWritable, Errno::EINTR
64
+ IO.select(nil, [self])
65
+ retry
66
+ end
67
+ result
68
+ end
69
+
70
+ def io.recv(size)
71
+ begin
72
+ result = read_nonblock(size)
73
+ rescue IO::WaitReadable, Errno::EINTR
74
+ timeout_in_seconds = 20
75
+ if IO.select([self], nil, [self], timeout_in_seconds) == nil
76
+ raise "Unexpected spurious read wakeup"
77
+ end
78
+ retry
79
+ end
80
+ result
81
+ end
82
+ end
83
+ io
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
data/lib/prize/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Prize
2
- VERSION = "0.1.3"
2
+ VERSION = "0.3.1"
3
3
  end
data/lib/prize.rb CHANGED
@@ -1,2 +1,10 @@
1
1
  require "prize/version"
2
+ require 'prize/id'
3
+ require 'prize/ext'
4
+ require "prize/repl"
5
+ require "prize/ssh_proxy"
6
+ require "prize/app"
2
7
  require "prize/cli"
8
+
9
+ module Prize
10
+ end
data/prize.gemspec CHANGED
@@ -1,7 +1,4 @@
1
-
2
- lib = File.expand_path("../lib", __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "prize/version"
1
+ require_relative 'lib/prize/version'
5
2
 
6
3
  Gem::Specification.new do |spec|
7
4
  spec.name = "prize"
@@ -13,7 +10,7 @@ Gem::Specification.new do |spec|
13
10
  spec.description = %{Simple Redis CLI client with pry loaded}
14
11
  spec.homepage = "https://github.com/lululau/prize"
15
12
  spec.license = "MIT"
16
-
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
17
14
 
18
15
  # Specify which files should be added to the gem when it is released.
19
16
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -24,13 +21,13 @@ Gem::Specification.new do |spec|
24
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
22
  spec.require_paths = ["lib"]
26
23
 
27
- spec.add_dependency 'activesupport'
28
- spec.add_dependency 'redis', '>= 4.0.0'
29
- spec.add_dependency 'hiredis', '>= 0.6.0'
24
+ spec.add_dependency 'activesupport', '~> 6.0.3'
25
+ spec.add_dependency 'net-ssh-gateway', '~> 2.0.0'
26
+ spec.add_dependency 'pry', '~> 0.13.1'
27
+ spec.add_dependency 'pry-byebug', '~> 3.9.0'
28
+ spec.add_dependency 'pry-doc', '>= 1.0.0'
29
+ spec.add_dependency 'rainbow', '~> 3.0.0'
30
+ spec.add_dependency 'redis', '~> 4.0.0'
31
+ spec.add_dependency 'hiredis', '~> 0.6.0'
30
32
  spec.add_dependency 'thor', '~> 0.20.0'
31
- spec.add_dependency 'pry', '>= 0.12.0'
32
-
33
- spec.add_development_dependency "bundler", "~> 1.17"
34
- spec.add_development_dependency "rake", "~> 10.0"
35
- spec.add_development_dependency "rspec", "~> 3.0"
36
33
  end
metadata CHANGED
@@ -1,138 +1,151 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liu Xiang
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-18 00:00:00.000000000 Z
11
+ date: 2022-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 6.0.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 6.0.3
27
27
  - !ruby/object:Gem::Dependency
28
- name: redis
28
+ name: net-ssh-gateway
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 4.0.0
33
+ version: 2.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 4.0.0
40
+ version: 2.0.0
41
41
  - !ruby/object:Gem::Dependency
42
- name: hiredis
42
+ name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.6.0
47
+ version: 0.13.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.6.0
54
+ version: 0.13.1
55
55
  - !ruby/object:Gem::Dependency
56
- name: thor
56
+ name: pry-byebug
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.20.0
61
+ version: 3.9.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.20.0
68
+ version: 3.9.0
69
69
  - !ruby/object:Gem::Dependency
70
- name: pry
70
+ name: pry-doc
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: 0.12.0
75
+ version: 1.0.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 0.12.0
82
+ version: 1.0.0
83
83
  - !ruby/object:Gem::Dependency
84
- name: bundler
84
+ name: rainbow
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '1.17'
90
- type: :development
89
+ version: 3.0.0
90
+ type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '1.17'
96
+ version: 3.0.0
97
97
  - !ruby/object:Gem::Dependency
98
- name: rake
98
+ name: redis
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '10.0'
104
- type: :development
103
+ version: 4.0.0
104
+ type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '10.0'
110
+ version: 4.0.0
111
111
  - !ruby/object:Gem::Dependency
112
- name: rspec
112
+ name: hiredis
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '3.0'
118
- type: :development
117
+ version: 0.6.0
118
+ type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '3.0'
124
+ version: 0.6.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: thor
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.20.0
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.20.0
125
139
  description: Simple Redis CLI client with pry loaded
126
140
  email:
127
141
  - liuxiang921@gmail.com
128
142
  executables:
129
143
  - prize
144
+ - prize_setsid_wrapper
130
145
  extensions: []
131
146
  extra_rdoc_files: []
132
147
  files:
133
148
  - ".gitignore"
134
- - ".rspec"
135
- - ".travis.yml"
136
149
  - CODE_OF_CONDUCT.md
137
150
  - Gemfile
138
151
  - Gemfile.lock
@@ -142,15 +155,28 @@ files:
142
155
  - bin/console
143
156
  - bin/setup
144
157
  - exe/prize
158
+ - exe/prize_setsid_wrapper
145
159
  - lib/prize.rb
160
+ - lib/prize/app.rb
146
161
  - lib/prize/cli.rb
162
+ - lib/prize/commands.rb
163
+ - lib/prize/commands/info.rb
164
+ - lib/prize/commands/reconnect.rb
165
+ - lib/prize/ext.rb
166
+ - lib/prize/ext/object.rb
167
+ - lib/prize/ext/string.rb
168
+ - lib/prize/ext/time.rb
169
+ - lib/prize/id.rb
170
+ - lib/prize/repl.rb
171
+ - lib/prize/ssh_proxy.rb
172
+ - lib/prize/ssh_proxy_patch.rb
147
173
  - lib/prize/version.rb
148
174
  - prize.gemspec
149
175
  homepage: https://github.com/lululau/prize
150
176
  licenses:
151
177
  - MIT
152
178
  metadata: {}
153
- post_install_message:
179
+ post_install_message:
154
180
  rdoc_options: []
155
181
  require_paths:
156
182
  - lib
@@ -158,15 +184,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
184
  requirements:
159
185
  - - ">="
160
186
  - !ruby/object:Gem::Version
161
- version: '0'
187
+ version: 2.3.0
162
188
  required_rubygems_version: !ruby/object:Gem::Requirement
163
189
  requirements:
164
190
  - - ">="
165
191
  - !ruby/object:Gem::Version
166
192
  version: '0'
167
193
  requirements: []
168
- rubygems_version: 3.0.6
169
- signing_key:
194
+ rubygems_version: 3.3.3
195
+ signing_key:
170
196
  specification_version: 4
171
197
  summary: Simple Redis CLI client with pry loaded
172
198
  test_files: []
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
data/.travis.yml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.6.2
7
- before_install: gem install bundler -v 1.17.2