macadmin 0.0.4

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,274 @@
1
+ require 'spec_helper'
2
+
3
+ describe MacAdmin::ComputerGroup do
4
+
5
+ before :all do
6
+ # Create a dslocal sandbox
7
+ @test_dir = "/private/tmp/macadmin_computergroup_test.#{rand(100000)}"
8
+ MacAdmin::DSLocalRecord.send(:remove_const, :DSLOCAL_ROOT)
9
+ MacAdmin::DSLocalRecord::DSLOCAL_ROOT = File.expand_path @test_dir
10
+ FileUtils.mkdir_p "#{@test_dir}/Default/computergroups"
11
+ FileUtils.mkdir_p "#{@test_dir}/Default/computers"
12
+
13
+ # Create two group record plists that we can load
14
+ fratbots = {
15
+ "gid" => ["1010"],
16
+ "realname" => ["Fratbots"],
17
+ "name" => ["fratbots"],
18
+ "generateduid" => ["00000000-0000-0000-0000-000000000001"],
19
+ }
20
+
21
+ robot_mafia = {
22
+ "gid" => ["502"],
23
+ "realname" => ["Robot Mafia"],
24
+ "name" => ["robot_mafia"],
25
+ "generateduid" => ["00000000-0000-0000-0000-000000000002"],
26
+ }
27
+
28
+ [fratbots, robot_mafia].each do |computergroup|
29
+ record = CFPropertyList::List.new
30
+ record.value = CFPropertyList.guess(computergroup)
31
+ record.save("#{@test_dir}/Default/computergroups/#{computergroup['name'].first}.plist", CFPropertyList::List::FORMAT_BINARY)
32
+ end
33
+ end
34
+
35
+ describe '#new' do
36
+
37
+ context 'throws an ArgumentError when given fewer than 1 params' do
38
+ subject { ComputerGroup.new }
39
+ it { expect { subject }.to raise_error(ArgumentError) }
40
+ end
41
+
42
+ context 'when created from a parameter Hash' do
43
+ subject { ComputerGroup.new :name => 'league-of-robots', :gid => "666" }
44
+ it { should be_an_instance_of ComputerGroup }
45
+ it 'should have a valid generateduid attribute' do
46
+ (UUID.valid?(subject.generateduid.first)).should be_true
47
+ end
48
+ its (:gid) { should eq ['666'] }
49
+ its (:name) { should eq ['league-of-robots'] }
50
+ its (:realname) { should eq ['league-of-robots'.capitalize] }
51
+ its (:users) { should eq [] }
52
+ its (:groupmembers) { should eq [] }
53
+ end
54
+
55
+ context 'when created from a just a name (String)' do
56
+ subject { ComputerGroup.new 'league-of-robots' }
57
+ it { should be_an_instance_of ComputerGroup }
58
+ it 'should have a valid generateduid attribute' do
59
+ (UUID.valid?(subject.generateduid.first)).should be_true
60
+ end
61
+ its (:gid) { should eq ['503'] } # 503 should be the next available GID
62
+ its (:name) { should eq ['league-of-robots'] }
63
+ its (:realname) { should eq ['league-of-robots'.capitalize] }
64
+ its (:users) { should eq [] }
65
+ its (:groupmembers) { should eq [] }
66
+ end
67
+
68
+ end
69
+
70
+ describe '#exists?' do
71
+
72
+ context "when the object is different from its associated file" do
73
+ subject { ComputerGroup.new :name => 'fratbots', :gid => "1111" }
74
+ it 'should return false' do
75
+ subject.exists?.should be_false
76
+ end
77
+ end
78
+
79
+ context "when ALL the object's attributes match its associated file" do
80
+ subject { ComputerGroup.new :name => 'fratbots', :gid => "1010" }
81
+ it 'should return true' do
82
+ subject.exists?.should be_true
83
+ end
84
+ end
85
+
86
+ context "when the object does not have an associated file on disk" do
87
+ subject { ComputerGroup.new :name => 'league-of-robots' }
88
+ it 'should return false' do
89
+ subject.exists?.should be_false
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ describe '#create' do
96
+
97
+ context "with NO path parameter (default)" do
98
+ subject { ComputerGroup.new :name => 'league-of-robots', :gid => "666" }
99
+ it 'saves the record to disk on the derived path' do
100
+ subject.create.should be_true
101
+ File.exists?(subject.file).should be_true
102
+ end
103
+ after do
104
+ FileUtils.rm_rf subject.file
105
+ end
106
+ end
107
+
108
+ context "with a path parameter" do
109
+ path = "/private/tmp/group-create-method-test.plist"
110
+ subject { ComputerGroup.new :name => 'league-of-robots', :gid => "666" }
111
+ it 'saves the record to disk on the path specified' do
112
+ subject.create(path).should be_true
113
+ end
114
+ after do
115
+ FileUtils.rm_rf path
116
+ end
117
+ end
118
+
119
+ end
120
+
121
+ describe '#destroy' do
122
+ subject { ComputerGroup.new :name => 'league-of-robots', :gid => "666" }
123
+ it 'removes the record on disk and returns true' do
124
+ subject.create
125
+ subject.destroy.should be_true
126
+ File.exists?(subject.file).should be_false
127
+ end
128
+ end
129
+
130
+ describe '#users=' do
131
+ subject { ComputerGroup.new 'fratbots' }
132
+ before { subject.users = ['fratbots', 'robot_mafia'] }
133
+ it 'replaces the membership array for users' do
134
+ subject['users'].should eq ['fratbots', 'robot_mafia']
135
+ end
136
+ end
137
+
138
+ describe '#users' do
139
+ subject { ComputerGroup.new 'fratbots' }
140
+ before { subject.users = ['fratbots', 'robot_mafia'] }
141
+ it 'returns a membership array of users' do
142
+ subject.users.should eq ['fratbots', 'robot_mafia']
143
+ end
144
+ end
145
+
146
+ describe '#has_user?' do
147
+ subject { ComputerGroup.new 'league-of-robots' }
148
+
149
+ context 'when membership array is non-existent' do
150
+ it 'should be false' do
151
+ subject.has_user?('bender').should be_false
152
+ end
153
+ end
154
+
155
+ context 'when membership array is populated' do
156
+ before { subject.users = ['bender', 'crushinator'] }
157
+ it 'should be true if the user is a member of the group' do
158
+ subject.has_user?('crushinator').should be_true
159
+ end
160
+
161
+ it 'should be false if the user is NOT a member of the group' do
162
+ subject.has_user?('flexo').should be_false
163
+ end
164
+ end
165
+
166
+ end
167
+
168
+ describe '#add_user' do
169
+ subject { ComputerGroup.new 'league-of-robots' }
170
+
171
+ context 'when the member does NOT exist' do
172
+ it 'should raise an error' do
173
+ expect { subject.add_user('flexo') }.to raise_error(StandardError)
174
+ end
175
+ end
176
+
177
+ context 'when the member exists' do
178
+ it "should add the user to the users array" do
179
+ crushinator = Computer.new 'crushinator'
180
+ crushinator.create
181
+ subject.add_user('crushinator').should be_nil
182
+ subject['users'].should eql ["crushinator"]
183
+ crushinator.destroy
184
+ end
185
+ end
186
+
187
+ end
188
+
189
+ describe '#rm_user' do
190
+ subject { ComputerGroup.new 'fratbots' }
191
+
192
+ context 'when user does NOT exist' do
193
+ it 'should return nil' do
194
+ subject.users = ['fry', 'bender']
195
+ subject.rm_user('leela').should be_nil
196
+ end
197
+ end
198
+
199
+ context 'when user does exist' do
200
+ it 'should remove the user from the membership array' do
201
+ subject.users = ['fry', 'bender']
202
+ subject.rm_user('fry').should eq 'fry'
203
+ subject.users.should eq ['bender']
204
+ end
205
+ end
206
+
207
+ end
208
+
209
+ describe '#has_groupmember?' do
210
+ subject { ComputerGroup.new 'league-of-robots' }
211
+
212
+ context 'when membership array is non-existent' do
213
+ it 'should be false' do
214
+ subject.has_groupmember?('fratbots').should be_false
215
+ end
216
+ end
217
+
218
+ context 'when membership array is populated' do
219
+ it 'should be true if the user is a member of the group' do
220
+ subject.groupmembers = ['00000000-0000-0000-0000-000000000001']
221
+ subject.has_groupmember?('fratbots').should be_true
222
+ end
223
+
224
+ it 'should be false if the user is NOT a member of the group' do
225
+ subject.has_groupmember?('killbots').should be_false
226
+ end
227
+ end
228
+
229
+ end
230
+
231
+ describe '#add_groupmember' do
232
+ subject { ComputerGroup.new 'league-of-robots' }
233
+
234
+ context 'when the member does NOT exist' do
235
+ it 'should raise an error' do
236
+ expect { subject.add_groupmember('killbots') }.to raise_error(StandardError)
237
+ end
238
+ end
239
+
240
+ context 'when the member exists' do
241
+ it "should add named group's GeneratedUID to the groupmembers array" do
242
+ subject.add_groupmember('fratbots').should be_nil
243
+ subject['groupmembers'].should eql ["00000000-0000-0000-0000-000000000001"]
244
+ end
245
+ end
246
+
247
+ end
248
+
249
+ describe '#rm_groupmember' do
250
+ subject { ComputerGroup.new 'league-of-robots' }
251
+
252
+ context 'when the member does NOT exist' do
253
+ it 'should return nil' do
254
+ subject.rm_groupmember('killbots').should be_nil
255
+ end
256
+ end
257
+
258
+ context 'when the member exists' do
259
+ it 'should remove the member from the array' do
260
+ ['fratbots', 'robot_mafia'].each do |member|
261
+ subject.add_groupmember member
262
+ end
263
+ subject.rm_groupmember('fratbots').should eq "00000000-0000-0000-0000-000000000001"
264
+ subject.groupmembers.should eq ["00000000-0000-0000-0000-000000000002"]
265
+ end
266
+ end
267
+
268
+ end
269
+
270
+ after :all do
271
+ FileUtils.rm_rf @test_dir
272
+ end
273
+
274
+ end
@@ -0,0 +1,179 @@
1
+ require 'spec_helper'
2
+
3
+ describe MacAdmin::DSLocalRecord do
4
+
5
+ before :all do
6
+ # Create a dslocal sandbox
7
+ @test_dir = "/private/tmp/macadmin_dslocal_test.#{rand(100000)}"
8
+ MacAdmin::DSLocalRecord.send(:remove_const, :DSLOCAL_ROOT)
9
+ MacAdmin::DSLocalRecord::DSLOCAL_ROOT = File.expand_path @test_dir
10
+ FileUtils.mkdir_p "#{@test_dir}/Default/groups"
11
+ FileUtils.mkdir_p "#{@test_dir}/Default/users"
12
+
13
+ # Create a user record plist that we can load
14
+ fry = {
15
+ "uid" => ["501"],
16
+ "name" => ["fry"],
17
+ "realname" => ["Phillip J. Fry"],
18
+ "generateduid" => ["00000000-0000-0000-0000-000000000001"],
19
+ }
20
+
21
+ record = CFPropertyList::List.new
22
+ record.value = CFPropertyList.guess(fry)
23
+ record.save("#{@test_dir}/Default/users/#{fry['name'].first}.plist", CFPropertyList::List::FORMAT_BINARY)
24
+ end
25
+
26
+ describe '#init_with_file' do
27
+ before do
28
+ @user = <<-RECORD
29
+ <?xml version="1.0" encoding="UTF-8"?>
30
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
31
+ <plist version="1.0">
32
+ <dict>
33
+ <key>generateduid</key>
34
+ <array>
35
+ <string>331D5FCC-DBE1-4193-9DBF-BC955E997B3E</string>
36
+ </array>
37
+ <key>name</key>
38
+ <array>
39
+ <string>foo</string>
40
+ </array>
41
+ <key>uid</key>
42
+ <array>
43
+ <string>411</string>
44
+ </array>
45
+ <key>gid</key>
46
+ <array>
47
+ <string>80</string>
48
+ </array>
49
+ <key>home</key>
50
+ <array>
51
+ <string>/Users/foo</string>
52
+ </array>
53
+ <key>shell</key>
54
+ <array>
55
+ <string>/bin/bash</string>
56
+ </array>
57
+ <key>realname</key>
58
+ <array>
59
+ <string>foo</string>
60
+ </array>
61
+ </dict>
62
+ </plist>
63
+ RECORD
64
+ @test_dir = "/private/tmp/test.#{rand(100000)}"
65
+ @file = "#{@test_dir}/Default/users/foo.plist"
66
+ FileUtils.mkdir_p "#{@test_dir}/Default/users"
67
+ File.open(@file, mode='w') { |f| f.write @user }
68
+ end
69
+
70
+ subject { User.init_with_file @file }
71
+ it { should be_an_instance_of User }
72
+ its (:uid) { should eq ['411'] }
73
+ its (:gid) { should eq ['80'] }
74
+ its (:name) { should eq ['foo'] }
75
+ its (:home) { should eq ["/Users/foo"] }
76
+ its (:shell) { should eq ["/bin/bash"] }
77
+ its (:realname) { should eq ['foo'] }
78
+ its (:generateduid) { should eq ['331D5FCC-DBE1-4193-9DBF-BC955E997B3E'] }
79
+
80
+ after do
81
+ FileUtils.rm_rf @test_dir
82
+ end
83
+
84
+ end
85
+
86
+ describe '#new' do
87
+
88
+ context 'throws an ArgumentError when given fewer than 1 params' do
89
+ subject { DSLocalRecord.new }
90
+ it { expect { subject }.to raise_error(ArgumentError) }
91
+ end
92
+
93
+ context 'throws a DSLocalError when given an invalid name attribute' do
94
+ subject { DSLocalRecord.new 'bad name' }
95
+ it { expect { subject }.to raise_error(DSLocalError) }
96
+ end
97
+
98
+ context 'throws a DSLocalError when given an invalid name attribute' do
99
+ subject { DSLocalRecord.new 'fry' }
100
+ it 'takes a String argument and returns a DSLocalRecord object' do
101
+ subject.should be_an_instance_of DSLocalRecord
102
+ end
103
+ end
104
+
105
+ context 'throws a DSLocalError when given an invalid name attribute' do
106
+ subject { DSLocalRecord.new :name => 'fry', :gid => 80, :uid => 666 }
107
+ it 'takes a Hash argument and returns a DSLocalRecord object' do
108
+ subject.should be_an_instance_of DSLocalRecord
109
+ end
110
+ end
111
+
112
+ end
113
+
114
+ describe '#exists?' do
115
+
116
+ context "when the object is different from its associated file" do
117
+ subject { DSLocalRecord.new :name => 'fry', :uid => 666 }
118
+ it { subject.exists?.should be_false }
119
+ end
120
+
121
+ context "when the object is identical to its associated file" do
122
+ subject { DSLocalRecord.new :name => 'fry',
123
+ :uid => "501",
124
+ :generateduid => "00000000-0000-0000-0000-000000000001",
125
+ :file => @test_dir + '/Default/users/fry.plist' }
126
+ it { subject.exists?.should be_true }
127
+ end
128
+
129
+ context "when the object does not have an associated file on disk" do
130
+ subject { DSLocalRecord.new 'bender' }
131
+ it { subject.exists?.should be_false }
132
+ end
133
+
134
+ end
135
+
136
+ describe '#create' do
137
+
138
+ context "with NO path parameter (default)" do
139
+ subject { DSLocalRecord.new :name => 'bender', :uid => "666", :file => @test_dir + '/Default/users/bender.plist' }
140
+ it 'saves the record to disk on the derived path' do
141
+ subject.create.should be_true
142
+ File.exists?(subject.file).should be_true
143
+ end
144
+ after do
145
+ FileUtils.rm_rf subject.file
146
+ end
147
+ end
148
+
149
+ context "with a path parameter" do
150
+ mode = 33152
151
+ path = "/private/tmp/group-create-method-test.plist"
152
+ subject { DSLocalRecord.new :name => 'leela', :uid => "609" }
153
+ it 'saves the record to disk on the path specified' do
154
+ subject.create(path).should be_true
155
+ stat = File::Stat.new path
156
+ File.exists?(path).should be_true
157
+ stat.mode.should eq mode
158
+ end
159
+ after do
160
+ FileUtils.rm_rf path
161
+ end
162
+ end
163
+
164
+ end
165
+
166
+ describe '#destroy' do
167
+ subject { DSLocalRecord.new :name => 'zoidberg', :file => @test_dir + '/Default/users/bender.plist' }
168
+ it 'removes the record on disk and returns true' do
169
+ subject.create
170
+ subject.destroy.should be_true
171
+ File.exists?(subject.file).should be_false
172
+ end
173
+ end
174
+
175
+ after :all do
176
+ FileUtils.rm_rf @test_dir
177
+ end
178
+
179
+ end