canals 0.9.0 → 0.9.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
- SHA1:
3
- metadata.gz: 8e283a22a7f6c82810b5d6882f43261d52049c43
4
- data.tar.gz: 3241f8e7db64722f49d194fcd7913e9c03d3276a
2
+ SHA256:
3
+ metadata.gz: 9bc1163849df66d22bad8690d09e21a9bce8a69b25b1b433f76129cfe3e540b2
4
+ data.tar.gz: 2b7df31c017d857e1eef4e85e92e3be608729020e953ed750d82c1cee57ee7f0
5
5
  SHA512:
6
- metadata.gz: 70c882e0a9523ac94c4f4fc752952e00250234c6ab41fa437c942e7ec01fcef08f7ddfb441c2d04fa1a6a91aab4f62c73a56bd1bde751145be44d0f2aef597d6
7
- data.tar.gz: fdaf278face0c256fac3f38db681f4fdaef3bd30161d59037acf1c6c59dceaf8c3b0e256c8eeb8b406bb6e7a2a401d5b853c19aa803cebc1739e5600e015dc92
6
+ metadata.gz: b936391c6d89a681e3e80090e15f5daf0c76a0968aa1b3bd7aac79a6cf259ad688d85ddbf5cee8823e35d182cf0218a6d9f616c2a0bd1ec69d6053f08f5f4243
7
+ data.tar.gz: c5ab2225ca01e9c6473d35090c06713ae7696630d3c118f34ffabf5ed8b9140b5999bf3dc2ab890ac3062f9b688abdbfb048a444cab7fcdd3d3a20d5012faaa1
data/assets/canals.sh CHANGED
@@ -10,7 +10,7 @@ _canal_complete() {
10
10
  # Setup the base level (everything after "canal")
11
11
  if [ $COMP_CWORD -eq 1 ]; then
12
12
  COMPREPLY=( $(compgen \
13
- -W "adhoc create environment help repo restart session setup start stop update" \
13
+ -W "adhoc create environment help repo restart session setup socks start stop update" \
14
14
  -- $cur) )
15
15
  return 0
16
16
  fi
data/canals.gemspec CHANGED
@@ -20,8 +20,8 @@ Gem::Specification.new do |s|
20
20
  s.require_path = "lib"
21
21
  s.license = "MIT"
22
22
 
23
- s.add_dependency 'thor', '~> 0.19.1'
24
- s.add_dependency 'terminal-table', '~> 1.5'
23
+ s.add_dependency 'thor', '~> 0.20.3'
24
+ s.add_dependency 'terminal-table', '~> 1.8'
25
25
 
26
26
  s.add_development_dependency 'rspec', '~> 3.4'
27
27
  end
data/lib/canals/cli.rb CHANGED
@@ -32,7 +32,7 @@ module Canals
32
32
  method_option :user, :type => :string, :desc => "The user for the ssh proxy host"
33
33
  method_option :bind_address, :type => :string, :desc => "The bind address to connect to"
34
34
  def create(name, remote_host, remote_port, local_port=nil)
35
- opts = {"name" => name, "remote_host" => remote_host, "remote_port" => remote_port, "local_port" => local_port}.merge(options)
35
+ opts = {name: name, remote_host: remote_host, remote_port: remote_port, local_port: local_port}.merge(options)
36
36
  opts = Canals::CanalOptions.new(opts)
37
37
  Canals.create_tunnel(opts)
38
38
  say "Tunnel #{name.inspect} created.", :green
@@ -40,13 +40,13 @@ module Canals
40
40
 
41
41
  desc 'delete NAME', "Delete an existing tunnel; if tunnel is active, stop it first"
42
42
  def delete(name)
43
- tunnel = Canals.repository.get(name)
43
+ tunnel = Canals.repository.get(name.to_sym)
44
44
  if tunnel.nil?
45
45
  say "couldn't find tunnel #{name.inspect}. try using 'create' instead", :red
46
46
  return
47
47
  end
48
48
  tstop(name, silent: true)
49
- Canals.repository.delete(name)
49
+ Canals.repository.delete(name.to_sym)
50
50
  say "Tunnel #{name.inspect} deleted.", :green
51
51
  end
52
52
 
@@ -59,7 +59,7 @@ module Canals
59
59
  method_option :user, :type => :string, :desc => "The user for the ssh proxy host"
60
60
  method_option :bind_address, :type => :string, :desc => "The bind address to connect to"
61
61
  def update(name)
62
- tunnel = Canals.repository.get(name)
62
+ tunnel = Canals.repository.get(name.to_sym)
63
63
  if tunnel.nil?
64
64
  say "couldn't find tunnel #{name.inspect}. try using 'create' instead", :red
65
65
  return
@@ -136,6 +136,21 @@ module Canals
136
136
  tstart(opts)
137
137
  end
138
138
 
139
+
140
+ desc "socks LOCAL_PORT", "Create and run a socks connection"
141
+ method_option :name, :type => :string, :desc => "The name to use for the socks tunnel, if not supplied a template will be generated"
142
+ method_option :env, :type => :string, :desc => "The proxy environment to use"
143
+ method_option :hostname, :type => :string, :desc => "The proxy host we will use to connect through"
144
+ method_option :user, :type => :string, :desc => "The user for the ssh socks host"
145
+ method_option :bind_address, :type => :string, :desc => "The bind address to connect to"
146
+ def socks(local_port)
147
+ opts = {"adhoc" => true, "socks" => true, "local_port" => local_port}.merge(options)
148
+ opts["name"] ||= "__SOCKS__"
149
+ opts = Canals::CanalOptions.new(opts)
150
+ opts.name = "SOCKS-adhoc-#{opts.hostname}-#{local_port}" if opts.name == "__SOCKS__"
151
+ tstart(opts)
152
+ end
153
+
139
154
  desc "environment SUBCOMMAND", "Environment related command (use 'canal environment help' to find out more)"
140
155
  subcommand "environment", Canals::Cli::Environment
141
156
 
@@ -3,7 +3,6 @@ require 'canals/options'
3
3
  require 'canals/environment'
4
4
  require 'thor'
5
5
 
6
-
7
6
  module Canals
8
7
  module Cli
9
8
  class Environment < Thor
@@ -19,8 +18,8 @@ module Canals
19
18
  host = hostname
20
19
  user = nil
21
20
  end
22
- opts = {"name" => name, "hostname" => host}.merge(options)
23
- opts["user"] = user if !user.nil?
21
+ opts = {name: name, hostname: host}.merge(options)
22
+ opts[:user] = user if !user.nil?
24
23
  env = Canals::Environment.new(opts)
25
24
  Canals.repository.add_environment(env)
26
25
  end
@@ -6,11 +6,11 @@ module Canals
6
6
  module Cli
7
7
  module Helpers
8
8
 
9
- def tstop(tunnel_opts, silent: false)
9
+ def tstop(tunnel_opts, remove_from_session: true, silent: false)
10
10
  if tunnel_opts.instance_of? String
11
11
  tunnel_opts = tunnel_options(tunnel_opts)
12
12
  end
13
- Canals.stop(tunnel_opts)
13
+ Canals.stop(tunnel_opts, remove_from_session: remove_from_session)
14
14
  say "Tunnel #{tunnel_opts.name.inspect} stopped." unless silent
15
15
  end
16
16
 
@@ -42,13 +42,20 @@ module Canals
42
42
  end
43
43
  end
44
44
 
45
- desc "stop", "Stop the current session"
45
+ desc "stop", "Stop the current session (stops and removes from session)"
46
46
  def stop
47
47
  on_all_canals_in_session(:stop) do |canal|
48
48
  tstop(canal)
49
49
  end
50
50
  end
51
51
 
52
+ desc "suspend", "Suspend the current session (stops and doesn't remove from session)"
53
+ def suspend
54
+ on_all_canals_in_session(:suspend) do |canal|
55
+ tstop(canal, remove_from_session: false)
56
+ end
57
+ end
58
+
52
59
  no_commands do
53
60
  def on_all_canals_in_session(command, &block)
54
61
  return if session_empty?
@@ -19,7 +19,6 @@ module Canals
19
19
  desc "completion", "Setup bash completion"
20
20
  def completion
21
21
  install_completion
22
- say "Bash completion script upgraded, use `source #{Canals::Tools::Completion.cmp_file}` to reload it", :red
23
22
  end
24
23
 
25
24
  desc "bind-address", "Setup a global bind address (defaults to 127.0.0.1)"
@@ -32,7 +31,7 @@ module Canals
32
31
  def setup_first_environment
33
32
  say "We'll start by setting up your first environment", :green
34
33
  say "An 'environment' is the server you connect your tunnels through. you can have many environments."
35
- say "The first environment is the default one used for new connections (but you can always change this default in the future"
34
+ say "The first environment is the default one used for new connections (but you can always change this default in the future)"
36
35
  say ""
37
36
  return unless yes? "Wait, should we setup your first environment?", :green
38
37
  opts = {}
@@ -82,8 +81,9 @@ module Canals
82
81
  end
83
82
 
84
83
  def install_completion
85
- Canals::Tools::Completion.install_completion
86
- say "Shell completion installed.", :green
84
+ first_time = Canals::Tools::Completion.install_completion
85
+ say "Shell completion installed.", :green if first_time
86
+ say "Bash completion script #{first_time ? "installed" : "upgraded"}, use `source #{Canals::Tools::Completion.cmp_file}` to reload it", :red
87
87
  end
88
88
 
89
89
  def check(check_result, message)
data/lib/canals/config.rb CHANGED
@@ -1,6 +1,7 @@
1
- require 'psych'
2
1
  require 'pathname'
2
+ require 'fileutils'
3
3
  require 'forwardable'
4
+ require 'canals/tools/yaml'
4
5
 
5
6
  module Canals
6
7
  class Config
@@ -16,14 +17,12 @@ module Canals
16
17
  def load_config(config_file)
17
18
  valid_file = config_file && config_file.exist? && !config_file.size.zero?
18
19
  return {} if !valid_file
19
- return Psych.load_file(config_file)
20
+ return Canals::Tools::YAML.load_file(config_file)
20
21
  end
21
22
 
22
23
  def save!
23
24
  FileUtils.mkdir_p(global_config_file.dirname)
24
- File.open(global_config_file, 'w') do |file|
25
- file.write(Psych.dump(@config))
26
- end
25
+ Canals::Tools::YAML.dump_file(global_config_file, @config)
27
26
  end
28
27
 
29
28
  private
data/lib/canals/core.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'open3'
2
+ require 'fileutils'
2
3
 
3
4
  module Canals
4
5
 
@@ -23,7 +24,7 @@ module Canals
23
24
  pid.to_i
24
25
  end
25
26
 
26
- def stop(tunnel_opts)
27
+ def stop(tunnel_opts, remove_from_session: true)
27
28
  if tunnel_opts.instance_of? String
28
29
  if (Canals.repository.has?(tunnel_opts))
29
30
  tunnel_opts = Canals.repository.get(tunnel_opts)
@@ -32,7 +33,7 @@ module Canals
32
33
  end
33
34
  end
34
35
  tunnel_close(tunnel_opts)
35
- Canals.session.del(tunnel_opts.name)
36
+ Canals.session.del(tunnel_opts.name) if remove_from_session
36
37
  end
37
38
 
38
39
  def restart(tunnel_opts)
@@ -59,7 +60,11 @@ module Canals
59
60
 
60
61
  def tunnel_start(tunnel_opts)
61
62
  FileUtils.mkdir_p("/tmp/canals")
62
- cmd = "ssh -M -S #{socket_file(tunnel_opts)} -o 'ExitOnForwardFailure yes' -fnNT -L #{tunnel_opts.bind_address}:#{tunnel_opts.local_port}:#{tunnel_opts.remote_host}:#{tunnel_opts.remote_port} #{tunnel_opts.proxy}"
63
+ if (tunnel_opts.socks)
64
+ cmd = "ssh -M -S #{socket_file(tunnel_opts)} -o 'ExitOnForwardFailure=yes' -fnNT -D \"#{tunnel_opts.bind_address}:#{tunnel_opts.local_port}\" #{tunnel_opts.proxy}"
65
+ else
66
+ cmd = "ssh -M -S #{socket_file(tunnel_opts)} -o 'ExitOnForwardFailure=yes' -fnNT -L #{tunnel_opts.bind_address}:#{tunnel_opts.local_port}:#{tunnel_opts.remote_host}:#{tunnel_opts.remote_port} #{tunnel_opts.proxy}"
67
+ end
63
68
  system(cmd)
64
69
  $?
65
70
  end
@@ -1,4 +1,4 @@
1
- require 'psych'
1
+ require 'canals/tools/yaml'
2
2
 
3
3
  module Canals
4
4
  class CanalEnvironmentError < StandardError; end
@@ -28,7 +28,7 @@ module Canals
28
28
  end
29
29
 
30
30
  def to_yaml
31
- Psych.dump(@args)
31
+ Canals::Tools::YAML.to_yaml(@args)
32
32
  end
33
33
 
34
34
  def to_hash
@@ -1,14 +1,14 @@
1
- require 'psych'
1
+ require 'canals/tools/yaml'
2
2
 
3
3
  module Canals
4
4
  CanalOptionError = Class.new StandardError
5
5
 
6
6
  class CanalOptions
7
7
  BIND_ADDRESS = "127.0.0.1"
8
- attr_reader :name, :remote_host, :remote_port, :local_port, :env_name, :env, :adhoc
8
+ attr_reader :name, :remote_host, :remote_port, :local_port, :env_name, :env, :adhoc, :socks
9
9
 
10
10
  # define setters
11
- [:name, :local_port, :adhoc].each do |attribute|
11
+ [:name, :local_port, :adhoc, :socks].each do |attribute|
12
12
  define_method :"#{attribute}=" do |value|
13
13
  @args[attribute] = value
14
14
  self.instance_variable_set(:"@#{attribute}", value)
@@ -23,6 +23,7 @@ module Canals
23
23
  @remote_port = @args[:remote_port]
24
24
  @local_port = @args[:local_port]
25
25
  @adhoc = @args[:adhoc] || false
26
+ @socks = @args[:socks] || false
26
27
  @env_name = @args[:env]
27
28
  @env = Canals.repository.environment(@env_name)
28
29
  end
@@ -57,7 +58,7 @@ module Canals
57
58
  end
58
59
 
59
60
  def to_yaml
60
- Psych.dump(@args)
61
+ Canals::Tools::YAML.to_yaml(@args)
61
62
  end
62
63
 
63
64
  def to_hash(mode=:basic)
@@ -67,7 +68,7 @@ module Canals
67
68
  end
68
69
 
69
70
  def exploded_options
70
- {bind_address: bind_address, hostname: hostname, user: user, pem: pem, proxy: proxy, adhoc: adhoc}
71
+ {bind_address: bind_address, hostname: hostname, user: user, pem: pem, proxy: proxy, adhoc: adhoc, socks: socks}
71
72
  end
72
73
 
73
74
  private
@@ -75,8 +76,13 @@ module Canals
75
76
  def validate?(args)
76
77
  vargs = args.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
77
78
  raise CanalOptionError.new("Missing option: \"name\" in canal creation") if vargs[:name].nil?
78
- raise CanalOptionError.new("Missing option: \"remote_host\" in canal creation") if vargs[:remote_host].nil?
79
- raise CanalOptionError.new("Missing option: \"remote_port\" in canal creation") if vargs[:remote_port].nil?
79
+ if vargs[:socks]
80
+ raise CanalOptionError.new("Missing option: \"local_port\" in canal creation") if vargs[:local_port].nil?
81
+ else
82
+ raise CanalOptionError.new("Missing option: \"remote_host\" in canal creation") if vargs[:remote_host].nil?
83
+ raise CanalOptionError.new("Missing option: \"remote_port\" in canal creation") if vargs[:remote_port].nil?
84
+ end
85
+
80
86
  vargs[:remote_port] = vargs[:remote_port].to_i
81
87
  if vargs[:local_port].nil?
82
88
  vargs[:local_port] = vargs[:remote_port]
@@ -1,7 +1,8 @@
1
- require 'psych'
2
1
  require 'pathname'
2
+ require 'fileutils'
3
3
  require 'forwardable'
4
4
  require 'canals/environment'
5
+ require 'canals/tools/yaml'
5
6
 
6
7
  module Canals
7
8
  class Repository
@@ -27,9 +28,9 @@ module Canals
27
28
  end
28
29
 
29
30
  def add(options, save=true)
30
- @repo[TUNNELS][options.name] = options.to_hash
31
+ @repo[TUNNELS][options.name.to_sym] = options.to_hash
31
32
  if options.env_name.nil? && !options.env.nil? && options.env.is_default?
32
- @repo[TUNNELS][options.name][:env] = options.env.name
33
+ @repo[TUNNELS][options.name.to_sym][:env] = options.env.name
33
34
  end
34
35
  save! if save
35
36
  end
@@ -40,37 +41,36 @@ module Canals
40
41
  end
41
42
 
42
43
  def get(name)
44
+ name = name.to_sym
43
45
  return nil if !@repo[:tunnels].has_key? name
44
46
  CanalOptions.new(@repo[:tunnels][name])
45
47
  end
46
48
 
47
49
  def has?(name)
48
- return @repo[:tunnels].has_key? name
50
+ return @repo[:tunnels].has_key? name.to_sym
49
51
  end
50
52
 
51
53
  def add_environment(environment, save=true)
52
54
  if environment.is_default?
53
- @repo[ENVIRONMENTS].each { |name, env| env.delete("default") }
55
+ @repo[ENVIRONMENTS].each { |name, env| env.delete(:default) }
54
56
  end
55
57
  if @repo[ENVIRONMENTS].empty?
56
58
  environment.default = true
57
59
  end
58
- @repo[ENVIRONMENTS][environment.name] = environment.to_hash
60
+ @repo[ENVIRONMENTS][environment.name.to_sym] = environment.to_hash
59
61
  save! if save
60
62
  end
61
63
 
62
64
  def save!
63
65
  FileUtils.mkdir_p(repo_file.dirname)
64
- File.open(repo_file, 'w') do |file|
65
- file.write(Psych.dump(@repo))
66
- end
66
+ Canals::Tools::YAML.dump_file(repo_file, @repo)
67
67
  end
68
68
 
69
69
  def environment(name=nil)
70
70
  if name.nil?
71
- args = @repo[ENVIRONMENTS].select{ |n,e| e["default"] }.values[0]
71
+ args = @repo[ENVIRONMENTS].select{ |n,e| e[:default] }.values[0]
72
72
  else
73
- args = @repo[ENVIRONMENTS][name]
73
+ args = @repo[ENVIRONMENTS][name.to_sym]
74
74
  end
75
75
  Canals::Environment.new(args) if !args.nil?
76
76
  end
@@ -89,7 +89,7 @@ module Canals
89
89
  def load_repository(repository_file)
90
90
  valid_file = repository_file && repository_file.exist? && !repository_file.size.zero?
91
91
  return { ENVIRONMENTS => {}, TUNNELS => {} } if !valid_file
92
- return Psych.load_file(repository_file)
92
+ return Canals::Tools::YAML.load_file(repository_file)
93
93
  end
94
94
 
95
95
  end
@@ -1,6 +1,7 @@
1
- require 'psych'
2
1
  require 'pathname'
2
+ require 'fileutils'
3
3
  require 'forwardable'
4
+ require 'canals/tools/yaml'
4
5
 
5
6
  module Canals
6
7
  class Session
@@ -65,9 +66,7 @@ module Canals
65
66
 
66
67
  def save!
67
68
  FileUtils.mkdir_p(session_file.dirname)
68
- File.open(session_file, 'w') do |file|
69
- file.write(Psych.dump(@session))
70
- end
69
+ Canals::Tools::YAML.dump_file(session_file, @session)
71
70
  end
72
71
 
73
72
  private
@@ -80,7 +79,7 @@ module Canals
80
79
  def load_session(_session_file)
81
80
  valid_file = _session_file && _session_file.exist? && !_session_file.size.zero?
82
81
  return [] if !valid_file
83
- return Psych.load_file(_session_file)
82
+ Canals::Tools::YAML.load_file(_session_file)
84
83
  end
85
84
 
86
85
  def basic?(sess)
@@ -1,3 +1,4 @@
1
+ require 'fileutils'
1
2
  require 'canals'
2
3
  require 'canals/tools/assets'
3
4
 
@@ -20,8 +21,9 @@ module Canals
20
21
  source = "source " << cmp_file
21
22
 
22
23
  rcfile = File.expand_path('.bashrc', ENV['HOME'])
23
- return if File.read(rcfile).include? source
24
+ return false if File.read(rcfile).include? source
24
25
  File.open(rcfile, 'a') { |f| f.puts("", "# added by canals gem", "[ -f #{cmp_file} ] && #{source}") }
26
+ true
25
27
  end
26
28
 
27
29
  def update_completion
@@ -0,0 +1,28 @@
1
+ require 'psych'
2
+
3
+ module Canals
4
+ module Tools
5
+ module YAML
6
+
7
+ def self.load(content)
8
+ Psych.load(content, symbolize_names: true)
9
+ end
10
+
11
+ def self.load_file(filename)
12
+ File.open(filename, 'r:bom|utf-8') { |f|
13
+ Psych.load(f, filename, fallback: false, symbolize_names: true)
14
+ }
15
+ end
16
+
17
+ def self.dump_file(filename, content)
18
+ File.open(filename, 'w') do |f|
19
+ f.write(self.to_yaml(content))
20
+ end
21
+ end
22
+
23
+ def self.to_yaml(content)
24
+ Psych.dump(content)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,6 +1,6 @@
1
1
  module Canals
2
2
 
3
3
  # Canals gem current version
4
- VERSION = "0.9.0"
4
+ VERSION = "0.9.1"
5
5
 
6
6
  end
@@ -1,5 +1,5 @@
1
1
  require 'canals/options'
2
- require 'psych'
2
+ require 'canals/tools/yaml'
3
3
 
4
4
  describe Canals::CanalOptions do
5
5
 
@@ -13,6 +13,7 @@ describe Canals::CanalOptions do
13
13
  let(:user) { "user" }
14
14
  let(:pem) { "/tmp/file.pem" }
15
15
  let(:adhoc) { true }
16
+ let(:socks) { true }
16
17
 
17
18
  describe "name" do
18
19
  it "contains 'name'" do
@@ -95,6 +96,25 @@ describe Canals::CanalOptions do
95
96
  end
96
97
  end
97
98
 
99
+ describe "socks" do
100
+ it "returns 'socks' if 'socks' is availble" do
101
+ args = {"name" => name, "remote_host" => remote_host, "remote_port" => remote_port, "local_port" => local_port, "hostname" => hostname, "socks" => socks}
102
+ opt = Canals::CanalOptions.new(args)
103
+ expect(opt.socks).to eq socks
104
+ end
105
+
106
+ it "returns 'false' for 'socks' if 'socks' isn't given" do
107
+ args = {"name" => name, "remote_host" => remote_host, "remote_port" => remote_port, "local_port" => local_port, "hostname" => hostname}
108
+ opt = Canals::CanalOptions.new(args)
109
+ expect(opt.socks).to eq false
110
+ end
111
+
112
+ it "raises error when 'socks' is true and 'local_port' is not availble" do
113
+ args = {"name" => name, "hostname" => hostname, "socks" => socks}
114
+ expect{Canals::CanalOptions.new(args)}.to raise_error(Canals::CanalOptionError)
115
+ end
116
+ end
117
+
98
118
  describe "bind_address" do
99
119
  it "returns 'bind_address' if 'bind_address' is availble" do
100
120
  allow(Canals.config).to receive(:[]).with(:bind_address).and_return(global_bind_address)
@@ -210,7 +230,7 @@ describe Canals::CanalOptions do
210
230
  it "dumps remote_port as int" do
211
231
  args = {"name" => name, "remote_host" => remote_host, "remote_port" => '1234'}
212
232
  yaml = Canals::CanalOptions.new(args).to_yaml
213
- reparsed = Psych.load(yaml)
233
+ reparsed = Canals::Tools::YAML.load(yaml)
214
234
  expect(reparsed[:remote_port]).to eq 1234
215
235
  expect(reparsed[:local_port]).to eq 1234
216
236
  end
@@ -218,7 +238,7 @@ describe Canals::CanalOptions do
218
238
  it "dumps local_port as int" do
219
239
  args = {"name" => name, "remote_host" => remote_host, "remote_port" => remote_port, "local_port" => "4321"}
220
240
  yaml = Canals::CanalOptions.new(args).to_yaml
221
- reparsed = Psych.load(yaml)
241
+ reparsed = Canals::Tools::YAML.load(yaml)
222
242
  expect(reparsed[:local_port]).to eq 4321
223
243
  end
224
244
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canals
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ido Abramovich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-02 00:00:00.000000000 Z
11
+ date: 2018-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.19.1
19
+ version: 0.20.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.19.1
26
+ version: 0.20.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: terminal-table
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.5'
33
+ version: '1.8'
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: '1.5'
40
+ version: '1.8'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +86,7 @@ files:
86
86
  - lib/canals/session.rb
87
87
  - lib/canals/tools/assets.rb
88
88
  - lib/canals/tools/completion.rb
89
+ - lib/canals/tools/yaml.rb
89
90
  - lib/canals/version.rb
90
91
  - spec/canals/environment_spec.rb
91
92
  - spec/canals/options_spec.rb
@@ -110,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
111
  version: '0'
111
112
  requirements: []
112
113
  rubyforge_project: canals
113
- rubygems_version: 2.6.14
114
+ rubygems_version: 2.7.7
114
115
  signing_key:
115
116
  specification_version: 4
116
117
  summary: Eases the process of creating and managing SSH tunnels