ssh-conf 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/bin/ssh-conf +49 -0
- data/lib/ssh-conf.rb +2 -0
- data/lib/ssh-conf/version.rb +5 -0
- data/lib/ssh_config.rb +181 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NjIyYjA5MGJlZjQzOGNkZGVjNGQ3ODk4MTRiMjBjNzMwZmQxODk5Ng==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OGQ3M2JhYmUzNmViMGUzNzdiNzQ3ODllNjM0ZjFkZWRmMjQzMTU3MA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZmYxM2QwZDJmNzU1MDc5N2VjYWJmNDIwZTEzOGY2MDkxYmM0OTFjZjA5MDYy
|
10
|
+
MmZkNDFlODY1Y2M5MDZhMzkxMGFjMDcwNTlhZjBkYTkxNDU0NWVkMjM0Mjdj
|
11
|
+
M2I3NmQ0MTQ0YjIzZTA5OTEyMmNiYmZmMjFkOTVhZmYyYTgzZDU=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MjFmNTU2NDMzOTk0OWM3ZmQzODA0ZDEzZDgzMjg3MGNmYzQ3ODIxMmY4ZDEx
|
14
|
+
NGJkOThmYWE3MDg3NDMyZDg0NzQ1NDY4MWU3ZjZiM2RiODYzODM2Y2JhYjNl
|
15
|
+
ZGMwODA0OTQ1YzdiM2I3M2YxN2QxYWNjYzgxYWZhYTA0ODMxYjU=
|
data/bin/ssh-conf
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'ssh-conf'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
optparse = OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: ssh-conf [options]"
|
10
|
+
|
11
|
+
opts.on("-a", "--all", "Search all default SSH conf files on system") do |v|
|
12
|
+
options[:all] = true
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on("-f", "--files FILES", "Comma separated list of files to process") do |f|
|
16
|
+
options[:files] = f
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on("-p", "--pretty", "Pretty output") do |v|
|
20
|
+
options[:pretty] = true
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on("-f", "--format format", [:text, :json], "Output format (text, json)") do |f|
|
24
|
+
options[:format] = f
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-v", "--version", "Gem version") do |f|
|
28
|
+
puts "ssh-conf: #{Ssh::Config::VERSION}"
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
33
|
+
puts opts
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
begin
|
39
|
+
optparse.parse!
|
40
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument, OptionParser::InvalidArgument
|
41
|
+
puts $!.to_s
|
42
|
+
puts optparse
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
sshconf = Ssh::Config.new(ARGV, options)
|
48
|
+
|
49
|
+
puts sshconf.output
|
data/lib/ssh-conf.rb
ADDED
data/lib/ssh_config.rb
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Ssh
|
4
|
+
class Config
|
5
|
+
def initialize(hosts, options = {})
|
6
|
+
@hosts = hosts
|
7
|
+
@options = options
|
8
|
+
@results = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def output
|
12
|
+
method = "text"
|
13
|
+
|
14
|
+
if @options[:format] == :json
|
15
|
+
method = "json"
|
16
|
+
end
|
17
|
+
|
18
|
+
if @options[:pretty]
|
19
|
+
method = "pretty_#{method}"
|
20
|
+
end
|
21
|
+
|
22
|
+
send("as_#{method}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def as_text
|
26
|
+
out = ''
|
27
|
+
|
28
|
+
results.each do |host, config|
|
29
|
+
out << "Host\t#{host}\n"
|
30
|
+
|
31
|
+
config.each do |key, value|
|
32
|
+
out << "#{key}\t#{value}\n"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
out
|
37
|
+
end
|
38
|
+
|
39
|
+
def as_pretty_text
|
40
|
+
longest = results.values.map(&:flatten).flatten
|
41
|
+
.max { |a, b| a.length <=> b.length }.length + 2
|
42
|
+
|
43
|
+
out = ''
|
44
|
+
results.each do |host, config|
|
45
|
+
out << sprintf("%-#{longest}s %s\n", 'Host', host)
|
46
|
+
|
47
|
+
config.each do |key, value|
|
48
|
+
out << sprintf("%-#{longest}s %s\n", key, value)
|
49
|
+
end
|
50
|
+
|
51
|
+
out << "\n"
|
52
|
+
end
|
53
|
+
|
54
|
+
out
|
55
|
+
end
|
56
|
+
|
57
|
+
def as_json
|
58
|
+
JSON.dump(results)
|
59
|
+
end
|
60
|
+
|
61
|
+
def as_pretty_json
|
62
|
+
JSON.pretty_generate(results)
|
63
|
+
end
|
64
|
+
|
65
|
+
def results
|
66
|
+
if @results.empty?
|
67
|
+
@hosts.each do |host|
|
68
|
+
config = self.for(host)
|
69
|
+
config.each do |key, value|
|
70
|
+
case value
|
71
|
+
when Array
|
72
|
+
config[key] = value.join(',')
|
73
|
+
when String
|
74
|
+
else
|
75
|
+
config[key] = value.to_s
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
@results[host] = config
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
@results
|
84
|
+
end
|
85
|
+
|
86
|
+
def for(host)
|
87
|
+
files.inject({}) { |settings, file|
|
88
|
+
load(file, host, settings)
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def load(path, host, settings={})
|
93
|
+
file = File.expand_path(path)
|
94
|
+
return settings unless File.readable?(file)
|
95
|
+
|
96
|
+
globals = {}
|
97
|
+
matched_host = nil
|
98
|
+
seen_host = false
|
99
|
+
IO.foreach(file) do |line|
|
100
|
+
next if line =~ /^\s*(?:#.*)?$/
|
101
|
+
|
102
|
+
if line =~ /^\s*(\S+)\s*=(.*)$/
|
103
|
+
key, value = $1, $2
|
104
|
+
else
|
105
|
+
key, value = line.strip.split(/\s+/, 2)
|
106
|
+
end
|
107
|
+
|
108
|
+
# silently ignore malformed entries
|
109
|
+
next if value.nil?
|
110
|
+
|
111
|
+
value = $1 if value =~ /^"(.*)"$/
|
112
|
+
|
113
|
+
value = case value.strip
|
114
|
+
when /^\d+$/ then value.to_i
|
115
|
+
when /^no$/i then false
|
116
|
+
when /^yes$/i then true
|
117
|
+
else value
|
118
|
+
end
|
119
|
+
|
120
|
+
if key == 'Host'
|
121
|
+
# Support "Host host1 host2 hostN".
|
122
|
+
# See http://github.com/net-ssh/net-ssh/issues#issue/6
|
123
|
+
negative_hosts, positive_hosts = value.to_s.split(/\s+/).partition { |h| h.start_with?('!') }
|
124
|
+
|
125
|
+
# Check for negative patterns first. If the host matches, that overrules any other positive match.
|
126
|
+
# The host substring code is used to strip out the starting "!" so the regexp will be correct.
|
127
|
+
negative_match = negative_hosts.select { |h| host =~ pattern2regex(h[1..-1]) }.first
|
128
|
+
|
129
|
+
if negative_match
|
130
|
+
matched_host = nil
|
131
|
+
else
|
132
|
+
matched_host = positive_hosts.select { |h| host =~ pattern2regex(h) }.first
|
133
|
+
end
|
134
|
+
|
135
|
+
seen_host = true
|
136
|
+
settings.delete(key)
|
137
|
+
elsif !seen_host
|
138
|
+
if key == 'IdentityFile'
|
139
|
+
(globals[key] ||= []) << value
|
140
|
+
else
|
141
|
+
globals[key] = value unless settings.key?(key)
|
142
|
+
end
|
143
|
+
elsif !matched_host.nil?
|
144
|
+
if key == 'IdentityFile'
|
145
|
+
(settings[key] ||= []) << value
|
146
|
+
else
|
147
|
+
settings[key] = value unless settings.key?(key)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
settings = globals.merge(settings) if globals
|
153
|
+
|
154
|
+
return settings
|
155
|
+
end
|
156
|
+
|
157
|
+
def files
|
158
|
+
if @options[:files]
|
159
|
+
@options[:files].split(',')
|
160
|
+
elsif @options[:all]
|
161
|
+
%w(~/.ssh/config /etc/ssh_config /etc/ssh/ssh_config)
|
162
|
+
else
|
163
|
+
%w( ~/.ssh/config )
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
# Converts an ssh_config pattern into a regex for matching against
|
170
|
+
# host names.
|
171
|
+
def pattern2regex(pattern)
|
172
|
+
pattern = "^" + pattern.to_s.gsub(/\./, "\\.").
|
173
|
+
gsub(/\?/, '.').
|
174
|
+
gsub(/([+\/])/, '\\\\\\0').
|
175
|
+
gsub(/\*/, '.*') + "$"
|
176
|
+
Regexp.new(pattern, true)
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ssh-conf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nenad Petronijevic
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Displays ssh config for given hosts
|
28
|
+
email:
|
29
|
+
- set.krag@gmail.com
|
30
|
+
executables:
|
31
|
+
- ssh-conf
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- bin/ssh-conf
|
36
|
+
- lib/ssh-conf.rb
|
37
|
+
- lib/ssh-conf/version.rb
|
38
|
+
- lib/ssh_config.rb
|
39
|
+
homepage: https://github.com/arr-dev/ssh-conf
|
40
|
+
licenses:
|
41
|
+
- MIT
|
42
|
+
metadata: {}
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
requirements: []
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 2.4.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: Displays ssh config for given hosts, with different output options
|
63
|
+
test_files: []
|