ghost 0.3.0 → 1.0.0.pre

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.
Files changed (46) hide show
  1. data/LICENSE +1 -1
  2. data/bin/ghost +2 -130
  3. data/lib/ghost.rb +3 -16
  4. data/lib/ghost/cli.rb +60 -0
  5. data/lib/ghost/cli/task.rb +71 -0
  6. data/lib/ghost/cli/task/add.rb +25 -0
  7. data/lib/ghost/cli/task/delete.rb +30 -0
  8. data/lib/ghost/cli/task/empty.rb +18 -0
  9. data/lib/ghost/cli/task/export.rb +19 -0
  10. data/lib/ghost/cli/task/help.rb +41 -0
  11. data/lib/ghost/cli/task/import.rb +25 -0
  12. data/lib/ghost/cli/task/list.rb +40 -0
  13. data/lib/ghost/host.rb +34 -0
  14. data/lib/ghost/store.rb +12 -0
  15. data/lib/ghost/store/dscl_store.rb +71 -0
  16. data/lib/ghost/store/hosts_file_store.rb +123 -0
  17. data/lib/ghost/tokenized_file.rb +65 -0
  18. data/lib/ghost/version.rb +3 -0
  19. data/spec/ghost/cli/task/add_spec.rb +80 -0
  20. data/spec/ghost/cli/task/delete_spec.rb +20 -0
  21. data/spec/ghost/cli/task/empty_spec.rb +19 -0
  22. data/spec/ghost/cli/task/export_spec.rb +16 -0
  23. data/spec/ghost/cli/task/help_spec.rb +36 -0
  24. data/spec/ghost/cli/task/import_spec.rb +56 -0
  25. data/spec/ghost/cli/task/list_spec.rb +50 -0
  26. data/spec/ghost/cli_spec.rb +22 -0
  27. data/spec/ghost/host_spec.rb +36 -0
  28. data/spec/ghost/store/dscl_store_spec.rb +153 -0
  29. data/spec/ghost/store/hosts_file_store_spec.rb +316 -0
  30. data/spec/ghost/store_spec.rb +2 -0
  31. data/spec/ghost/tokenized_file_spec.rb +131 -0
  32. data/spec/spec_helper.rb +4 -2
  33. data/spec/support/cli.rb +29 -0
  34. data/spec/support/resolv.rb +15 -0
  35. metadata +91 -27
  36. data/Rakefile +0 -28
  37. data/TODO +0 -0
  38. data/bin/ghost-ssh +0 -132
  39. data/lib/ghost/linux-host.rb +0 -158
  40. data/lib/ghost/mac-host.rb +0 -116
  41. data/lib/ghost/ssh_config.rb +0 -110
  42. data/spec/etc_hosts_spec.rb +0 -190
  43. data/spec/ghost_spec.rb +0 -151
  44. data/spec/spec.opts +0 -1
  45. data/spec/ssh_config_spec.rb +0 -80
  46. data/spec/ssh_config_template +0 -11
@@ -0,0 +1,2 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper.rb")
2
+ require 'ghost/store'
@@ -0,0 +1,131 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper.rb")
2
+ require 'ghost/tokenized_file'
3
+
4
+ require 'tmpdir'
5
+ require 'fileutils'
6
+
7
+ describe Ghost::TokenizedFile do
8
+ let(:file) { File.open(file_path, 'r+') }
9
+ let(:file_path) { File.join(Dir.tmpdir, "tokenized_file.#{Process.pid}.#{rand(9999999)}") }
10
+ let(:tokenized_file) { Ghost::TokenizedFile.new(file_path, start_token, end_token) }
11
+ let(:start_token) { "# start" }
12
+ let(:end_token) { "# end" }
13
+
14
+ before { FileUtils.touch(file_path) }
15
+
16
+ describe "#read" do
17
+ context "with empty file" do
18
+ it "returns empty string" do
19
+ tokenized_file.read.should == ""
20
+ end
21
+ end
22
+
23
+ context "with a non-empty file with no tokens" do
24
+ before do
25
+ file.write "hi there"
26
+ file.close
27
+ end
28
+
29
+ it "returns empty string" do
30
+ tokenized_file.read.should == ""
31
+ end
32
+ end
33
+
34
+ context 'with a non-empty file with content between tokens' do
35
+ before do
36
+ file.write "#{start_token}\nline 1\nline 2\n#{end_token}"
37
+ file.close
38
+ end
39
+
40
+ it "returns empty string" do
41
+ tokenized_file.read.should == "line 1\nline 2\n"
42
+ end
43
+ end
44
+
45
+ context 'with a non-empty file with empty tokens' do
46
+ before do
47
+ file.write "#{start_token}\n#{end_token}"
48
+ file.flush
49
+ file.rewind
50
+ end
51
+
52
+ it "returns empty string" do
53
+ tokenized_file.read.should == ""
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "#write" do
59
+ context 'writing to a file with existing content' do
60
+ context "with no tokens" do
61
+ before do
62
+ file.write "xyz"
63
+ file.flush
64
+ file.rewind
65
+ end
66
+
67
+ it "doesn't change file contents when writing nothing" do
68
+ tokenized_file.write ""
69
+ file.read.should == "xyz\n"
70
+ end
71
+
72
+ it "inserts appends new content to file between tokens" do
73
+ tokenized_file.write "abc"
74
+ file.read.should == "xyz\n#{start_token}\nabc\n#{end_token}\n"
75
+ end
76
+ end
77
+
78
+ context "with empty tokens" do
79
+ before do
80
+ file.write "#{start_token}\n#{end_token}\nxyz"
81
+ file.flush
82
+ file.rewind
83
+ end
84
+
85
+ it "removes the token when writing an nothing" do
86
+ tokenized_file.write ""
87
+ file.read.should == "xyz\n"
88
+ end
89
+
90
+ it "adds content between the tokens when writing content" do
91
+ tokenized_file.write "foo"
92
+ file.read.should == "xyz\n#{start_token}\nfoo\n#{end_token}\n"
93
+ end
94
+ end
95
+
96
+ context "with non-empty tokens" do
97
+ before do
98
+ file.write "#{start_token}\nfoo\n#{end_token}\nxyz"
99
+ file.flush
100
+ file.rewind
101
+ end
102
+
103
+ it "removes the token when writing an nothing" do
104
+ tokenized_file.write ""
105
+ file.read.should == "xyz\n"
106
+ end
107
+
108
+ it "replaces the content between the tokens when writing new content" do
109
+ tokenized_file.write "bar"
110
+ file.read.should == "xyz\n#{start_token}\nbar\n#{end_token}\n"
111
+ end
112
+ end
113
+ end
114
+
115
+ context "writing to an empty file" do
116
+ context "when writing nothing" do
117
+ it "writes nothing to the file" do
118
+ tokenized_file.write ""
119
+ file.read.should == ""
120
+ end
121
+ end
122
+
123
+ context "when writing something" do
124
+ it "writes content to the file between tokens" do
125
+ tokenized_file.write "a"
126
+ file.read.should == "#{start_token}\na\n#{end_token}\n"
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -1,4 +1,6 @@
1
- $TESTING=true
2
1
  $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
3
  require 'rubygems'
4
- require 'spec'
4
+ require 'rspec'
5
+
6
+ Dir[File.join(File.dirname(__FILE__), "support", "*")].each { |f| require(f) }
@@ -0,0 +1,29 @@
1
+ require 'fileutils'
2
+ require 'tempfile'
3
+ require 'tmpdir'
4
+
5
+ module CliSpecs
6
+ def self.included(klass)
7
+ klass.before do
8
+ FileUtils.touch(store_path)
9
+ Ghost.store = store
10
+ end
11
+
12
+ klass.let(:store_path) { File.join(Dir.tmpdir, "etc_hosts.#{Process.pid}.#{rand(9999)}") }
13
+ klass.let(:store) { Ghost::Store::HostsFileStore.new(store_path) }
14
+ end
15
+
16
+ def ghost(args)
17
+ out = StringIO.new
18
+ Ghost::Cli.new(out).parse(args.split(/\s+/))
19
+ out.rewind
20
+ out.read
21
+ rescue SystemExit
22
+ out.rewind
23
+ out.read
24
+ end
25
+ end
26
+
27
+ RSpec.configure do |c|
28
+ c.include CliSpecs, :type => :cli
29
+ end
@@ -0,0 +1,15 @@
1
+ require 'ipaddr'
2
+
3
+ RSpec.configure do |c|
4
+ IP_ADDRESS_REGEX = /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/
5
+
6
+ c.before do
7
+ Ghost::Host.any_instance.stub(:resolve_ip) do |ip_or_hostname|
8
+ if ip_or_hostname =~ IP_ADDRESS_REGEX
9
+ ip_or_hostname
10
+ else
11
+ raise "Don't resolve in tests!"
12
+ end
13
+ end
14
+ end
15
+ end
metadata CHANGED
@@ -1,48 +1,96 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ghost
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
5
- prerelease:
4
+ version: 1.0.0.pre
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Bodaniel Jeanes
9
- autorequire: ghost
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-18 00:00:00.000000000Z
13
- dependencies: []
14
- description: Allows you to create, list, and modify local hostnames
12
+ date: 2012-09-05 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: unindent
16
+ requirement: &70100277448360 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - =
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70100277448360
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &70100277447880 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - =
31
+ - !ruby/object:Gem::Version
32
+ version: 2.9.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70100277447880
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &70100277447400 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - =
42
+ - !ruby/object:Gem::Version
43
+ version: 0.9.2.2
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70100277447400
47
+ description: Allows you to create, list, and modify local hostnames on POSIX systems
48
+ (e.g. Mac OS X and Linux) and Windows
15
49
  email: me@bjeanes.com
16
50
  executables:
17
51
  - ghost
18
- - ghost-ssh
19
52
  extensions: []
20
- extra_rdoc_files:
21
- - README.md
22
- - LICENSE
23
- - TODO
53
+ extra_rdoc_files: []
24
54
  files:
25
55
  - LICENSE
26
56
  - README.md
27
- - Rakefile
28
- - TODO
29
57
  - bin/ghost
30
- - bin/ghost-ssh
31
- - lib/ghost/linux-host.rb
32
- - lib/ghost/mac-host.rb
33
- - lib/ghost/ssh_config.rb
58
+ - lib/ghost/cli/task/add.rb
59
+ - lib/ghost/cli/task/delete.rb
60
+ - lib/ghost/cli/task/empty.rb
61
+ - lib/ghost/cli/task/export.rb
62
+ - lib/ghost/cli/task/help.rb
63
+ - lib/ghost/cli/task/import.rb
64
+ - lib/ghost/cli/task/list.rb
65
+ - lib/ghost/cli/task.rb
66
+ - lib/ghost/cli.rb
67
+ - lib/ghost/host.rb
68
+ - lib/ghost/store/dscl_store.rb
69
+ - lib/ghost/store/hosts_file_store.rb
70
+ - lib/ghost/store.rb
71
+ - lib/ghost/tokenized_file.rb
72
+ - lib/ghost/version.rb
34
73
  - lib/ghost.rb
35
- - spec/etc_hosts_spec.rb
36
- - spec/ghost_spec.rb
37
- - spec/spec.opts
74
+ - spec/ghost/cli/task/add_spec.rb
75
+ - spec/ghost/cli/task/delete_spec.rb
76
+ - spec/ghost/cli/task/empty_spec.rb
77
+ - spec/ghost/cli/task/export_spec.rb
78
+ - spec/ghost/cli/task/help_spec.rb
79
+ - spec/ghost/cli/task/import_spec.rb
80
+ - spec/ghost/cli/task/list_spec.rb
81
+ - spec/ghost/cli_spec.rb
82
+ - spec/ghost/host_spec.rb
83
+ - spec/ghost/store/dscl_store_spec.rb
84
+ - spec/ghost/store/hosts_file_store_spec.rb
85
+ - spec/ghost/store_spec.rb
86
+ - spec/ghost/tokenized_file_spec.rb
38
87
  - spec/spec_helper.rb
39
- - spec/ssh_config_spec.rb
40
- - spec/ssh_config_template
88
+ - spec/support/cli.rb
89
+ - spec/support/resolv.rb
41
90
  homepage: http://github.com/bjeanes/ghost
42
91
  licenses: []
43
92
  post_install_message:
44
- rdoc_options:
45
- - --line-numbers
93
+ rdoc_options: []
46
94
  require_paths:
47
95
  - lib
48
96
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -54,13 +102,29 @@ required_ruby_version: !ruby/object:Gem::Requirement
54
102
  required_rubygems_version: !ruby/object:Gem::Requirement
55
103
  none: false
56
104
  requirements:
57
- - - ! '>='
105
+ - - ! '>'
58
106
  - !ruby/object:Gem::Version
59
- version: '0'
107
+ version: 1.3.1
60
108
  requirements: []
61
109
  rubyforge_project: ghost
62
110
  rubygems_version: 1.8.10
63
111
  signing_key:
64
112
  specification_version: 3
65
113
  summary: Allows you to create, list, and modify local hostnames
66
- test_files: []
114
+ test_files:
115
+ - spec/ghost/cli/task/add_spec.rb
116
+ - spec/ghost/cli/task/delete_spec.rb
117
+ - spec/ghost/cli/task/empty_spec.rb
118
+ - spec/ghost/cli/task/export_spec.rb
119
+ - spec/ghost/cli/task/help_spec.rb
120
+ - spec/ghost/cli/task/import_spec.rb
121
+ - spec/ghost/cli/task/list_spec.rb
122
+ - spec/ghost/cli_spec.rb
123
+ - spec/ghost/host_spec.rb
124
+ - spec/ghost/store/dscl_store_spec.rb
125
+ - spec/ghost/store/hosts_file_store_spec.rb
126
+ - spec/ghost/store_spec.rb
127
+ - spec/ghost/tokenized_file_spec.rb
128
+ - spec/spec_helper.rb
129
+ - spec/support/cli.rb
130
+ - spec/support/resolv.rb
data/Rakefile DELETED
@@ -1,28 +0,0 @@
1
- require 'rubygems'
2
- require 'rake/gempackagetask'
3
- require 'rubygems/specification'
4
- require 'date'
5
-
6
- Dir['tasks/**/*.rake'].each { |rake| load rake }
7
-
8
-
9
- #### MISC TASKS ####
10
-
11
- desc "list tasks"
12
- task :default do
13
- puts `rake -T`
14
- end
15
-
16
- desc "Outstanding TODO's"
17
- task :todo do
18
- files = ["**/*.{rb,rake}" "bin/*", "README.mkdn"]
19
-
20
- File.open('TODO','w') do |f|
21
- FileList[*files].egrep(/TODO|FIXME/) do |file, line, text|
22
- output = "#{file}:#{line} - #{text.chomp.gsub(/^\s+|\s+$/ , "")}"
23
-
24
- puts output
25
- f.puts output
26
- end
27
- end
28
- end
data/TODO DELETED
File without changes
@@ -1,132 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require File.expand_path(File.dirname(__FILE__) + '/../lib/ghost')
4
-
5
- def help_text(exit_code = 0)
6
- script_name = File.basename $0
7
- puts """USAGE: #{script_name} add <host> <hostname> [--user=<user>] [--port=<port>]
8
- #{script_name} modify <host> <hostname> [--user=<user>] [--port=<port>]
9
- #{script_name} delete <host>
10
- #{script_name} list
11
- #{script_name} empty
12
- #{script_name} export
13
- #{script_name} import <file>
14
- """
15
- exit(exit_code)
16
- end
17
-
18
- def parse(argv)
19
- argv.shift
20
-
21
- new_config = {
22
- :host => argv.shift,
23
- :hostname => argv.shift
24
- }
25
-
26
- if argv.size > 0
27
- argv.each do |arg|
28
- if arg =~ /--([a-z]+)=(.*)/
29
- new_config[$1.to_sym] = $2
30
- end
31
- end
32
- end
33
-
34
- new_config
35
- end
36
-
37
- if ARGV.size.zero? || ['-h', '--help', 'help'].include?(ARGV.first)
38
- help_text
39
- else
40
- case ARGV[0]
41
- when 'add'
42
- if [3,4,5].include?(ARGV.size)
43
- begin
44
- new_config = parse(ARGV)
45
-
46
- config = Ghost::SshConfig.add(new_config)
47
- puts " [Adding] #{config.host} -> #{config.hostname}"
48
- exit 0
49
- rescue Ghost::SshConfigDuplicateError
50
- $stderr.puts $!
51
- exit 3
52
- end
53
- else
54
- $stderr.puts "The add subcommand requires at least a host and a hostname.\n\n"
55
- help_text 2
56
- end
57
- when 'modify'
58
- if [3,4,5].include?(ARGV.size)
59
- new_config = parse(ARGV)
60
- new_config[:force] = true
61
- config = Ghost::SshConfig.add(new_config)
62
- puts " [Modifying] #{config.host} -> #{config.hostname}"
63
- exit 0
64
- else
65
- $stderr.puts "The modify subcommand requires at least a host and a hostname.\n\n"
66
- help_text 4
67
- end
68
- when 'delete', 'del', 'remove', 'rm'
69
- if ARGV.size == 2
70
- Ghost::SshConfig.delete(ARGV[1])
71
- puts " [Deleting] #{ARGV[1]}"
72
- exit 0
73
- else
74
- $stderr.puts "The delete subcommand requires a hostname.\n\n"
75
- help_text 2
76
- end
77
-
78
- when 'list'
79
- configs = Ghost::SshConfig.list
80
- pad = configs.max{|a,b| a.to_s.length <=> b.to_s.length }.to_s.length
81
-
82
- puts "Listing #{configs.size} configs(s):"
83
-
84
- configs.each do |c|
85
- user = c.user ? "#{c.user}@" : ""
86
- puts "#{c.host.rjust(pad+2)} -> #{user}#{c.hostname}:#{c.port||22}"
87
- end
88
- exit 0
89
- when 'empty'
90
- print " [Emptying] "
91
- Ghost::SshConfig.empty!
92
- puts "Done."
93
- exit 0
94
- when 'export'
95
- configs = Ghost::SshConfig.list
96
- configs.each do |c|
97
- puts "#{c.host},#{c.hostname},#{c.user},#{c.port}"
98
- end
99
- exit 0
100
- when 'import'
101
- if ARGV.size == 2
102
- begin
103
- File.foreach(ARGV[1]) do |line|
104
- cfg_infos = line.strip.split(',')
105
- hash = {
106
- :host => cfg_infos[0],
107
- :hostname => cfg_infos[1]
108
- }
109
-
110
- hash[:user] = cfg_infos[2] if cfg_infos.size > 2
111
- hash[:port] = cfg_infos[3] if cfg_infos.size > 3
112
- hash[:force] = true
113
-
114
- config = Ghost::SshConfig.add(hash)
115
-
116
- puts " [Adding] #{config.host} -> #{config.hostname}"
117
- end
118
- exit 0
119
- rescue
120
- $stderr.puts "Cannot import. A problem occured while opening the import file (#{$!.message})."
121
- exit 5
122
- end
123
- else
124
- $stderr.puts "The import command requires an input file.\n\n"
125
- help_text 6
126
- end
127
- else
128
- $stderr.puts "Invalid option: #{ARGV[0]}"
129
- help_text 1
130
- end
131
- end
132
-