ssh-config 0.1.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.
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2008-2009 David Brady github@shinybit.com
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,66 @@
1
+ = ssh-config: A Tool for Managing ssh Config Files
2
+
3
+ == Overview
4
+
5
+ It's not THAT much trouble to update your .ssh/config file every time
6
+ a host changes, but when it starts happening often enough, even that
7
+ hassle starts to add up. This is a quick tool I wrote to help handle
8
+ them.
9
+
10
+ It takes great care to not trash your config file, so you can continue
11
+ to edit your config files by hand before and after running the tool.
12
+
13
+ ssh-config will make a backup of your ~/.ssh/config file as
14
+ ~/.ssh/config~.
15
+
16
+ Probably the most useful command is "copy", which intelligently copies
17
+ an existing host section.
18
+
19
+ == Commands
20
+
21
+ === set <host> <key> <value>
22
+
23
+ Adds or updates the value for a given host.
24
+
25
+ === unset <host> <key>
26
+
27
+ Removes a key value for a given host. NOTE: If all values are removed
28
+ from a section, the section is NOT removed; use rm <host> for that.
29
+
30
+ === rm <host>
31
+
32
+ Removes an entire host section.
33
+
34
+ === copy <old_host> <new_host>
35
+
36
+ Copies the entire section named <old_host> to a new section called
37
+ <new_host>. If old_host has a Hostname section, ssh-config will try to
38
+ update it to reflect the new_host name. For example, if you had a
39
+ section like
40
+
41
+ Host rails01
42
+ Hostname rails01.example.com
43
+
44
+ And you did ssh-config copy rails01 rails02, the new section would
45
+ look like this:
46
+
47
+ Host rails02
48
+ Hostname rails02.example.com
49
+
50
+ === dump
51
+
52
+ Dumps the entire file.
53
+
54
+ === show <host>
55
+
56
+ Dumps one section. (Similar to ssh-what.)
57
+
58
+ === search <pattern>
59
+
60
+ Shows all sections that have any line (key OR value) that matches
61
+ pattern. (Similar to ssh-what.)
62
+
63
+ === list
64
+
65
+ Lists all section names (just the Host line)
66
+
data/bin/ssh-config ADDED
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env ruby
2
+ require 'ftools'
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'ssh-config'))
4
+
5
+ # ssh-config - Manipulate config values in the .ssh/config file.
6
+ #
7
+ # ssh-config help
8
+ # ssh-config dump
9
+ # ssh-config list
10
+ # ssh-config show <host-nickname>
11
+ # ssh-config find <regex>
12
+ # ssh-config set <host-nickname> <setting> <value> [<setting> <value> [...]]
13
+ # Note: "<setting> -" deletes a setting
14
+ # ssh-config rm <host-nickname> # delete config settings for that host
15
+ # ssh-config copy <host-nickname> <new-host-nickname> # copy settings from one to the other.
16
+
17
+ config = ConfigFile.new
18
+ argv = ARGV
19
+ command = argv.shift
20
+
21
+ def usage
22
+ str =<<HELP
23
+ ssh-config - Configure your .ssh/config file
24
+
25
+ Usage:
26
+ ssh-config <command> <params>
27
+
28
+ Commands:
29
+ help - show this message
30
+ dump - parse and dump the config file
31
+ list - list configured hosts
32
+ show <host> - display the settings for host
33
+ find <pattern> - find all hosts with any detail matching pattern
34
+ set <host> <setting> <value> [<setting> <value> [...]] - set a value
35
+ NOTE: If host does not exist, it will be created
36
+ NOTE: If value is -, setting will be deleted, e.g. set User -
37
+ NOTE: If all values are deleted, section will NOT be removed, use rm instead
38
+ unset <host> <setting> - Remove a setting from a host section
39
+ rm <host> - Remove configuration for a host
40
+ copy <host> <newhost> - Duplicate the settings for a host
41
+ NOTE: If Hostname contains Host, new host will be automagically updated
42
+ HELP
43
+
44
+ end
45
+
46
+ case command
47
+ when 'help'
48
+ puts usage
49
+ when 'list'
50
+ puts config.list
51
+ when 'show'
52
+ puts config.show(argv.shift)
53
+ when 'search'
54
+ puts config.search(argv.shift)
55
+ when 'cp', 'copy'
56
+ config.copy! argv.shift, argv.shift
57
+ when 'unset'
58
+ config.unset!(argv.shift, *argv)
59
+ when 'set'
60
+ config.set!(*argv)
61
+ when 'rm', 'del', 'delete'
62
+ config.rm! argv.shift
63
+ when 'dump'
64
+ puts config.dump
65
+ end
66
+
@@ -0,0 +1,126 @@
1
+ class ConfigFile
2
+ def initialize
3
+ @make_backups = true
4
+ @header_lines = []
5
+ @sections = []
6
+ @sections_by_name = {}
7
+ read_config
8
+ end
9
+
10
+ def add_section(name)
11
+ section = ConfigSection.new(name)
12
+ @sections << section
13
+ @sections_by_name[name] = section
14
+ section
15
+ end
16
+
17
+ def read_config
18
+ current_section = nil
19
+ IO.readlines(File.expand_path("~/.ssh/config")).each_with_index do |line, i|
20
+ line.rstrip!
21
+ if line =~ /\bHost\s+(.+)/
22
+ current_section = add_section($1)
23
+ else
24
+ if current_section
25
+ current_section.lines << line
26
+ else
27
+ @header_lines << line
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def show(host_nick)
34
+ @sections_by_name[host_nick]
35
+ end
36
+
37
+ def list()
38
+ to_text(@sections_by_name.keys.sort.map {|name| "Host #{name}"})
39
+ end
40
+
41
+ def search(text)
42
+ to_text(@sections.find_all {|section| section.matches?(text)}.sort_by {|section| section.name})
43
+ end
44
+
45
+ def set!(host_nick, *args)
46
+ backup if @make_backups
47
+ while args.length > 0
48
+ key, value = args.shift, args.shift
49
+ section = set(host_nick, key, value)
50
+ end
51
+ save
52
+ section
53
+ end
54
+
55
+ def set(host_nick, key, value)
56
+ section = @sections_by_name[host_nick] || add_section(host_nick)
57
+ section[key] = value
58
+ end
59
+
60
+ def unset!(host_nick, *keys)
61
+ backup if @make_backups
62
+ while keys.length > 0
63
+ section = unset(host_nick, keys.shift)
64
+ end
65
+ save
66
+ section
67
+ end
68
+
69
+ def unset(host_nick, key)
70
+ if section = @sections_by_name[host_nick]
71
+ section.unset(key)
72
+ end
73
+ end
74
+
75
+ def dump
76
+ to_text([@header_lines, @sections].flatten)
77
+ end
78
+
79
+ def rm!(host_nick)
80
+ backup if @make_backups
81
+ rm(host_nick)
82
+ save
83
+ end
84
+
85
+ def rm(host_nick)
86
+ if @sections_by_name.key?(host_nick)
87
+ @sections_by_name.delete host_nick
88
+ @sections.delete_at(@sections.index{|s| s.name == host_nick})
89
+ end
90
+ end
91
+
92
+ def copy!(old_host_nick, new_host_nick)
93
+ backup if @make_backups
94
+ copy(old_host_nick, new_host_nick)
95
+ save
96
+ end
97
+
98
+ def copy(old_host_nick, new_host_nick)
99
+ if @sections_by_name.key?(old_host_nick)
100
+ old_section = @sections_by_name[old_host_nick]
101
+ new_section = @sections_by_name[new_host_nick] || add_section(new_host_nick)
102
+ new_section.lines = old_section.lines.dup
103
+
104
+ if old_section["Hostname"]
105
+ new_section["Hostname"] = old_section["Hostname"].gsub(old_host_nick, new_host_nick)
106
+ end
107
+ end
108
+ end
109
+
110
+ def save
111
+ File.open(File.expand_path("~/.ssh/config"), "w") do |file|
112
+ file.puts dump
113
+ end
114
+ end
115
+
116
+ def backup
117
+ File.copy(File.expand_path("~/.ssh/config"), File.expand_path("~/.ssh/config~"))
118
+ end
119
+
120
+ private
121
+
122
+ def to_text(ray)
123
+ ray.map {|s| s.to_s } * "\n"
124
+ end
125
+ end
126
+
@@ -0,0 +1,57 @@
1
+ class ConfigSection
2
+ attr_accessor :name, :lines, :settings
3
+
4
+ def initialize(name)
5
+ @name = name
6
+ @settings = {}
7
+ @lines = []
8
+ end
9
+
10
+ def [](setting)
11
+ unless @settings.key? setting
12
+ if line = lines[setting_index(setting)]
13
+ key,val = line.split(nil, 2)
14
+ @settings[key] = val
15
+ end
16
+ end
17
+ @settings[setting]
18
+ end
19
+
20
+ def unset(setting)
21
+ if line_num = setting_index(setting)
22
+ @settings.delete setting
23
+ @lines.delete_at line_num
24
+ end
25
+ end
26
+
27
+ def to_s
28
+ ["Host #{name}", *lines] * "\n"
29
+ end
30
+
31
+ def []=(setting, value)
32
+ if value != '-'
33
+ line_num = setting_index(setting) || lines.length
34
+ lines[line_num] = format_line(setting, value)
35
+ else
36
+ @settings.delete(setting)
37
+ @lines.delete_at(setting_index(setting))
38
+ end
39
+ end
40
+
41
+ def matches?(text)
42
+ r = Regexp.new text
43
+ name =~ r || lines.any? {|line| line =~ r}
44
+ end
45
+
46
+ protected
47
+
48
+ def format_line(setting, value)
49
+ " #{setting} #{value}"
50
+ end
51
+
52
+ def setting_index(setting)
53
+ r = Regexp.new(setting)
54
+ lines.index {|line| line =~ r}
55
+ end
56
+ end
57
+
data/lib/ssh-config.rb ADDED
@@ -0,0 +1,3 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'config_file'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), 'config_section'))
3
+
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ssh-config
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - David Brady
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-26 00:00:00 -06:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Ssh-Config, a tool that lets you quickly add, update, remove, and copy ssh config file entries.
22
+ email: github@shinybit.com
23
+ executables:
24
+ - ssh-config
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README.rdoc
29
+ - MIT-LICENSE
30
+ files:
31
+ - bin/ssh-config
32
+ - lib/config_file.rb
33
+ - lib/config_section.rb
34
+ - lib/ssh-config.rb
35
+ - README.rdoc
36
+ - MIT-LICENSE
37
+ has_rdoc: true
38
+ homepage: http://github.com/dbrady/ssh-config/
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --line-numbers
44
+ - --inline-source
45
+ - --main
46
+ - README.rdoc
47
+ - --title
48
+ - Ssh-Config - A Tool for ssh config files
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.6
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Ssh-Config - tool for managing your .ssh/config file
72
+ test_files: []
73
+