canals 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +38 -0
- data/.rvmrc +1 -0
- data/Gemfile +8 -0
- data/LICENSE +21 -0
- data/README.md +11 -0
- data/Rakefile +3 -0
- data/assets/canals.sh +53 -0
- data/bin/canal +14 -0
- data/canals.gemspec +27 -0
- data/lib/canals/cli/environment.rb +44 -0
- data/lib/canals/cli/helpers.rb +38 -0
- data/lib/canals/cli/list.rb +43 -0
- data/lib/canals/cli/session.rb +75 -0
- data/lib/canals/cli/setup.rb +98 -0
- data/lib/canals/cli.rb +90 -0
- data/lib/canals/config.rb +37 -0
- data/lib/canals/core.rb +69 -0
- data/lib/canals/core_ext/shell_colors.rb +15 -0
- data/lib/canals/core_ext/string.rb +6 -0
- data/lib/canals/environment.rb +40 -0
- data/lib/canals/options.rb +75 -0
- data/lib/canals/repository.rb +87 -0
- data/lib/canals/session.rb +64 -0
- data/lib/canals/tools/assets.rb +21 -0
- data/lib/canals/tools/completion.rb +47 -0
- data/lib/canals/version.rb +6 -0
- data/lib/canals.rb +39 -0
- data/spec/canals/environment_spec.rb +77 -0
- data/spec/canals/options_spec.rb +203 -0
- data/spec/spec_helper.rb +4 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b0af6d8d1f776054496a2e57bd383087ceb9d847
|
4
|
+
data.tar.gz: 84eef80c5fc95a038bb58361ecbe6a80676a1f8b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 068e49ef7a7a43c035e9d6c4ee8815ad9a985639b5e0b50d290f52e4afb30a0c7531babd8ab7aa8d8a6ff1ac3ef11df3314209657f626518cb5128f5542b3e01
|
7
|
+
data.tar.gz: 3add6233e74d5debf21966b693f3c362fe660b25a13eaadff67ce8d4e51b74c676ecff8b84720979b92142aaca66a14caca615d6f3bed3205b86caeafd805df3
|
data/.gitignore
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
/pkg
|
2
|
+
.idea/*
|
3
|
+
*.iml
|
4
|
+
*.swp
|
5
|
+
*.DS_Store
|
6
|
+
|
7
|
+
*.gem
|
8
|
+
*.rbc
|
9
|
+
/.config
|
10
|
+
/coverage/
|
11
|
+
/InstalledFiles
|
12
|
+
/pkg/
|
13
|
+
/spec/reports/
|
14
|
+
/test/tmp/
|
15
|
+
/test/version_tmp/
|
16
|
+
/tmp/
|
17
|
+
|
18
|
+
## Specific to RubyMotion:
|
19
|
+
.dat*
|
20
|
+
.repl_history
|
21
|
+
build/
|
22
|
+
|
23
|
+
## Documentation cache and generated files:
|
24
|
+
/.yardoc/
|
25
|
+
/_yardoc/
|
26
|
+
/doc/
|
27
|
+
/rdoc/
|
28
|
+
|
29
|
+
## Environment normalisation:
|
30
|
+
/.bundle/
|
31
|
+
/vendor/bundle
|
32
|
+
/lib/bundler/man/
|
33
|
+
|
34
|
+
# for a library or gem, you might want to ignore these files since the code is
|
35
|
+
# intended to run in multiple environments; otherwise, check them in:
|
36
|
+
Gemfile.lock
|
37
|
+
# .ruby-version
|
38
|
+
# .ruby-gemset
|
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use ruby@canals --create
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Ido Abramovich
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Canals: Help manage SSH tunnels
|
2
|
+
|
3
|
+
Canals eases the process of creating and managing SSH tunnels.
|
4
|
+
Behind the scenes, Canals creates SSH tunnels using the standard OpenSSH library, but it helps with making the process more forward and by remembering those tunnels between usages.
|
5
|
+
|
6
|
+
### Instalation
|
7
|
+
|
8
|
+
```
|
9
|
+
gem install canals
|
10
|
+
canal setup wizard
|
11
|
+
```
|
data/Rakefile
ADDED
data/assets/canals.sh
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
_canal_complete() {
|
4
|
+
local cur prev
|
5
|
+
|
6
|
+
COMPREPLY=()
|
7
|
+
cur=${COMP_WORDS[COMP_CWORD]}
|
8
|
+
prev=${COMP_WORDS[COMP_CWORD-1]}
|
9
|
+
|
10
|
+
# Setup the base level (everything after "canal")
|
11
|
+
if [ $COMP_CWORD -eq 1 ]; then
|
12
|
+
COMPREPLY=( $(compgen \
|
13
|
+
-W "create environment help repo restart session setup start stop" \
|
14
|
+
-- $cur) )
|
15
|
+
return 0
|
16
|
+
fi
|
17
|
+
|
18
|
+
# Setup the second level
|
19
|
+
if [ $COMP_CWORD -eq 2 ]; then
|
20
|
+
case "$prev" in
|
21
|
+
start|stop|restart)
|
22
|
+
COMPREPLY=( $(compgen \
|
23
|
+
-W "`canal list tunnels`" \
|
24
|
+
-- $cur) )
|
25
|
+
;;
|
26
|
+
environment)
|
27
|
+
COMPREPLY=( $(compgen \
|
28
|
+
-W "create help show" \
|
29
|
+
-- $cur) )
|
30
|
+
;;
|
31
|
+
session)
|
32
|
+
COMPREPLY=( $(compgen \
|
33
|
+
-W "help restart restore show stop" \
|
34
|
+
-- $cur) )
|
35
|
+
;;
|
36
|
+
setup)
|
37
|
+
COMPREPLY=( $(compgen \
|
38
|
+
-W "completion help wizard" \
|
39
|
+
-- $cur) )
|
40
|
+
;;
|
41
|
+
# Everything else
|
42
|
+
*)
|
43
|
+
COMPREPLY=( $(compgen \
|
44
|
+
-W "`canal list commands $prev`" \
|
45
|
+
-- $cur) )
|
46
|
+
;;
|
47
|
+
esac
|
48
|
+
return 0
|
49
|
+
fi
|
50
|
+
|
51
|
+
return 0
|
52
|
+
}
|
53
|
+
complete -F _canal_complete canal
|
data/bin/canal
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
Signal.trap('INT') { exit 1 }
|
4
|
+
|
5
|
+
# resolve bin path, ignoring symlinks
|
6
|
+
require 'pathname'
|
7
|
+
bin_file = Pathname.new(__FILE__).realpath
|
8
|
+
|
9
|
+
# add self to libpath
|
10
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", bin_file)
|
11
|
+
|
12
|
+
require "canals/cli"
|
13
|
+
|
14
|
+
Canals::Cli::Application.start(ARGV)
|
data/canals.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
$:.push File.expand_path('../lib', __FILE__)
|
2
|
+
require 'canals/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "canals"
|
6
|
+
s.version = Canals::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
|
9
|
+
s.summary = "Eases the process of creating and managing SSH tunnels"
|
10
|
+
s.description = "A console utility to help build ssh tunnels and keep them up"
|
11
|
+
s.authors = ["Ido Abramovich"]
|
12
|
+
s.email = "canals.sf17@abramovich.info"
|
13
|
+
s.homepage = 'http://github.com/idoa01/canals'
|
14
|
+
|
15
|
+
s.required_ruby_version = '>= 2.2.0'
|
16
|
+
s.rubyforge_project = "canals"
|
17
|
+
s.files = `git ls-files`.split($/)
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split($/)
|
19
|
+
s.executables = `git ls-files -- bin/*`.split($/).map{ |f| File.basename(f) }
|
20
|
+
s.require_path = "lib"
|
21
|
+
s.license = "MIT"
|
22
|
+
|
23
|
+
s.add_dependency 'thor', '~> 0.19.1'
|
24
|
+
s.add_dependency 'terminal-table', '~> 1.5'
|
25
|
+
|
26
|
+
s.add_development_dependency 'rspec', '~> 3.4'
|
27
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'canals'
|
2
|
+
require 'canals/options'
|
3
|
+
require 'canals/environment'
|
4
|
+
require 'thor'
|
5
|
+
|
6
|
+
|
7
|
+
module Canals
|
8
|
+
module Cli
|
9
|
+
class Environment < Thor
|
10
|
+
include Thor::Actions
|
11
|
+
|
12
|
+
desc 'create NAME HOSTNAME', 'Create a new ssh environment'
|
13
|
+
method_option :user, :type => :string, :desc => "The user for the ssh proxy host"
|
14
|
+
method_option :pem, :type => :string, :desc => "The PEM file location for this environment"
|
15
|
+
method_option :default, :type => :boolean, :desc => "Make this the default enviroment"
|
16
|
+
def create(name, hostname)
|
17
|
+
user, host = hostname.split("@")
|
18
|
+
if host.nil?
|
19
|
+
host = hostname
|
20
|
+
user = nil
|
21
|
+
end
|
22
|
+
opts = {"name" => name, "hostname" => host}.merge(options)
|
23
|
+
opts["user"] = user if !user.nil?
|
24
|
+
env = Canals::Environment.new(opts)
|
25
|
+
Canals.repository.add_environment(env)
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "show [ENV]", "Show the available tunnels"
|
29
|
+
def show(env=nil)
|
30
|
+
if Canals.environments.empty?
|
31
|
+
say "No environments currently defined."
|
32
|
+
return
|
33
|
+
end
|
34
|
+
require 'terminal-table'
|
35
|
+
rows = Canals.environments.select{ |e| env.nil? || e.name == env}.map{ |e| [(e.is_default? ? "*" : ""), e.name, e.user, e.hostname, e.pem] }
|
36
|
+
table = Terminal::Table.new :headings => ['', 'Name', 'User', 'Hostname', 'PEM'], :rows => rows
|
37
|
+
say table
|
38
|
+
end
|
39
|
+
|
40
|
+
default_task :show
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'canals'
|
2
|
+
require 'canals/tools/completion'
|
3
|
+
|
4
|
+
module Canals
|
5
|
+
module Cli
|
6
|
+
module Helpers
|
7
|
+
|
8
|
+
def tstop(name)
|
9
|
+
Canals.stop(name)
|
10
|
+
say "Tunnel #{name.inspect} stopped."
|
11
|
+
end
|
12
|
+
|
13
|
+
def tstart(name)
|
14
|
+
pid = Canals.start(name)
|
15
|
+
say "Created tunnel #{name.inspect} with pid #{pid}"
|
16
|
+
pid
|
17
|
+
end
|
18
|
+
|
19
|
+
def trestart(name)
|
20
|
+
tstop(name)
|
21
|
+
tstart(name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def startup_checks
|
25
|
+
check_completion
|
26
|
+
end
|
27
|
+
|
28
|
+
def check_completion
|
29
|
+
if Canals.config[:completion_version]
|
30
|
+
if Canals.config[:completion_version] != Canals::VERSION
|
31
|
+
Canals::Tools::Completion.update_completion
|
32
|
+
say "bash completion script upgraded, use `source #{Canals::Tools::Completion.cmp_file}` to reload it", :red
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'canals'
|
2
|
+
require 'canals/options'
|
3
|
+
require 'canals/environment'
|
4
|
+
require 'thor'
|
5
|
+
require 'pry'
|
6
|
+
|
7
|
+
module Canals
|
8
|
+
module Cli
|
9
|
+
class List < Thor
|
10
|
+
include Thor::Actions
|
11
|
+
|
12
|
+
desc 'environments', 'List the different environments'
|
13
|
+
def environments
|
14
|
+
envs = Canals.environments.map{ |conf| conf.name }
|
15
|
+
say envs.sort.join " "
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'tunnels', 'List the different tunnels'
|
19
|
+
def tunnels
|
20
|
+
tunnels = Canals.repository.map{ |conf| conf.name }
|
21
|
+
say tunnels.sort.join " "
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'commands', 'List all the base level commands'
|
25
|
+
def commands(subcommand=nil)
|
26
|
+
#binding.pry
|
27
|
+
thor_class = Canals::Cli::Application
|
28
|
+
if !subcommand.nil?
|
29
|
+
thor_class = thor_class.subcommand_classes[subcommand]
|
30
|
+
if thor_class.nil?
|
31
|
+
return
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
cmds = thor_class.all_commands.values.select{ |c| c.class == Thor::Command }.map{ |c| c.name }
|
36
|
+
say cmds.sort.join " "
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'canals'
|
2
|
+
require 'canals/cli/helpers'
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
|
6
|
+
module Canals
|
7
|
+
module Cli
|
8
|
+
class Session < Thor
|
9
|
+
include Thor::Actions
|
10
|
+
include Canals::Cli::Helpers
|
11
|
+
|
12
|
+
desc "show", "Show the current session"
|
13
|
+
def show
|
14
|
+
return if session_empty?
|
15
|
+
require 'terminal-table'
|
16
|
+
require 'canals/core_ext/string'
|
17
|
+
columns = ["pid", "name", "socket"]
|
18
|
+
rows = Canals.session.map{ |s| columns.map{ |c| s[c.to_sym] } }
|
19
|
+
table = Terminal::Table.new :headings => columns.map{|c| c.sub("_"," ").titleize }, :rows => rows
|
20
|
+
say table
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "restore", "Restore the connection to tunnels which aren't working"
|
24
|
+
def restore
|
25
|
+
on_all_canals_in_session(:restore) do |name|
|
26
|
+
if Canals.isalive? name
|
27
|
+
say "Canal #{name.inspect} is running."
|
28
|
+
else
|
29
|
+
Canals.session.del(name)
|
30
|
+
tstart(name)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "restart", "Restart the current session (closing and starting all connections)"
|
36
|
+
def restart
|
37
|
+
on_all_canals_in_session(:restart) do |name|
|
38
|
+
trestart(name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "stop", "Stop the current session"
|
43
|
+
def stop
|
44
|
+
on_all_canals_in_session(:stop) do |name|
|
45
|
+
tstop(name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
no_commands do
|
50
|
+
def on_all_canals_in_session(command, &block)
|
51
|
+
return if session_empty?
|
52
|
+
Canals.session.map{|s| s[:name]}.each do |name|
|
53
|
+
say "#{command.to_s.capitalize} canal #{name.inspect}:", :green
|
54
|
+
block.call(name)
|
55
|
+
end
|
56
|
+
say
|
57
|
+
say "#{command} done.", :green
|
58
|
+
end
|
59
|
+
|
60
|
+
def session_empty?
|
61
|
+
if Canals.session.empty?
|
62
|
+
say "Canal session is currently empty."
|
63
|
+
true
|
64
|
+
else
|
65
|
+
false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
default_task :show
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'canals'
|
2
|
+
require 'canals/tools/completion'
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
module Canals
|
6
|
+
module Cli
|
7
|
+
class Setup < Thor
|
8
|
+
include Thor::Actions
|
9
|
+
|
10
|
+
desc "wizard", "Run the setup wizard"
|
11
|
+
def wizard
|
12
|
+
say "Welcome to the Canals Setup Wizard!", :green
|
13
|
+
setup_first_environment
|
14
|
+
setup_first_tunnel
|
15
|
+
check_install_completion
|
16
|
+
say "Setup complete. Thanks! :)", :green
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "completion", "Setup bash completion"
|
20
|
+
def completion
|
21
|
+
install_completion
|
22
|
+
end
|
23
|
+
|
24
|
+
no_commands do
|
25
|
+
def setup_first_environment
|
26
|
+
say "We'll start by setting up your first environment", :green
|
27
|
+
say "An 'environment' is the server you connect your tunnels through. you can have many environments."
|
28
|
+
say "The first environment is the default one used for new connections (but you can always change this default in the future"
|
29
|
+
say ""
|
30
|
+
return unless yes? "Wait, should we setup your first environment?", :green
|
31
|
+
opts = {}
|
32
|
+
opts["name"] = ask " Name for environment:"
|
33
|
+
opts["hostname"] = ask " Hostname:"
|
34
|
+
opts["user"] = ask " User:"
|
35
|
+
opts["pem"] = ask " PEM file:", :path => true
|
36
|
+
opts["default"] = true
|
37
|
+
opts.delete_if { |key, value| value.to_s.strip.empty? }
|
38
|
+
if opts["name"].nil? || opts["hostname"].nil?
|
39
|
+
say "couldn't add first environment, use 'canal environment create ...' to add it manually.", :red
|
40
|
+
return
|
41
|
+
end
|
42
|
+
env = Canals::Environment.new(opts)
|
43
|
+
Canals.repository.add_environment(env)
|
44
|
+
say "Environment added. To add more environments in the future, use 'canal environment create...'", :green
|
45
|
+
end
|
46
|
+
|
47
|
+
def setup_first_tunnel
|
48
|
+
return unless yes? "Should we setup a first tunnel?", :green
|
49
|
+
|
50
|
+
opts = {}
|
51
|
+
shell.padding += 1
|
52
|
+
opts["name"] = ask "Name for Tunnel:"
|
53
|
+
opts["remote_host"] = ask "Remote host:"
|
54
|
+
opts["remote_port"] = ask "Remote port:"
|
55
|
+
opts["local_port"] = ask "Local port:", :default =>opts["remote_port"]
|
56
|
+
use_env = !Canals.repository.environment.nil? && yes?("* Use stored environment?", :bold)
|
57
|
+
if use_env
|
58
|
+
opts["env"] = ask "Environment:", :default => Canals.repository.environment.name
|
59
|
+
else
|
60
|
+
opts["hostname"] = ask "Hostname:"
|
61
|
+
opts["user"] = ask "User:"
|
62
|
+
opts["pem"] = ask "PEM file:", :path => true
|
63
|
+
end
|
64
|
+
opts.delete_if { |key, value| value.to_s.strip.empty? }
|
65
|
+
shell.padding -= 1
|
66
|
+
opts = Canals::CanalOptions.new(opts)
|
67
|
+
Canals.create_tunnel(opts)
|
68
|
+
say "Tunnel added. To add more tunnels in the future, use 'canal create...'", :green
|
69
|
+
end
|
70
|
+
|
71
|
+
def check_install_completion
|
72
|
+
if !check(Canals::Tools::Completion.completion_installed?, "Checking if shell completion is installed...")
|
73
|
+
yes?('Shell completion not installed. Would you like to install it now? ') && install_completion
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def install_completion
|
78
|
+
Canals::Tools::Completion.install_completion
|
79
|
+
say "Shell completion installed.", :green
|
80
|
+
end
|
81
|
+
|
82
|
+
def check(check_result, message)
|
83
|
+
spaces = " " * (shell.padding + 1)
|
84
|
+
say "#{spaces}#{message}#{spaces}#{humanize(check_result)}"
|
85
|
+
return check_result
|
86
|
+
end
|
87
|
+
|
88
|
+
def humanize(bool)
|
89
|
+
bool ? set_color("yes", :green) : set_color("no", :red)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
default_task :wizard
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
data/lib/canals/cli.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'canals'
|
2
|
+
require 'canals/options'
|
3
|
+
require 'canals/environment'
|
4
|
+
require 'canals/cli/environment'
|
5
|
+
require 'canals/cli/session'
|
6
|
+
require 'canals/cli/helpers'
|
7
|
+
require 'canals/cli/setup'
|
8
|
+
require 'canals/cli/list'
|
9
|
+
require 'canals/core_ext/shell_colors'
|
10
|
+
require 'thor'
|
11
|
+
|
12
|
+
module Canals
|
13
|
+
module Cli
|
14
|
+
class Application < Thor
|
15
|
+
include Thor::Actions
|
16
|
+
include Canals::Cli::Helpers
|
17
|
+
|
18
|
+
def initialize(*args)
|
19
|
+
super
|
20
|
+
startup_checks
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'create NAME REMOTE_HOST REMOTE_PORT [LOCAL_PORT]', "Create a new tunnel; if LOCAL_PORT isn't supplied, REMOTE_PORT will be used as LOCAL"
|
24
|
+
method_option :env, :type => :string, :desc => "The proxy environment to use"
|
25
|
+
method_option :hostname, :type => :string, :desc => "The proxy host we will use to connect through"
|
26
|
+
method_option :user, :type => :string, :desc => "The user for the ssh proxy host"
|
27
|
+
def create(name, remote_host, remote_port, local_port=nil)
|
28
|
+
opts = {"name" => name, "remote_host" => remote_host, "remote_port" => remote_port, "local_port" => local_port}.merge(options)
|
29
|
+
opts = Canals::CanalOptions.new(opts)
|
30
|
+
Canals.create_tunnel(opts)
|
31
|
+
say "Tunnel #{name.inspect} created.", :green
|
32
|
+
end
|
33
|
+
|
34
|
+
desc 'start NAME', 'Start tunnel'
|
35
|
+
def start(name)
|
36
|
+
tstart(name)
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'stop NAME', 'Stop tunnel'
|
40
|
+
def stop(name)
|
41
|
+
tstop(name)
|
42
|
+
end
|
43
|
+
|
44
|
+
desc 'restart NAME', 'Restart tunnel'
|
45
|
+
def restart(name)
|
46
|
+
trestart(name)
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "repo", "Show the available tunnels, for given enviroment if given"
|
50
|
+
method_option :full, :type => :boolean, :desc => "Show full data on repostitory"
|
51
|
+
method_option :env, :type => :string , :desc => "Show data only on given environment"
|
52
|
+
method_option :'sort-by', :type => :string, :desc => "Sort by this field", :default => "name"
|
53
|
+
def repo
|
54
|
+
if Canals.repository.empty?
|
55
|
+
say "Repository is currently empty."
|
56
|
+
return
|
57
|
+
end
|
58
|
+
require 'terminal-table'
|
59
|
+
require 'canals/core_ext/string'
|
60
|
+
columns = ["name", "remote_host", "remote_port", "local_port"]
|
61
|
+
columns_extra = ["bind_address", "env_name", "user", "hostname"]
|
62
|
+
if options[:full]
|
63
|
+
columns += columns_extra
|
64
|
+
end
|
65
|
+
|
66
|
+
env = options[:env]
|
67
|
+
sort_by = options[:'sort-by'].downcase.split.join("_").to_sym
|
68
|
+
rows = Canals.repository.select { |conf| env.nil? || conf.env_name == env }
|
69
|
+
.sort { |a,b| a.send(sort_by) <=> b.send(sort_by) rescue a.name <=> b.name }
|
70
|
+
.map { |conf| columns.map{ |c| conf.send c.to_sym } }
|
71
|
+
table = Terminal::Table.new :headings => columns.map{|c| c.sub("_"," ").titleize }, :rows => rows
|
72
|
+
say table
|
73
|
+
say "* use --full to show more data", [:white, :dim] if !options[:full]
|
74
|
+
end
|
75
|
+
|
76
|
+
desc "environment SUBCOMMAND", "Environment related command (use 'canal environment help' to find out more)"
|
77
|
+
subcommand "environment", Canals::Cli::Environment
|
78
|
+
|
79
|
+
desc "session SUBCOMMAND", "Session related commands (use 'canal session help' to find out more)"
|
80
|
+
subcommand "session", Canals::Cli::Session
|
81
|
+
|
82
|
+
desc "setup", "Setup related commands (use 'canal setup help' to find out more)"
|
83
|
+
subcommand "setup", Canals::Cli::Setup
|
84
|
+
|
85
|
+
desc "list", "hidden lists for autocompletion", :hide => true
|
86
|
+
subcommand "list", Canals::Cli::List
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'psych'
|
2
|
+
require 'pathname'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module Canals
|
6
|
+
class Config
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def initialize(root = nil)
|
10
|
+
@root = root
|
11
|
+
@config = load_config(global_config_file)
|
12
|
+
end
|
13
|
+
|
14
|
+
def_delegators :@config, :[], :[]=
|
15
|
+
|
16
|
+
def load_config(config_file)
|
17
|
+
valid_file = config_file && config_file.exist? && !config_file.size.zero?
|
18
|
+
return {} if !valid_file
|
19
|
+
return Psych.load_file(config_file)
|
20
|
+
end
|
21
|
+
|
22
|
+
def save!
|
23
|
+
FileUtils.mkdir_p(global_config_file.dirname)
|
24
|
+
File.open(global_config_file, 'w') do |file|
|
25
|
+
file.write(Psych.dump(@config))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def global_config_file
|
32
|
+
file = File.join(Dir.home, '.canals/config')
|
33
|
+
Pathname.new(file)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|