canals 0.8.0
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/.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
|