fabric 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.
@@ -0,0 +1,212 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe Map do
4
+ before(:each) do
5
+ Fabric.options[:map_root] = File.join(File.dirname(__FILE__), '..')
6
+ @map = Map.create
7
+ end
8
+
9
+ describe "when created" do
10
+ it "should be valid when created" do
11
+ @map.should be_a Map
12
+ end
13
+
14
+ it "should have a blank collection attribute for roles" do
15
+ @map.roles.should == []
16
+ end
17
+
18
+ it "should have a blank collection attribute for users" do
19
+ @map.users.should == []
20
+ end
21
+
22
+ it "should default the key repository to 'keys'" do
23
+ @map.key_repository.should == 'keys'
24
+ end
25
+ end
26
+
27
+ describe "when read" do
28
+ it "should return true" do
29
+ @map.read!.should be_true
30
+ end
31
+ end
32
+
33
+ describe "'draw' called with a block" do
34
+ it "should return the map" do
35
+
36
+ map = Map.draw do |map|
37
+ 1
38
+ end
39
+
40
+ map.should be_a Map
41
+ end
42
+ end
43
+
44
+ describe "when passed a non-existent directory as key repository" do
45
+ it "should raise a LoadError" do
46
+ lambda { @map.key_repository('blah') }.should raise_error LoadError
47
+ end
48
+ end
49
+
50
+ describe "with a mock key repository" do
51
+ it "should update the key repository without raising an error" do
52
+ lambda { @map.key_repository('support/mock_key_repo') }.should_not raise_error LoadError
53
+ end
54
+
55
+ it "should know the full path of the repository" do
56
+ @map.key_repository 'support/mock_key_repo'
57
+ @map.expanded_key_repository_path.should == File.join(File.dirname(__FILE__), '..','support', 'mock_key_repo')
58
+ end
59
+ end
60
+
61
+ describe "when given a role" do
62
+ it "should add that role to the role list" do
63
+ @map.role 'test'
64
+ @map.roles.first(:name => 'test').should be_a Role
65
+ end
66
+
67
+ describe "with host(s)" do
68
+ it "should add a server object when passed one host" do
69
+ @map.role 'test', '127.0.0.1'
70
+ @map.roles.first(:name =>'test').servers.first.should be_a Server
71
+ end
72
+
73
+ it "should add multiple server objects when passed multiple hosts" do
74
+ hosts = []
75
+ (rand(4) + 1).times { hosts << '127.0.0.1' }
76
+
77
+ @map.role 'test', *hosts
78
+
79
+ servers = @map.roles.first(:name => 'test').servers
80
+ servers.count.should == hosts.count
81
+ servers.each do |server|
82
+ server.should be_a Server
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ describe "with user(s)" do
89
+ it "should add user to the user list" do
90
+ @map.user 'test'
91
+ @map.users.first(:name => 'test').should be_a User
92
+ end
93
+
94
+ describe "with a user with an ssh key in the mock key repository" do
95
+ before(:each) do
96
+ @map.key_repository 'support/mock_key_repo'
97
+ @key_file = File.join(@map.expanded_key_repository_path, 'fabric_test_user.pub')
98
+
99
+ File.open(@key_file, 'w+') do |f|
100
+ f.write('test key')
101
+ end
102
+ end
103
+
104
+ after(:each) do
105
+ File.delete(@key_file)
106
+ end
107
+
108
+ it "should add the user's ssh key from the key repository" do
109
+ @map.user 'fabric_test_user'
110
+ @map.users.first(:name => 'fabric_test_user').keys.first.public_key.should == 'test key'
111
+ end
112
+ end
113
+
114
+ it "should add multiple users to the user list" do
115
+ users = []
116
+ (rand(4) + 1).times { |i| users << "user_#{i}" }
117
+
118
+ @map.user *users
119
+
120
+ @map.users.count.should == users.count
121
+ @map.users.all.each do |user|
122
+ user.should be_a User
123
+ end
124
+ end
125
+ end
126
+
127
+ describe "when given a grant" do
128
+ before(:each) do
129
+ @map.role 'test', '127.0.0.1'
130
+ @map.user 'test_user'
131
+ end
132
+
133
+ it "should add the map's users to the role" do
134
+ @map.roles.first(:name => 'test').users.count.should == 0
135
+ @map.grant 'test_user', 'test'
136
+ @map.roles.first(:name => 'test').users.count.should == 1
137
+ end
138
+
139
+ describe "for multiple users" do
140
+ before(:each) do
141
+ @map.user 'another test'
142
+ end
143
+
144
+ it "should add multiple users to the role" do
145
+ @map.grant ['test_user', 'another test'], 'test'
146
+ @map.roles.first(:name => 'test').users.count.should == 2
147
+ end
148
+
149
+ it "should add all the users to the role when passed :all" do
150
+ @map.grant :all, 'test'
151
+ @map.roles.first(:name => 'test').users.count.should == 2
152
+ end
153
+ end
154
+
155
+ describe "for all roles" do
156
+ before(:each) do
157
+ @map.role 'test again', '127.0.0.1'
158
+ end
159
+
160
+ it "should add the user to multiple roles" do
161
+ @map.grant 'test_user', ['test', 'test again']
162
+ @map.roles.each do |role|
163
+ role.users.count.should == 1
164
+ end
165
+ end
166
+
167
+ it "should add the user to all the roles when passed :all" do
168
+ @map.grant 'test_user', :all
169
+ @map.roles.each do |role|
170
+ role.users.count.should == 1
171
+ end
172
+ end
173
+ end
174
+
175
+ it "should raise a Object Not Found if an invalid user identifier is passed" do
176
+ lambda { @map.grant 'fake_user', 'test' }.should raise_error(DataMapper::ObjectNotFoundError)
177
+ end
178
+
179
+ it "should raise a Object Not Found if an invalid role identifier is passed" do
180
+ lambda { @map.grant 'user', 'fake_test' }.should raise_error(DataMapper::ObjectNotFoundError)
181
+ end
182
+ end
183
+
184
+ describe "with a namespace" do
185
+ it "should be an instance of Map when created" do
186
+ namespace = @map.namespace
187
+ namespace.should be_a Map
188
+ end
189
+
190
+ it "should know its parent when created" do
191
+ namespace = @map.namespace
192
+ namespace.parent.should == @map
193
+ end
194
+
195
+ describe "with users" do
196
+ before(:each) do
197
+ @map.users.create(:name => 'test')
198
+ @namespace = @map.namespace
199
+ end
200
+
201
+ it "should inherit its parents users" do
202
+ @namespace.users.should == @map.users
203
+ end
204
+
205
+ it "should add users without adding them to the parent" do
206
+ @namespace.users.create(:name => 'test two')
207
+ @namespace.users.length.should == 2
208
+ @map.users.length.should == 1
209
+ end
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe Role do
4
+ end
@@ -0,0 +1,104 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe Server do
4
+ before(:each) do
5
+ @server = Server.create(:host => TEST_SERVER)
6
+ end
7
+
8
+ it "should be valid when created" do
9
+ @server.should be_a Server
10
+ end
11
+
12
+ describe "'create_group' method" do
13
+ before(:each) do
14
+ @group = Group.new(:name => TEST_GROUP)
15
+ end
16
+
17
+ after(:each) do
18
+ @server.execute_command("sudo /usr/sbin/groupdel #{TEST_GROUP}")
19
+ end
20
+
21
+ it "should create a group" do
22
+ @server.create_group(@group)
23
+
24
+ @server.execute_command("cat /etc/group | grep #{TEST_GROUP}") # Not the strongest test - grep not ideal for this
25
+ @server.output.should_not == ''
26
+ end
27
+ end
28
+
29
+ describe "running plesk" do
30
+ before(:each) do
31
+ # mock a plesk server
32
+ @server.execute_command("sudo mkdir /usr/local/psa")
33
+ end
34
+
35
+ after(:each) do
36
+ # how can we tear this down safely?
37
+ @server.execute_command("sudo rm -rf /usr/local/psa")
38
+ end
39
+
40
+ it "should know it is a plesk server" do
41
+ @server.is_running_plesk?.should be_true
42
+ end
43
+ end
44
+
45
+ describe "not running plesk" do
46
+ it "should know it is not a plesk server" do
47
+ @server.is_running_plesk?.should be_false
48
+ end
49
+ end
50
+
51
+ describe "with accounts" do
52
+ before(:each) do
53
+ @role = Role.create(:name => 'test')
54
+ @role.servers << @server
55
+ @role.users.create(:name => TEST_USER)
56
+ end
57
+
58
+ it "should have an account object for each of its role's users" do
59
+ @server.accounts.first.user.should == @role.users.first
60
+ end
61
+
62
+ it "should check if an account exists" do
63
+ # Runner has to exist for the login to have worked
64
+ runner = User.new(:name => TEST_RUNNER)
65
+
66
+ @server.account_exists_for?(runner).should be_true
67
+ @server.account_exists_for?(@role.users.first).should be_false
68
+ end
69
+
70
+ it "should identify account that require adding" do
71
+ @server.accounts_to_add.should == Array(@role.users.first)
72
+ end
73
+
74
+ end
75
+
76
+ describe "with an account that should be deleted" do
77
+ before(:each) do
78
+ @role = Role.create(:name => 'test')
79
+ @role.servers << @server
80
+
81
+ # We'll add the test user too; just to check it doesn't get deleted
82
+ @role.users.create(:name => TEST_USER)
83
+ @server.accounts.first.add_user
84
+
85
+ @doomed_user = User.create(:name => TEST_DOOMED_USER)
86
+ @server.execute_command("sudo /usr/sbin/useradd -m #{@doomed_user.name}")
87
+ end
88
+
89
+ after(:each) do
90
+ @server.execute_command("sudo /usr/sbin/userdel --remove #{TEST_USER}")
91
+ @server.execute_command("sudo /usr/sbin/userdel --remove #{TEST_DOOMED_USER}")
92
+ end
93
+
94
+ it "should identify accounts that require removing" do
95
+ @server.accounts_to_remove.should == Array(@doomed_user)
96
+ end
97
+
98
+ it "should delete the account" do
99
+ @server.account_exists_for?(@doomed_user).should be_true
100
+ @server.delete_account_for(@doomed_user)
101
+ @server.account_exists_for?(@doomed_user).should be_false
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe User do
4
+ before :each do
5
+ @user = User.new(:name => 'bob')
6
+ end
7
+
8
+ it "should merge multiple keys into the authorized_keys file" do
9
+ user = User.create
10
+ key1 = 'this is'
11
+ key2 = ' a key.'
12
+
13
+ user.keys.create(:public_key => key1)
14
+ user.keys.create(:public_key => key2)
15
+
16
+ user.authorized_keys_file.should == key1 + key2
17
+ end
18
+
19
+ it "should raise an error if the authorized_keys_file is blank" do
20
+ lambda { @user.authorized_keys_file }.should raise_error
21
+ end
22
+
23
+ it "can generate the user's home directory path" do
24
+ @user.home_directory_path.should == '/home/bob/'
25
+ end
26
+
27
+ it "can generate the path to the user's .ssh directory" do
28
+ @user.ssh_config_directory_path.should == '/home/bob/.ssh/'
29
+ end
30
+
31
+ it "can generate the path to the user's authorized_keys file" do
32
+ @user.authorized_keys_file_path.should == '/home/bob/.ssh/authorized_keys'
33
+ end
34
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,5 @@
1
+ --colour
2
+ --format specdoc
3
+ --loadby mtime
4
+ --reverse
5
+ --debugger
@@ -0,0 +1,27 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'vendor','gems','environment')
2
+
3
+ $:.unshift File.dirname(__FILE__) + '/../lib'
4
+
5
+ require 'fabric'
6
+ require 'fabric-test'
7
+ require 'database_cleaner'
8
+
9
+ TEST_SERVER = Fabric::Test.settings['server']
10
+ TEST_RUNNER = Fabric::Test.settings['runner']
11
+ TEST_USER = Fabric::Test.settings['user']
12
+ TEST_DOOMED_USER = Fabric::Test.settings['doomed_user']
13
+ TEST_GROUP = Fabric::Test.settings['group']
14
+
15
+ Spec::Runner.configure do |config|
16
+ config.before(:suite) do
17
+ DatabaseCleaner.strategy = :transaction
18
+ end
19
+
20
+ config.before(:each) do
21
+ DatabaseCleaner.start
22
+ end
23
+
24
+ config.after(:each) do
25
+ DatabaseCleaner.clean
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ namespace :test do
2
+ begin
3
+ require 'cucumber/rake/task'
4
+ Cucumber::Rake::Task.new(:features)
5
+
6
+ task :features => :check_dependencies
7
+ rescue LoadError
8
+ task :features do
9
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
10
+ end
11
+ end
12
+ end
13
+
14
+ desc 'synonym for test:features'
15
+ task 'features' => 'test:features'
@@ -0,0 +1,14 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "fabric"
5
+ gem.summary = %Q{Fabric is a small ruby app to perform tasks on servers via SSH.}
6
+ gem.description = %Q{Fabric is a small ruby app to perform tasks on servers via SSH. Built around net/ssh and taking heavy inspiration from Capistrano, it allows you to create policies for server management and perform sysadmin tasks without the need for a process/daemon/dependency or even ruby being installed on the remote server.}
7
+ gem.email = "sam.phillips@setfiremedia.com"
8
+ gem.homepage = "http://github.com/setfire/fabric"
9
+ gem.authors = ["Sam Phillips"]
10
+ gem.add_development_dependency "cucumber", ">= 0.3.104"
11
+ end
12
+ rescue LoadError
13
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
14
+ end
data/tasks/rdoc.rake ADDED
@@ -0,0 +1,9 @@
1
+ require 'rake/rdoctask'
2
+ Rake::RDocTask.new do |rdoc|
3
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
4
+
5
+ rdoc.rdoc_dir = 'rdoc'
6
+ rdoc.title = "fabric #{version}"
7
+ rdoc.rdoc_files.include('README*')
8
+ rdoc.rdoc_files.include('lib/**/*.rb')
9
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,15 @@
1
+ require 'spec'
2
+ require 'spec/rake/spectask'
3
+
4
+ namespace 'test' do
5
+ Spec::Rake::SpecTask.new('spec') do |t|
6
+ t.spec_files = FileList['spec/**/*_spec.rb']
7
+ t.spec_opts = ['--options', "\"spec/spec.opts\""]
8
+ t.ruby_opts = ['-Ilib']
9
+ t.rcov = false
10
+ end
11
+ end
12
+
13
+ desc 'synonym for test:spec'
14
+ task 'spec' => 'test:spec'
15
+