con_ssh 0.0.1

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.
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.0
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ con_ssh
2
+ =================
3
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task default: :test
data/TODO ADDED
File without changes
data/bin/con ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ostruct'
4
+ require 'con_ssh'
5
+
6
+ SSHCon.new.run *ARGV
data/con_ssh.gemspec ADDED
@@ -0,0 +1,18 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "con_ssh"
3
+ s.version = "0.0.1"
4
+ s.authors = ["Tom Lobato"]
5
+ s.email = "lobato@bettercall.io"
6
+ # s.homepage = "http://sys-watchdog.bettercall.io/"
7
+ s.summary = "SSH cli wrapper."
8
+ s.description = "#{s.summary}."
9
+ s.licenses = ["MIT"]
10
+ s.platform = Gem::Platform::RUBY
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- test/*`.split("\n")
14
+ s.require_paths = ["lib"]
15
+ s.executables = %w(con)
16
+ s.required_ruby_version = '>= 2.3.0'
17
+ end
18
+
data/gempush ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+
3
+ rm con_ssh-*.gem
4
+ gem build con_ssh.gemspec
5
+ gem push con_ssh-*.gem
@@ -0,0 +1,24 @@
1
+
2
+ class String
3
+ def strip_text
4
+ split("\n")
5
+ .map{|l| l.trip}
6
+ .join("\n")
7
+ end
8
+ end
9
+
10
+ class Exception
11
+ def desc
12
+ "#{ message } #{ backtrace&.join "\n" }"
13
+ end
14
+ end
15
+
16
+ def log_ex e
17
+ STDERR.puts e.desc
18
+ end
19
+
20
+ def match_root_or_current_user stat
21
+ (stat.uid == 0 and stat.gid == 0) ||
22
+ (stat.uid == Process.uid and stat.gid == Process.gid)
23
+ end
24
+
data/lib/con_ssh.rb ADDED
@@ -0,0 +1,173 @@
1
+
2
+ require 'ostruct'
3
+ require 'con_ssh/core_extensions'
4
+
5
+ class SSHCon
6
+ CONF_PATH = File.expand_path '~/.con'
7
+ CONF_LINE_FIELDS = %w(shortcut conn_desc host user port knock unknock)
8
+ DEFAULT_PORT = "22"
9
+
10
+ def initialize
11
+ @conn_confs = {}
12
+ end
13
+
14
+ def run *args
15
+ # setup
16
+ if args[0] == 'setup'
17
+ warn "Ignoring arguments after #{args[0]}." if args.length > 1
18
+ install_sample_conf
19
+
20
+ # knock / unknock
21
+ elsif ['knock', 'unknock'].include? args[1]
22
+ warn "Ignoring arguments after #{args[1]}." if args.length > 2
23
+ parse_conf
24
+ conn_conf = @conn_confs[args[0]]
25
+ unless conn_confs
26
+ warn "Shorcut #{args[0]} not found. See #{CONF_PATH}."
27
+ exit 1
28
+ end
29
+ ports = conn_conf[args[1]]
30
+ if ports.nil? || ports.empty?
31
+ warn "#{conn_conf.conn_desc} has no #{args[1]} configuration."
32
+ exit 1
33
+ end
34
+ knock conn_conf.host, ports
35
+
36
+ # connect
37
+ elsif conn_conf = @conn_confs[args[0]]
38
+ warn "Ignoring arguments after #{args[0]}." if args.length > 1
39
+ parse_conf
40
+ ssh conn_conf
41
+
42
+ # help
43
+ elsif ['-h'].include? args[0]
44
+ warn "Ignoring arguments after #{args[0]}." if args.length > 1
45
+ print_help
46
+
47
+ # fail
48
+ else
49
+ warn "Invalid arguments."
50
+ print_help
51
+ exit 1
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def ssh c
58
+ port = (c.port && c.port != DEFAULT_PORT) ? "-p #{ c.port } " : ''
59
+ user = c.user ? "#{ c.user }@" : ''
60
+ knock c.host, c.knock if c.knock
61
+ system "ssh #{port}#{user}#{c.host}"
62
+ knock c.host, c.unknock if c.unknock
63
+ end
64
+
65
+ def knock host, ports
66
+ unless has_knock
67
+ msg = "Skipping knock!
68
+ The connection configuration has ports knock set but you don`t have 'knock' installed on your system.
69
+ Please install: 'apt-get install knockd', 'brew install knock', ...".strip_text
70
+ warn msg
71
+ return
72
+ end
73
+ run_cmd "knock #{ host } #{ ports.join ' ' }", false
74
+ end
75
+
76
+
77
+ # Conf
78
+
79
+ def parse_conf
80
+ unless File.exists? CONF_PATH
81
+ raise "#{CONF_PATH} not found. Install a sample with 'con setup'."
82
+ end
83
+ File.open(CONF_PATH).readlines.each do |line|
84
+ add_connection line.strip
85
+ end
86
+ end
87
+
88
+ def add_connection line
89
+ return if skip_line? line
90
+
91
+ values = line.split /\s+/
92
+
93
+ conn_conf = OpenStruct.new
94
+ CONF_LINE_FIELDS.each_with_index do |field, idx|
95
+ conn_conf[field.to_sym] = values[idx]
96
+ end
97
+
98
+ unless valid? conn_conf
99
+ warn "WARNING: Invalid line, skipping: '#{line}'"
100
+ return
101
+ end
102
+
103
+ adjust_conn_conf conn_conf
104
+
105
+ if @conn_confs[conn_conf.shortcut]
106
+ warn "WARNING: Shorcut '#{conn_conf.shortcut} is duplicated, skipping line: '#{line}'"
107
+ return
108
+ end
109
+
110
+ @conn_confs[conn_conf.shortcut] = conn_conf
111
+ end
112
+
113
+ def valid? c
114
+ c.shortcut &&
115
+ c.conn_desc &&
116
+ c.host
117
+ end
118
+
119
+ def adjust_conn_conf c
120
+ c.knock = c.knock.split ',' if c.knock
121
+ c.unknock = c.unknock.split ',' if c.unknock
122
+
123
+ if c.host =~ /^(.*?)@(.*?)$/
124
+ c.host = $2
125
+ c.user ||= $1
126
+ end
127
+ end
128
+
129
+ def install_sample_conf
130
+ if File.exists? CONF_PATH
131
+ warn "#{CONF_PATH} already exists. Skipping install."
132
+ return false
133
+ end
134
+ sample_conf = "# #{ CONF_LINE_FIELDS.join ' ' }
135
+ # *connection_desc must have no spaces.
136
+ # *user, port, knock, unknock are optionals.
137
+
138
+ s1 server_1 123.234.35.456
139
+ s1r server_1r root@123.234.35.456
140
+ s3 server_3 123.234.35.456 username 2222 knock unknock"
141
+ File.write CONF_PATH, sample_conf.strip_text
142
+ true
143
+ end
144
+
145
+
146
+ # Util
147
+
148
+ def warn desc
149
+ $stderr.puts desc
150
+ end
151
+
152
+ def skip_line? line
153
+ line =~ /^\s*[$#]/
154
+ end
155
+
156
+ def has_knock
157
+ !`which knock`.strip.empty?
158
+ end
159
+
160
+ def print_help
161
+ puts "Usage: con <shortcut>|setup [knock|unknock]".strip_text
162
+ end
163
+
164
+ def run_cmd cmd, print = true
165
+ puts "run: #{cmd}" if print
166
+ output = `#{cmd} 2>&1`
167
+ exit_status = $?.to_i
168
+ unless exit_status == 0
169
+ warn "Non-zero output: #{output}"
170
+ end
171
+ [exit_status, output]
172
+ end
173
+ end
@@ -0,0 +1,8 @@
1
+ require 'test/unit'
2
+ require 'ssh_con'
3
+
4
+ class SSHConTest < Test::Unit::TestCase
5
+ def test_run
6
+ SSHCon.new
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: con_ssh
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tom Lobato
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-06-23 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: SSH cli wrapper..
14
+ email: lobato@bettercall.io
15
+ executables:
16
+ - con
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".codeclimate.yml"
21
+ - ".gitignore"
22
+ - ".rubocop-custom.yml"
23
+ - ".ruby-version"
24
+ - README.md
25
+ - Rakefile
26
+ - TODO
27
+ - bin/con
28
+ - con_ssh.gemspec
29
+ - gempush
30
+ - lib/con_ssh.rb
31
+ - lib/con_ssh/core_extensions.rb
32
+ - test/con_ssh_test.rb
33
+ homepage:
34
+ licenses:
35
+ - MIT
36
+ metadata: {}
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 2.3.0
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubyforge_project:
53
+ rubygems_version: 2.5.1
54
+ signing_key:
55
+ specification_version: 4
56
+ summary: SSH cli wrapper.
57
+ test_files:
58
+ - test/con_ssh_test.rb