zool 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/LICENSE +20 -0
- data/README.md +96 -0
- data/Rakefile +57 -0
- data/Readme.md +96 -0
- data/bin/zool +156 -0
- data/features/config_parser.feature +67 -0
- data/features/fetching_ssh_keys.feature +72 -0
- data/features/step_definitions/ssh_keys_steps.rb +136 -0
- data/features/store_ssh_keys.feature +62 -0
- data/features/support/env.rb +39 -0
- data/lib/py_config_parser/py_config_parser.tt +85 -0
- data/lib/zool.rb +24 -0
- data/lib/zool/configuration.rb +151 -0
- data/lib/zool/key_file_writer.rb +48 -0
- data/lib/zool/server.rb +116 -0
- data/lib/zool/server_pool.rb +74 -0
- data/spec/py_config_parser_spec.rb +55 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/zool.rb +4 -0
- data/spec/zool/configuration_spec.rb +170 -0
- data/spec/zool/key_file_writer_spec.rb +82 -0
- data/spec/zool/server_pool_spec.rb +133 -0
- data/spec/zool/server_spec.rb +178 -0
- metadata +266 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
module Zool
|
4
|
+
describe KeyfileWriter do
|
5
|
+
context "dumping keys to files" do
|
6
|
+
before :each do
|
7
|
+
@writer = KeyfileWriter.new
|
8
|
+
end
|
9
|
+
|
10
|
+
context "#write" do
|
11
|
+
context "with no filename provided" do
|
12
|
+
before :each do
|
13
|
+
sorted_keys = [
|
14
|
+
key_fixtures[:pascal],
|
15
|
+
key_fixtures[:pascal_private],
|
16
|
+
key_fixtures[:pascal_laptop],
|
17
|
+
key_fixtures[:bob],
|
18
|
+
key_fixtures[:upcase],
|
19
|
+
]
|
20
|
+
sorted_keys.each do |key|
|
21
|
+
@writer.write key
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should replace special characters with underscores in filename" do
|
26
|
+
it_should_generate_keyfile 'bob_schneider.pub'
|
27
|
+
it_should_generate_keyfile 'pascal_friederich.pub'
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should not fail if keyfile name is not parsable" do
|
31
|
+
key_without_host = "ssh-dsa asdfkasdlfjasdlfkjsdf="
|
32
|
+
@writer.write key_without_host
|
33
|
+
it_should_generate_keyfile '1__not_parsable.pub'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should not fail if the name in the keyfile is unusual" do
|
37
|
+
key_with_only_username = "ssh-dsa asdfasdfasdfkjkj= Peter"
|
38
|
+
@writer.write key_with_only_username
|
39
|
+
it_should_generate_keyfile "peter.pub"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should write the ssh key in the appropriate keyfile" do
|
43
|
+
File.read('keys/bob_schneider.pub').chomp.should == key_fixtures[:bob]
|
44
|
+
File.read('keys/pascal_friederich.pub').chomp.should == key_fixtures[:pascal]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should turn the filenames to underscores" do
|
48
|
+
it_should_generate_keyfile 'upcase_van.pub'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should number dublicate keynames" do
|
52
|
+
it_should_generate_keyfile 'pascal_friederich_2.pub'
|
53
|
+
it_should_generate_keyfile 'pascal_friederich_3.pub'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with a filename provided" do
|
58
|
+
it "should write the ssh key to the file named as given (with .pub added to the name)" do
|
59
|
+
@writer.write('a key', 'customname')
|
60
|
+
it_should_generate_keyfile('customname.pub')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "#write_keys" do
|
66
|
+
it "should write every key" do
|
67
|
+
@writer.should_receive(:write).exactly(3).times
|
68
|
+
keys = [
|
69
|
+
key_fixtures[:pascal],
|
70
|
+
key_fixtures[:pascal_private],
|
71
|
+
key_fixtures[:pascal_laptop]
|
72
|
+
]
|
73
|
+
@writer.write_keys(keys)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def it_should_generate_keyfile(keyfile)
|
81
|
+
Dir['keys/*.pub'].map {|path| path.split('/').last }.should include keyfile
|
82
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
module Zool
|
4
|
+
describe ServerPool do
|
5
|
+
context "parsing from a hosts file" do
|
6
|
+
context "with a user argument and/or password" do
|
7
|
+
before :each do
|
8
|
+
hostsfile = <<-HOSTS
|
9
|
+
12.21.4.1 servername
|
10
|
+
HOSTS
|
11
|
+
@server = ServerPool.from_hostfile(hostsfile, :user => 'peter', :password => 'peters1234').servers.first
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should pass the user argument to the servers" do
|
15
|
+
@server.user.should == 'peter'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should pass the password argument to the servers" do
|
19
|
+
@server.send(:instance_variable_get, :@options)[:password].should == 'peters1234'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when given a String" do
|
24
|
+
it "should return a Serverpool object with the servers from the hosts file" do
|
25
|
+
hostsfile = StringIO.new <<-HOSTS
|
26
|
+
12.21.4.1 servername
|
27
|
+
12.21.4.2 servername2
|
28
|
+
12.21.4.3 servername3
|
29
|
+
12.21.4.4 servername4
|
30
|
+
HOSTS
|
31
|
+
pool = ServerPool.from_hostfile(hostsfile)
|
32
|
+
pool.servers.map {|server| server.hostname }.should == ['12.21.4.1', '12.21.4.2', '12.21.4.3', '12.21.4.4']
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should remove duplicates from the list of servers" do
|
36
|
+
hostsfile = StringIO.new <<-HOSTS
|
37
|
+
12.21.4.1 servername1
|
38
|
+
12.21.4.2 servername2
|
39
|
+
12.21.4.2 fancy_alias
|
40
|
+
HOSTS
|
41
|
+
pool = ServerPool.from_hostfile(hostsfile)
|
42
|
+
pool.servers.map {|server| server.hostname }.should == ['12.21.4.1', '12.21.4.2']
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should remove localhost and networks from the list of servers" do
|
46
|
+
hostfile = StringIO.new <<-HOSTS
|
47
|
+
12.34.45.56 validserver
|
48
|
+
localhost localhost
|
49
|
+
127.0.0.1 localhost
|
50
|
+
255.255.255.255 network
|
51
|
+
::1 localhost
|
52
|
+
HOSTS
|
53
|
+
pool = ServerPool.from_hostfile(hostfile)
|
54
|
+
pool.servers.map {|server| server.hostname }.should == ['12.34.45.56']
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should ignore malformed lines" do
|
58
|
+
hostsfile = StringIO.new <<-HOSTS
|
59
|
+
# asdfasdfasdf comment
|
60
|
+
19023912u0194h odd_line
|
61
|
+
12.21.4.1 servername1
|
62
|
+
|
63
|
+
10.257.2.1 invalid_ip
|
64
|
+
12.21.4.2 servername2
|
65
|
+
myhost.de
|
66
|
+
HOSTS
|
67
|
+
pool = ServerPool.from_hostfile(hostsfile)
|
68
|
+
pool.servers.map {|server| server.hostname }.should == ['12.21.4.1', '12.21.4.2', 'myhost.de']
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
before :each do
|
73
|
+
@pool = ServerPool.new
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should only take Server objects" do
|
77
|
+
lambda { @pool << Object.new }.should raise_error TypeError
|
78
|
+
lambda { @pool.add Object.new }.should raise_error TypeError
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should delegate methods to the server objects" do
|
82
|
+
server = mock('server')
|
83
|
+
server.should_receive(:keys)
|
84
|
+
server.should_receive(:fetch_keys)
|
85
|
+
server.should_receive(:upload_keys)
|
86
|
+
@pool.push server
|
87
|
+
|
88
|
+
@pool.keys
|
89
|
+
@pool.fetch_keys
|
90
|
+
@pool.upload_keys
|
91
|
+
end
|
92
|
+
|
93
|
+
context "delegating methods to the servers" do
|
94
|
+
it "should aggregated values as an hash" do
|
95
|
+
server1 = stub
|
96
|
+
server1_keys = ['first key', 'second key']
|
97
|
+
server1.stub!(:keys).and_return(server1_keys)
|
98
|
+
|
99
|
+
server2 = stub
|
100
|
+
server2_keys = ['third key', 'forth key']
|
101
|
+
server2.stub!(:keys).and_return(server2_keys)
|
102
|
+
|
103
|
+
@pool.push server1
|
104
|
+
@pool.push server2
|
105
|
+
|
106
|
+
@pool.keys.should == server1_keys + server2_keys
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "dumping the servers keys to files" do
|
111
|
+
it "should write a keyfile for every key" do
|
112
|
+
FileUtils.rm_r 'keys' # cleanup old keyfiles
|
113
|
+
@pool.stub!(:keys).and_return(key_fixtures.values.join("\n"))
|
114
|
+
@pool.dump_keyfiles
|
115
|
+
Dir['keys/*'].should have(key_fixtures.size).keys
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "adding a key to the serverpool" do
|
120
|
+
it "should add the key to every server in the pool" do
|
121
|
+
new_key = 'a key'
|
122
|
+
keys = mock('keys')
|
123
|
+
server1 = mock('server1', :keys => keys)
|
124
|
+
server2 = mock('server2', :keys => keys)
|
125
|
+
@pool.push server1
|
126
|
+
@pool.push server2
|
127
|
+
|
128
|
+
keys.should_receive(:<<).twice.with(new_key)
|
129
|
+
@pool.keys << new_key
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
require 'ruby-debug'
|
3
|
+
Debugger.start
|
4
|
+
|
5
|
+
module Zool
|
6
|
+
describe Server do
|
7
|
+
before :each do
|
8
|
+
@server = Server.new("somehost")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have a getter for the user attribute" do
|
12
|
+
@server.user.should == @server.send(:instance_variable_get, :@options)[:user]
|
13
|
+
end
|
14
|
+
|
15
|
+
context "fetching a servers keys" do
|
16
|
+
it "should use a password if provided" do
|
17
|
+
server = Server.new('somehost', :user => 'root', :password => 'a password')
|
18
|
+
Net::SCP.should_receive(:download!).with(anything, anything, anything, anything, :ssh => {:password => 'a password'})
|
19
|
+
server.keys
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should use the default server location" do
|
23
|
+
Server.new('somehost').keyfile_location.should == '~/.ssh/authorized_keys'
|
24
|
+
Server.new('somehost', :user => 'peter').keyfile_location.should == '~/.ssh/authorized_keys'
|
25
|
+
end
|
26
|
+
|
27
|
+
context "with a custom keyfile location set" do
|
28
|
+
it "should use the custom keyfile location" do
|
29
|
+
@server = Server.new('somehost')
|
30
|
+
custom_keyfile_location = '/some/custom/path'
|
31
|
+
@server.keyfile_location = custom_keyfile_location
|
32
|
+
Net::SCP.should_receive(:download!).with(anything, anything, custom_keyfile_location, anything, anything)
|
33
|
+
|
34
|
+
@server.fetch_keys
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when the keyfile is not presetn" do
|
39
|
+
it "should return an empty list of keys" do
|
40
|
+
Net::SCP.should_receive(:download!).and_raise(Net::SCP::Error)
|
41
|
+
@server.keys.should be_empty
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should load the authorized_keys file from the server" do
|
46
|
+
@server = Server.new('somehost')
|
47
|
+
Net::SCP.should_receive(:download!).with(anything, anything, @server.keyfile_location, anything, anything)
|
48
|
+
|
49
|
+
@server.fetch_keys
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should make the keys available through a keys array" do
|
53
|
+
@server.stub!(:load_remote_file).and_return("#{key_fixtures[:pascal]}\n#{key_fixtures[:bob]}")
|
54
|
+
@server.keys.should == [key_fixtures[:pascal], key_fixtures[:bob]]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should remove unneccasarry whitespace from the output" do
|
58
|
+
@server = Server.new('somehost')
|
59
|
+
@server.stub!(:load_remote_file).and_return(" #{key_fixtures[:pascal]} ")
|
60
|
+
@server.keys.should == [key_fixtures[:pascal]]
|
61
|
+
@server.keys.should have(1).key
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should remove blank lines" do
|
65
|
+
@server = Server.new('somehost')
|
66
|
+
@server.stub!(:load_remote_file).and_return(" #{key_fixtures[:pascal]} \n ")
|
67
|
+
@server.keys.should == [key_fixtures[:pascal]]
|
68
|
+
@server.keys.should have(1).key
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should remove duplicate keys from the list" do
|
72
|
+
@server = Server.new('somehost')
|
73
|
+
@server.stub!(:load_remote_file).and_return("#{key_fixtures[:pascal]}\n#{key_fixtures[:pascal]}")
|
74
|
+
@server.keys.should have(1).key
|
75
|
+
@server.keys.should == [key_fixtures[:pascal]]
|
76
|
+
end
|
77
|
+
|
78
|
+
context "requesting the keys several times" do
|
79
|
+
it "should not fetch the keys again" do
|
80
|
+
@server = Server.new('somehost')
|
81
|
+
@server.should_receive(:load_remote_file).once.and_return("n#{key_fixtures[:pascal]}")
|
82
|
+
@server.keys
|
83
|
+
@server.keys
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "fetching the keys again after they have already been fetched" do
|
88
|
+
it "should return the new list of keys" do
|
89
|
+
@server = Server.new('somehost')
|
90
|
+
@server.should_receive(:load_remote_file).ordered.and_return("#{key_fixtures[:pascal]}")
|
91
|
+
@server.should_receive(:load_remote_file).ordered.and_return("#{key_fixtures[:bob]}")
|
92
|
+
@server.keys
|
93
|
+
@server.keys.should == [key_fixtures[:pascal]]
|
94
|
+
@server.fetch_keys
|
95
|
+
@server.keys.should == [key_fixtures[:bob]]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "dumping the keys to files" do
|
101
|
+
it "should write a keyfile for every key" do
|
102
|
+
FileUtils.rm_r 'keys' # cleanup old keyfiles
|
103
|
+
@server.stub!(:load_remote_file).and_return(key_fixtures.values.join("\n"))
|
104
|
+
@server.dump_keyfiles
|
105
|
+
Dir['keys/*'].should have(key_fixtures.size).keys
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "setting a servers keys" do
|
110
|
+
before :each do
|
111
|
+
@server = Server.new('somehost')
|
112
|
+
@server.stub!(:load_remote_file).and_return("")
|
113
|
+
end
|
114
|
+
|
115
|
+
context "by replacing all of them" do
|
116
|
+
it "should take a array of keys" do
|
117
|
+
@server.keys = [key_fixtures[:pascal], key_fixtures[:bob]]
|
118
|
+
@server.keys.should == [key_fixtures[:pascal], key_fixtures[:bob]]
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should not fetch the servers existing keys" do
|
122
|
+
@server.should_not_receive(:load_remote_file)
|
123
|
+
@server.keys = [key_fixtures[:pascal]]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "by adding keys to the existing keys" do
|
128
|
+
it "should fetch the servers current keys if not done before" do
|
129
|
+
@server.should_receive(:load_remote_file)
|
130
|
+
@server.keys << "asdf"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "and uploading them" do
|
135
|
+
before :each do
|
136
|
+
@server.keys = [key_fixtures[:pascal], key_fixtures[:bob]]
|
137
|
+
@backup_keys = 'original keys'
|
138
|
+
@server.stub!(:load_remote_file).and_return(@backup_keys)
|
139
|
+
|
140
|
+
Net::SCP.stub(:download!)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should write a authorized_keys file with all the keys" do
|
144
|
+
channel_stub = stub('ssh channel stub', :null_object => true)
|
145
|
+
Net::SSH.stub!(:start).and_return(channel_stub)
|
146
|
+
Net::SCP.stub!(:upload!) # the backup
|
147
|
+
channel_stub.stub(:scp).and_return(channel_stub)
|
148
|
+
|
149
|
+
channel_stub.should_receive(:upload!).with(stringbuffer_with(@server.keys.join("\n")), @server.keyfile_location).ordered
|
150
|
+
@server.upload_keys
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should backup the existing authorized_keys file" do
|
154
|
+
@server.should_receive(:load_remote_file).and_return(@backup_keys)
|
155
|
+
Net::SSH.stub!(:start).and_return(stub('ssh channel stub', :null_object => true))
|
156
|
+
|
157
|
+
Net::SCP.should_receive(:upload!).with('somehost', 'root', stringbuffer_with(@backup_keys), /authorized_keys_\d+$/, anything)
|
158
|
+
@server.upload_keys
|
159
|
+
end
|
160
|
+
|
161
|
+
context "with an exception during backup of the original keys" do
|
162
|
+
before :each do
|
163
|
+
Net::SCP.stub!(:download!).and_raise(Exception)
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should not upload the new keys" do
|
167
|
+
Net::SCP.should_not_receive(:upload!)
|
168
|
+
lambda { @server.upload_keys }.should raise_error
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context "providing a fallback if something goes wrong" do
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
metadata
ADDED
@@ -0,0 +1,266 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pascal Friederich
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-06 00:00:00 +01:00
|
13
|
+
default_executable: zool
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: net-scp
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.0.2
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: net-ssh
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.17
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: net-scp
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.0.2
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: net-ssh
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.0.17
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: treetop
|
57
|
+
type: :runtime
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.4.3
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: polyglot
|
67
|
+
type: :runtime
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 0.2.9
|
74
|
+
version:
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: highline
|
77
|
+
type: :runtime
|
78
|
+
version_requirement:
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 1.5.1
|
84
|
+
version:
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: builder
|
87
|
+
type: :development
|
88
|
+
version_requirement:
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 2.1.2
|
94
|
+
version:
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: columnize
|
97
|
+
type: :development
|
98
|
+
version_requirement:
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.3.1
|
104
|
+
version:
|
105
|
+
- !ruby/object:Gem::Dependency
|
106
|
+
name: cucumber
|
107
|
+
type: :development
|
108
|
+
version_requirement:
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: 0.5.3
|
114
|
+
version:
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: diff-lcs
|
117
|
+
type: :development
|
118
|
+
version_requirement:
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 1.1.2
|
124
|
+
version:
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: fakefs
|
127
|
+
type: :development
|
128
|
+
version_requirement:
|
129
|
+
version_requirements: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 0.2.1
|
134
|
+
version:
|
135
|
+
- !ruby/object:Gem::Dependency
|
136
|
+
name: json_pure
|
137
|
+
type: :development
|
138
|
+
version_requirement:
|
139
|
+
version_requirements: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: 1.2.0
|
144
|
+
version:
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: linecache
|
147
|
+
type: :development
|
148
|
+
version_requirement:
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: "0.43"
|
154
|
+
version:
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: rake
|
157
|
+
type: :development
|
158
|
+
version_requirement:
|
159
|
+
version_requirements: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: 0.8.7
|
164
|
+
version:
|
165
|
+
- !ruby/object:Gem::Dependency
|
166
|
+
name: rspec
|
167
|
+
type: :development
|
168
|
+
version_requirement:
|
169
|
+
version_requirements: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 1.2.9
|
174
|
+
version:
|
175
|
+
- !ruby/object:Gem::Dependency
|
176
|
+
name: ruby-debug
|
177
|
+
type: :development
|
178
|
+
version_requirement:
|
179
|
+
version_requirements: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - ">="
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: 0.10.3
|
184
|
+
version:
|
185
|
+
- !ruby/object:Gem::Dependency
|
186
|
+
name: ruby-debug-base
|
187
|
+
type: :development
|
188
|
+
version_requirement:
|
189
|
+
version_requirements: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - ">="
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: 0.10.3
|
194
|
+
version:
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: term-ansicolor
|
197
|
+
type: :development
|
198
|
+
version_requirement:
|
199
|
+
version_requirements: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - ">="
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: 1.0.4
|
204
|
+
version:
|
205
|
+
description: Zool allows you to manage authorized_keys files on servers. It comes with a command-line client 'zool'. The configuration can be done in a pyconfig/gitosis like configuration file. See README.md for further details
|
206
|
+
email: paukul@gmail.com
|
207
|
+
executables:
|
208
|
+
- zool
|
209
|
+
extensions: []
|
210
|
+
|
211
|
+
extra_rdoc_files:
|
212
|
+
- LICENSE
|
213
|
+
- README.md
|
214
|
+
files:
|
215
|
+
- LICENSE
|
216
|
+
- Rakefile
|
217
|
+
- Readme.md
|
218
|
+
- bin/zool
|
219
|
+
- lib/py_config_parser/py_config_parser.tt
|
220
|
+
- lib/zool.rb
|
221
|
+
- lib/zool/configuration.rb
|
222
|
+
- lib/zool/key_file_writer.rb
|
223
|
+
- lib/zool/server.rb
|
224
|
+
- lib/zool/server_pool.rb
|
225
|
+
- README.md
|
226
|
+
has_rdoc: true
|
227
|
+
homepage: http://github.com/paukul/zool
|
228
|
+
licenses: []
|
229
|
+
|
230
|
+
post_install_message:
|
231
|
+
rdoc_options:
|
232
|
+
- --charset=UTF-8
|
233
|
+
require_paths:
|
234
|
+
- lib
|
235
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
236
|
+
requirements:
|
237
|
+
- - ">="
|
238
|
+
- !ruby/object:Gem::Version
|
239
|
+
version: "0"
|
240
|
+
version:
|
241
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
242
|
+
requirements:
|
243
|
+
- - ">="
|
244
|
+
- !ruby/object:Gem::Version
|
245
|
+
version: "0"
|
246
|
+
version:
|
247
|
+
requirements: []
|
248
|
+
|
249
|
+
rubyforge_project:
|
250
|
+
rubygems_version: 1.3.5
|
251
|
+
signing_key:
|
252
|
+
specification_version: 3
|
253
|
+
summary: Library and command-line client to manage authorized_keys files
|
254
|
+
test_files:
|
255
|
+
- spec/py_config_parser_spec.rb
|
256
|
+
- spec/spec_helper.rb
|
257
|
+
- spec/zool/configuration_spec.rb
|
258
|
+
- spec/zool/key_file_writer_spec.rb
|
259
|
+
- spec/zool/server_pool_spec.rb
|
260
|
+
- spec/zool/server_spec.rb
|
261
|
+
- spec/zool.rb
|
262
|
+
- features/config_parser.feature
|
263
|
+
- features/fetching_ssh_keys.feature
|
264
|
+
- features/step_definitions/ssh_keys_steps.rb
|
265
|
+
- features/store_ssh_keys.feature
|
266
|
+
- features/support/env.rb
|