roast 0.1.2 → 0.2.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/README.md +3 -0
- data/lib/roast.rb +1 -0
- data/lib/roast/cli/commands.rb +18 -8
- data/lib/roast/group.rb +8 -4
- data/lib/roast/host.rb +18 -6
- data/lib/roast/hosts_file.rb +15 -6
- data/lib/roast/version.rb +1 -1
- data/roast.gemspec +1 -0
- data/test/files/one +1 -1
- data/test/host_test.rb +27 -4
- data/test/hosts_file_test.rb +17 -16
- data/test/test_helper.rb +2 -0
- metadata +18 -2
data/README.md
CHANGED
@@ -36,6 +36,9 @@ $ sudo roast add 10.0.1.1 something.dev
|
|
36
36
|
# add an entry to the "testing" group
|
37
37
|
$ sudo roast add testing 127.0.0.1 exampleapp.dev
|
38
38
|
|
39
|
+
# add an entry to the "testing" group via another hostname (resolve the ip)
|
40
|
+
$ sudo roast add testing example.org exampleapp.dev
|
41
|
+
|
39
42
|
# disable all entries with the ip "10.0.1.1"
|
40
43
|
$ sudo roast disable 10.0.1.1
|
41
44
|
|
data/lib/roast.rb
CHANGED
data/lib/roast/cli/commands.rb
CHANGED
@@ -21,23 +21,30 @@ module Roast
|
|
21
21
|
puts "`#{command}' is an unknown command, use --help to see available commands"
|
22
22
|
exit
|
23
23
|
end
|
24
|
+
rescue ArgumentError => e
|
25
|
+
puts e.message
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
|
29
|
+
def confirm(message = 'Are you sure that you want to do that?')
|
30
|
+
puts "#{message} [\"yes\" or \"no\"]"
|
31
|
+
exit if $stdin.gets.chomp !~ /\Ay(?:es)?\Z/i
|
24
32
|
end
|
25
33
|
|
26
34
|
def add(*args)
|
27
35
|
if args.length < 2
|
28
|
-
raise ArgumentError, "You must provide an ip address and a hostname to point it
|
36
|
+
raise ArgumentError, "You must provide an ip address and a hostname to point it to: `roast add 127.0.0.1 something.dev'"
|
29
37
|
elsif args.length == 3
|
30
38
|
group = args.shift
|
31
39
|
else
|
32
|
-
group =
|
40
|
+
group = nil
|
33
41
|
end
|
34
42
|
|
35
|
-
|
36
|
-
ip_address, hostname = args
|
43
|
+
source, hostname = args
|
37
44
|
|
38
|
-
if @hosts_file.add(group,
|
45
|
+
if @hosts_file.add(group, source, hostname)
|
39
46
|
@hosts_file.write
|
40
|
-
puts "added host entry for `#{
|
47
|
+
puts "added host entry for `#{source} \033[4m#{hostname}\033[0m'"
|
41
48
|
end
|
42
49
|
end
|
43
50
|
|
@@ -65,6 +72,7 @@ module Roast
|
|
65
72
|
|
66
73
|
def delete(*args)
|
67
74
|
entry = args.first
|
75
|
+
confirm("Are you sure that you want to delete entries matching `#{entry}'?")
|
68
76
|
results = @hosts_file.delete(entry)
|
69
77
|
if results.empty?
|
70
78
|
puts "no entries found matching `#{entry}'"
|
@@ -98,7 +106,7 @@ module Roast
|
|
98
106
|
|
99
107
|
def delete_group(*args)
|
100
108
|
group = args.first
|
101
|
-
|
109
|
+
confirm("Are you sure that you want to delete the group `#{group}'?")
|
102
110
|
if @hosts_file.delete_group(group)
|
103
111
|
@hosts_file.write
|
104
112
|
puts "deleted group `#{group}'"
|
@@ -115,7 +123,9 @@ module Roast
|
|
115
123
|
puts "there are no roast entries in `#{path}'\n"
|
116
124
|
else
|
117
125
|
entries = ''
|
118
|
-
groups.
|
126
|
+
indent = groups.map { |g| g.hosts.map { |h| h.hostname.size }.max }.max
|
127
|
+
|
128
|
+
groups.each { |group| entries << group.to_cli(indent) }
|
119
129
|
puts entries.chomp
|
120
130
|
end
|
121
131
|
end
|
data/lib/roast/group.rb
CHANGED
@@ -54,9 +54,9 @@ module Roast
|
|
54
54
|
deleted
|
55
55
|
end
|
56
56
|
|
57
|
-
def to_cli
|
57
|
+
def to_cli(max_indent = nil)
|
58
58
|
string = " - \033[4m#{name}\033[0m\n"
|
59
|
-
max
|
59
|
+
max = max_indent || hosts.map { |h| h.hostname.size }.max
|
60
60
|
|
61
61
|
hosts.each do |host|
|
62
62
|
padding = ' ' * (max - host.hostname.size + 4)
|
@@ -65,7 +65,9 @@ module Roast
|
|
65
65
|
else
|
66
66
|
string << ' '
|
67
67
|
end
|
68
|
-
string << "#{host.hostname}#{padding}#{host.ip_address}
|
68
|
+
string << "#{host.hostname}#{padding}#{host.ip_address}"
|
69
|
+
string << " # #{host.alias}" if host.alias
|
70
|
+
string << "\033[0m\n"
|
69
71
|
end
|
70
72
|
|
71
73
|
string
|
@@ -78,7 +80,9 @@ module Roast
|
|
78
80
|
hosts.each do |host|
|
79
81
|
padding = ' ' * (max - host.ip_address.size + 4)
|
80
82
|
section << '# ' if host.disabled?
|
81
|
-
section << "#{host.ip_address}#{padding}#{host.hostname}
|
83
|
+
section << "#{host.ip_address}#{padding}#{host.hostname}"
|
84
|
+
section << " # #{host.alias}" if host.alias
|
85
|
+
section << "\n"
|
82
86
|
end
|
83
87
|
|
84
88
|
section
|
data/lib/roast/host.rb
CHANGED
@@ -1,23 +1,35 @@
|
|
1
1
|
module Roast
|
2
2
|
class Host
|
3
|
-
IP_PATTERN = /\A
|
3
|
+
IP_PATTERN = /\A([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}\z/
|
4
4
|
HOST_PATTERN = /\A[a-z0-9\-\.]+\z/
|
5
5
|
|
6
|
-
attr_reader
|
7
|
-
attr_reader
|
6
|
+
attr_reader :ip_address
|
7
|
+
attr_reader :hostname
|
8
|
+
attr_reader :state
|
9
|
+
attr_accessor :alias
|
8
10
|
|
9
|
-
def initialize(
|
10
|
-
|
11
|
+
def initialize(source, hostname)
|
12
|
+
if source !~ IP_PATTERN
|
13
|
+
@alias = source.chomp
|
14
|
+
resolve_source
|
15
|
+
else
|
16
|
+
@ip_address = source.chomp
|
17
|
+
end
|
11
18
|
@hostname = hostname.chomp.downcase
|
12
19
|
@state = 'enabled'
|
13
20
|
validate!
|
14
21
|
end
|
15
22
|
|
16
23
|
def validate!
|
17
|
-
raise ArgumentError, "`#{ip_address}' is an invalid ip address" unless ip_address =~ IP_PATTERN
|
18
24
|
raise ArgumentError, "`#{hostname}' is an invalid hostname" unless hostname =~ HOST_PATTERN
|
19
25
|
end
|
20
26
|
|
27
|
+
def resolve_source
|
28
|
+
@ip_address = IPSocket.getaddress(@alias)
|
29
|
+
rescue SocketError
|
30
|
+
raise ArgumentError, "unable to determine the ip address of `#{@alias}'"
|
31
|
+
end
|
32
|
+
|
21
33
|
def disable!
|
22
34
|
@state = 'disabled'
|
23
35
|
end
|
data/lib/roast/hosts_file.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Roast
|
2
2
|
class HostsFile
|
3
3
|
GROUP_PATTERN = /^## \[([\w\s-]+)\]$/
|
4
|
-
HOST_PATTERN = /^#?\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+([
|
4
|
+
HOST_PATTERN = /^#?\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+([a-z0-9\.\-]+)\s*(?:#\s*(\S+))?$/
|
5
5
|
DISABLED_PATTERN = /^# \d+/
|
6
6
|
|
7
7
|
attr_reader :path
|
@@ -37,6 +37,7 @@ module Roast
|
|
37
37
|
@groups[group.name] ||= group
|
38
38
|
elsif group && host_match = line.match(HOST_PATTERN)
|
39
39
|
host = Host.new(host_match[1], host_match[2])
|
40
|
+
host.alias = host_match[3]
|
40
41
|
host.disable! if line =~ DISABLED_PATTERN
|
41
42
|
group << host
|
42
43
|
else
|
@@ -46,6 +47,9 @@ module Roast
|
|
46
47
|
end
|
47
48
|
|
48
49
|
self
|
50
|
+
rescue Errno::EACCES
|
51
|
+
puts "Unable to read hosts file: `#{@path}', you might need to `sudo roast'"
|
52
|
+
exit 1
|
49
53
|
end
|
50
54
|
|
51
55
|
def write(output_path = nil)
|
@@ -54,10 +58,14 @@ module Roast
|
|
54
58
|
|
55
59
|
temp_file << static_lines.join.sub(/\n{3,}\z/, "\n\n")
|
56
60
|
temp_file << groups.map { |g| g.to_hosts_file.chomp }.join("\n\n")
|
57
|
-
|
58
61
|
File.chmod(0644, temp_file.path)
|
59
|
-
|
60
|
-
|
62
|
+
begin
|
63
|
+
FileUtils.cp(path, path + '.roast.bak') if output_path.eql?(path)
|
64
|
+
FileUtils.mv(temp_file.path, output_path, :force => true)
|
65
|
+
rescue Errno::EACCES
|
66
|
+
puts "Unable to write to hosts file: `#{@path}', you might need to `sudo roast'"
|
67
|
+
exit 1
|
68
|
+
end
|
61
69
|
ensure
|
62
70
|
temp_file.close
|
63
71
|
temp_file.unlink
|
@@ -71,9 +79,10 @@ module Roast
|
|
71
79
|
groups.map { |g| g.delete_host(entry) }.flatten
|
72
80
|
end
|
73
81
|
|
74
|
-
def add(group,
|
82
|
+
def add(group, source, hostname)
|
83
|
+
group ||= 'base'
|
75
84
|
@groups[group] ||= Group.new(group)
|
76
|
-
@groups[group] << Host.new(
|
85
|
+
@groups[group] << Host.new(source, hostname)
|
77
86
|
end
|
78
87
|
|
79
88
|
def enable(entry)
|
data/lib/roast/version.rb
CHANGED
data/roast.gemspec
CHANGED
data/test/files/one
CHANGED
data/test/host_test.rb
CHANGED
@@ -2,10 +2,33 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
describe Roast::Host do
|
4
4
|
|
5
|
-
it "
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
it "initializes a Host" do
|
6
|
+
host = Roast::Host.new('127.0.0.1', 'blah.dev')
|
7
|
+
host.hostname.must_equal 'blah.dev'
|
8
|
+
host.ip_address.must_equal '127.0.0.1'
|
9
|
+
host.state.must_equal 'enabled'
|
10
|
+
host.must_be :enabled?
|
11
|
+
end
|
12
|
+
|
13
|
+
it "disables a host" do
|
14
|
+
host = Roast::Host.new('127.0.0.1', 'blah.dev')
|
15
|
+
host.state.must_equal 'enabled'
|
16
|
+
host.disable!
|
17
|
+
host.state.must_equal 'disabled'
|
18
|
+
host.must_be :disabled?
|
19
|
+
end
|
20
|
+
|
21
|
+
it "enables a host" do
|
22
|
+
host = Roast::Host.new('127.0.0.1', 'blah.dev')
|
23
|
+
host.disable!
|
24
|
+
host.must_be :disabled?
|
25
|
+
host.enable!
|
26
|
+
host.must_be :enabled?
|
27
|
+
end
|
28
|
+
|
29
|
+
it "attempts to resolve a source hostname if given" do
|
30
|
+
Roast::Host.any_instance.expects(:resolve_source)
|
31
|
+
Roast::Host.new('google.com', 'blah.dev')
|
9
32
|
end
|
10
33
|
|
11
34
|
it "validates the hostname" do
|
data/test/hosts_file_test.rb
CHANGED
@@ -15,10 +15,12 @@ describe Roast::HostsFile do
|
|
15
15
|
hosts.groups.length.must_equal 3
|
16
16
|
[
|
17
17
|
[ '127.0.0.1', 'local.dev' ],
|
18
|
-
[ '10.0.1.2', 'something.dev' ]
|
18
|
+
[ '10.0.1.2', 'something.dev' ],
|
19
|
+
[ '127.0.0.1', 'example.org', 'whatever.org']
|
19
20
|
].each_with_index do |host, i|
|
20
|
-
hosts['base'].hosts[i].ip_address.must_equal host
|
21
|
-
hosts['base'].hosts[i].hostname.must_equal host
|
21
|
+
hosts['base'].hosts[i].ip_address.must_equal host[0]
|
22
|
+
hosts['base'].hosts[i].hostname.must_equal host[1]
|
23
|
+
hosts['base'].hosts[i].alias.must_equal host[2] if host[2]
|
22
24
|
end
|
23
25
|
[
|
24
26
|
[ '10.0.20.1', 'staging.something.com' ],
|
@@ -48,7 +50,7 @@ describe Roast::HostsFile do
|
|
48
50
|
## [base]
|
49
51
|
127.0.0.1 local.dev
|
50
52
|
10.0.1.2 something.dev
|
51
|
-
127.0.0.1 example.org
|
53
|
+
127.0.0.1 example.org # whatever.org
|
52
54
|
|
53
55
|
## [foo]
|
54
56
|
# 10.0.3.1 foo.bar
|
@@ -82,7 +84,7 @@ describe Roast::HostsFile do
|
|
82
84
|
## [base]
|
83
85
|
127.0.0.1 local.dev
|
84
86
|
10.0.1.2 something.dev
|
85
|
-
127.0.0.1 example.org
|
87
|
+
127.0.0.1 example.org # whatever.org
|
86
88
|
|
87
89
|
## [foo]
|
88
90
|
# 10.0.3.1 foo.bar
|
@@ -118,7 +120,7 @@ describe Roast::HostsFile do
|
|
118
120
|
## [base]
|
119
121
|
# 127.0.0.1 local.dev
|
120
122
|
10.0.1.2 something.dev
|
121
|
-
127.0.0.1 example.org
|
123
|
+
127.0.0.1 example.org # whatever.org
|
122
124
|
|
123
125
|
## [foo]
|
124
126
|
# 10.0.3.1 foo.bar
|
@@ -151,7 +153,7 @@ describe Roast::HostsFile do
|
|
151
153
|
## [base]
|
152
154
|
# 127.0.0.1 local.dev
|
153
155
|
10.0.1.2 something.dev
|
154
|
-
# 127.0.0.1 example.org
|
156
|
+
# 127.0.0.1 example.org # whatever.org
|
155
157
|
|
156
158
|
## [foo]
|
157
159
|
# 10.0.3.1 foo.bar
|
@@ -184,7 +186,7 @@ describe Roast::HostsFile do
|
|
184
186
|
## [base]
|
185
187
|
127.0.0.1 local.dev
|
186
188
|
10.0.1.2 something.dev
|
187
|
-
127.0.0.1 example.org
|
189
|
+
127.0.0.1 example.org # whatever.org
|
188
190
|
|
189
191
|
## [foo]
|
190
192
|
# 10.0.3.1 foo.bar
|
@@ -217,7 +219,7 @@ describe Roast::HostsFile do
|
|
217
219
|
## [base]
|
218
220
|
127.0.0.1 local.dev
|
219
221
|
10.0.1.2 something.dev
|
220
|
-
127.0.0.1 example.org
|
222
|
+
127.0.0.1 example.org # whatever.org
|
221
223
|
|
222
224
|
## [foo]
|
223
225
|
# 10.0.3.1 foo.bar
|
@@ -250,7 +252,7 @@ describe Roast::HostsFile do
|
|
250
252
|
## [base]
|
251
253
|
127.0.0.1 local.dev
|
252
254
|
10.0.1.2 something.dev
|
253
|
-
127.0.0.1 example.org
|
255
|
+
127.0.0.1 example.org # whatever.org
|
254
256
|
|
255
257
|
## [foo]
|
256
258
|
10.0.3.1 foo.bar
|
@@ -283,7 +285,7 @@ describe Roast::HostsFile do
|
|
283
285
|
## [base]
|
284
286
|
127.0.0.1 local.dev
|
285
287
|
10.0.1.2 something.dev
|
286
|
-
127.0.0.1 example.org
|
288
|
+
127.0.0.1 example.org # whatever.org
|
287
289
|
|
288
290
|
## [foo]
|
289
291
|
# 10.0.3.1 foo.bar
|
@@ -315,7 +317,7 @@ describe Roast::HostsFile do
|
|
315
317
|
|
316
318
|
## [base]
|
317
319
|
10.0.1.2 something.dev
|
318
|
-
127.0.0.1 example.org
|
320
|
+
127.0.0.1 example.org # whatever.org
|
319
321
|
|
320
322
|
## [foo]
|
321
323
|
# 10.0.3.1 foo.bar
|
@@ -379,7 +381,7 @@ describe Roast::HostsFile do
|
|
379
381
|
## [base]
|
380
382
|
127.0.0.1 local.dev
|
381
383
|
10.0.1.2 something.dev
|
382
|
-
127.0.0.1 example.org
|
384
|
+
127.0.0.1 example.org # whatever.org
|
383
385
|
|
384
386
|
## [foo]
|
385
387
|
# 10.0.3.1 foo.bar
|
@@ -392,15 +394,14 @@ describe Roast::HostsFile do
|
|
392
394
|
hosts.groups.length.must_equal 3
|
393
395
|
hosts['base'] << Roast::Host.new('127.0.0.1', 'example.org')
|
394
396
|
hosts.write(File.join(FILES_PATH, 'two.new'))
|
395
|
-
File.exist?(File.join(FILES_PATH, 'one.bak')).wont_equal true
|
397
|
+
File.exist?(File.join(FILES_PATH, 'one.roast.bak')).wont_equal true
|
396
398
|
end
|
397
399
|
|
398
400
|
it "creates a backup file if the output file is the same as the input file" do
|
399
401
|
hosts = hosts_from_file('one')
|
400
402
|
hosts.groups.length.must_equal 3
|
401
|
-
hosts['base'] << Roast::Host.new('127.0.0.1', 'example.org')
|
402
403
|
hosts.write
|
403
|
-
File.exist?(File.join(FILES_PATH, 'one.bak')).must_equal true
|
404
|
+
File.exist?(File.join(FILES_PATH, 'one.roast.bak')).must_equal true
|
404
405
|
end
|
405
406
|
|
406
407
|
def hosts_from_file(file_name)
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roast
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 3.0.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: mocha
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.13.3
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.13.3
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: rake
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|