hoster 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ Hoster
2
+ =====
3
+
4
+ Summary
5
+ -------
6
+
7
+ A *cross-platform* gem that allows you to create, list, and modify local hostnames with ease. This gem was inspired by (and largely based on) the [ghost gem](http://github.com/bjeanes/ghost/tree/master) by Bodaniel Jeanes.
8
+
9
+ Hoster directly modifies the *hosts* file on you machine to add/remove entries. Because of this, Hoster must be executed as root user (or via *sudo*)
10
+
11
+
12
+ Usage
13
+ -----
14
+
15
+ $ hoster add testsite.com (defaults to 127.0.0.1)
16
+
17
+ $ hoster add testsite.com 192.168.1.150
18
+
19
+ $ hoster modify testsite.com 192.168.1.149
20
+
21
+ $ hoster remove testsite.com
22
+
23
+ $ hoster list (prints entire hosts file)
24
+
25
+ $ hoster list 127.0.0.1
26
+
27
+
28
+ Installation
29
+ ------------
30
+
31
+ sudo gem install sant0sk1-hoster --source http://gems.github.com/
32
+
33
+
34
+ License
35
+ -------
36
+
37
+ Copyright (c) 2009 Jerod Santo
38
+
39
+ Permission is hereby granted, free of charge, to any person obtaining
40
+ a copy of this software and associated documentation files (the
41
+ "Software"), to deal in the Software without restriction, including
42
+ without limitation the rights to use, copy, modify, merge, publish,
43
+ distribute, sublicense, and/or sell copies of the Software, and to
44
+ permit persons to whom the Software is furnished to do so, subject to
45
+ the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be
48
+ included in all copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
51
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
52
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
53
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
54
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
55
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
56
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/bin/hoster ADDED
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created by Jerod Santo on 2009-01-13
4
+ # Copyright (c) 2009. All rights reserved.
5
+
6
+ begin
7
+ require 'rubygems'
8
+ require 'hoster'
9
+ rescue LoadError
10
+ # no rubygems to load, so we fail silently
11
+ end
12
+
13
+ def help_text(exit_code = 0)
14
+ script_name = File.basename $0
15
+ puts """USAGE: #{script_name} add <hostname> [<ip=127.0.1.1>]
16
+ #{script_name} modify <hostname> <ip>
17
+ #{script_name} remove <hostname>
18
+ #{script_name} list [<ip>=all]
19
+ """
20
+ exit(exit_code)
21
+ end
22
+
23
+ if ARGV.size.zero? || ['-h', '--help', 'help'].include?(ARGV.first)
24
+ help_text
25
+ else
26
+ hosts = Hosts.new()
27
+ case ARGV[0]
28
+ when 'add':
29
+ if ARGV.size == 2
30
+ ARGV.shift
31
+ hosts.add(ARGV[0])
32
+ hosts.display
33
+ exit 0
34
+ elsif ARGV.size == 3
35
+ ARGV.shift
36
+ hosts.add(ARGV[0],ARGV[1])
37
+ hosts.display(ARGV[1])
38
+ else
39
+ $stderr.puts "The 'add' command requires at least a hostname.\n\n"
40
+ help_text 2
41
+ end
42
+ when 'modify':
43
+ if ARGV.size == 3
44
+ ARGV.shift
45
+ hosts.modify(ARGV[0],ARGV[1])
46
+ hosts.display(ARGV[1])
47
+ exit 0
48
+ else
49
+ $stderr.puts "The 'modify' command requires a hostname and an IP.\n\n"
50
+ help_text 4
51
+ end
52
+ when 'remove':
53
+ if ARGV.size == 2
54
+ hosts.remove(ARGV[1])
55
+ puts " Removed #{ARGV[1]}"
56
+ exit 0
57
+ else
58
+ $stderr.puts "The 'remove' command requires a hostname.\n\n"
59
+ help_text 2
60
+ end
61
+ when 'list':
62
+ if ARGV.size == 2
63
+ hosts.display(ARGV[1])
64
+ else
65
+ puts hosts.dump
66
+ end
67
+ exit 0
68
+ else
69
+ $stderr.puts "Invalid option: #{ARGV[0]}"
70
+ help_text 1
71
+ end
72
+ end
@@ -0,0 +1,106 @@
1
+ class Hosts
2
+
3
+ # disclaimer: I didn't test this because I didn't have windows around.
4
+ if RUBY_PLATFORM =~ /mswin32/
5
+ @@default_hosts_path = 'C:\WINDOWS\system32\drivers\etc\hosts'
6
+ else
7
+ @@default_hosts_path = '/etc/hosts'
8
+ end
9
+
10
+ attr_reader :entries
11
+
12
+ def initialize(hosts_path = @@default_hosts_path)
13
+ @hosts_path = hosts_path
14
+ @entries = extract_entries
15
+ end
16
+
17
+ def dump
18
+ File.open(@hosts_path,"r") { |f| f.read }
19
+ end
20
+
21
+ def add(host, ip_address = "127.0.0.1")
22
+ if @entries.has_key?(ip_address)
23
+ @entries[ip_address] << host
24
+ else
25
+ @entries[ip_address] = [host]
26
+ end
27
+ write_changes!
28
+ end
29
+
30
+ def remove(host)
31
+ @entries.each_pair { |key,value| value.delete_if { |v| v == host } }
32
+ write_changes!
33
+ end
34
+
35
+ def modify(host, ip_address)
36
+ host_exists = false
37
+ @entries.each_value { |v| host_exists = true if v.include?(host) }
38
+ if host_exists
39
+ remove(host)
40
+ add(host,ip_address)
41
+ else
42
+ raise "#{host} does not exist. Please use 'add' command instead."
43
+ end
44
+ end
45
+
46
+ def display(ip_address="127.0.0.1")
47
+ puts " #{ip_address} = #{@entries.values_at(ip_address).join(' ')}\n"
48
+ end
49
+
50
+ private
51
+
52
+ def extract_entries
53
+ entries = Hash.new
54
+ File.open(@hosts_path,"r").each do |line|
55
+ if line =~ /^(\d+\.\d+\.\d+\.\d+) (.*)/
56
+ ip_address = $1
57
+ hosts_list = $2.split(' ')
58
+ if entries.has_key?(ip_address)
59
+ hosts_list.each do |host|
60
+ entries[ip_address] << host
61
+ end
62
+ else
63
+ entries[ip_address] = hosts_list
64
+ end
65
+ end
66
+ end
67
+ entries
68
+ end
69
+
70
+ def write_changes!
71
+ @entries.each do |entry|
72
+ append_this = true
73
+ entry_exists = false
74
+
75
+ begin
76
+ File.open(@hosts_path,"r+") do |file|
77
+ lines = file.readlines
78
+ lines.each_with_index do |line,index|
79
+ if line =~ /#{entry.first}/
80
+ if entry_exists || entry.last.empty?
81
+ lines.delete_at(index)
82
+ else
83
+ lines[index] = "#{entry.first} #{entry.last.join(' ')}\n"
84
+ # update the state of this entry
85
+ append_this = false
86
+ entry_exists = true
87
+ end
88
+ end
89
+ end
90
+ file.pos = 0
91
+ file.print lines
92
+ file.truncate(file.pos)
93
+ end
94
+ if append_this && !entry.last.empty?
95
+ File.open(@hosts_path,"a") do |file|
96
+ file.print "#{entry.first} #{entry.last.join(' ')}\n"
97
+ end
98
+ end
99
+ rescue Errno::EACCES
100
+ puts "You do not have permission to edit #{@hosts_path}. Run as root or use 'sudo'"
101
+ exit 1
102
+ end
103
+ end
104
+ end
105
+
106
+ end
data/lib/hoster.rb ADDED
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+ require 'hoster/hosts'
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'hoster'
@@ -0,0 +1,90 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require 'rubygems'
3
+ require 'test/unit'
4
+ require 'shoulda'
5
+
6
+ BaseFile = <<CONTENT
7
+ 127.0.0.1 localhost
8
+ 127.0.1.1 localhost
9
+ 192.168.1.1 router.com router
10
+ 192.168.1.2 localhost
11
+ 127.0.0.1 test.com
12
+ 192.168.1.2 local.host
13
+ CONTENT
14
+
15
+ ModifiedFile = <<CONTENT
16
+ 127.0.0.1 localhost test.com test.dev
17
+ 127.0.1.1 localhost
18
+ 192.168.1.1 router router.org
19
+ 192.168.1.2 localhost local.host
20
+ 192.165.0.1 test.net
21
+ CONTENT
22
+
23
+ class TestHoster < Test::Unit::TestCase
24
+ context "Reading and parsing hosts file" do
25
+ setup do
26
+ File.open("test/hosts","w") do |file|
27
+ file.puts BaseFile
28
+ end
29
+ @hoster = Hosts.new("test/hosts")
30
+ end
31
+
32
+ should "create an object that stores a Hash" do
33
+ assert_kind_of Hash, @hoster.entries
34
+ end
35
+
36
+ should "assign ip addresses as hash keys" do
37
+ assert @hoster.entries.has_key?("127.0.0.1")
38
+ end
39
+
40
+ should "store a hosts array as hash values" do
41
+ assert_kind_of Array, @hoster.entries.values.first
42
+ end
43
+
44
+ should "map multiple hosts to ip addresses on the same line" do
45
+ assert_equal "router.com", @hoster.entries["192.168.1.1"].first
46
+ assert_equal "router", @hoster.entries["192.168.1.1"].last
47
+ end
48
+
49
+ should "map multiple hosts to same ip address on different lines" do
50
+ assert_equal "localhost", @hoster.entries["127.0.0.1"].first
51
+ assert_equal "test.com", @hoster.entries["127.0.0.1"].last
52
+ end
53
+
54
+ end
55
+
56
+ context "Manipulating hosts file" do
57
+ setup do
58
+ File.open("test/hosts","w") do |file|
59
+ file.puts BaseFile
60
+ end
61
+ @hoster = Hosts.new("test/hosts")
62
+ end
63
+
64
+ should "add a host to the correct line for specified ip address" do
65
+ assert_equal 2, @hoster.entries["192.168.1.1"].size
66
+ @hoster.add("router.org","192.168.1.1")
67
+ assert_equal 3, @hoster.entries["192.168.1.1"].size
68
+ end
69
+
70
+ should "remove correct host from line for specified ip address" do
71
+ assert_equal 2, @hoster.entries["192.168.1.1"].size
72
+ @hoster.remove("router.com")
73
+ assert_equal 1, @hoster.entries["192.168.1.1"].size
74
+ assert_equal "router", @hoster.entries["192.168.1.1"].first
75
+ end
76
+
77
+ should "add a new ip address if it doesn't exist" do
78
+ @hoster.add("test.net","192.165.0.1")
79
+ assert_equal "test.net", @hoster.entries["192.165.0.1"].first
80
+ end
81
+
82
+ should "write correct changes to file" do
83
+ @hoster.add("test.dev")
84
+ @hoster.add("router.org","192.168.1.1")
85
+ @hoster.add("test.net","192.165.0.1")
86
+ @hoster.remove("router.com")
87
+ assert_equal ModifiedFile, @hoster.dump
88
+ end
89
+ end
90
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hoster
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Jerod Santo
8
+ autorequire: hoster
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-26 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: jerod.santo@gmail.com
18
+ executables:
19
+ - hoster
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README.md
26
+ - bin/hoster
27
+ - lib/hoster/hosts.rb
28
+ - lib/hoster.rb
29
+ has_rdoc: true
30
+ homepage: http://github.com/sant0sk1/hoster
31
+ licenses: []
32
+
33
+ post_install_message:
34
+ rdoc_options: []
35
+
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project:
53
+ rubygems_version: 1.3.5
54
+ signing_key:
55
+ specification_version: 3
56
+ summary: Allows you to easily modify your local hosts file using one simple command
57
+ test_files:
58
+ - test/test_helper.rb
59
+ - test/test_hoster.rb