remy 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,360 @@
1
+ require 'spec_helper'
2
+
3
+ describe Remy::Config::Chef do
4
+ subject { Remy::Config::Chef }
5
+ before do
6
+ subject.instance_variable_set(:@config, nil)
7
+ end
8
+
9
+ after do
10
+ subject.instance_variable_set(:@config, nil)
11
+ end
12
+
13
+ def node_config(chef)
14
+ chef.instance_variable_get(:@node_config)
15
+ end
16
+
17
+ describe '.save_node_json' do
18
+ let(:node_json_output_path) { Dir.tmpdir + '/foo/chef/node.json' }
19
+
20
+ after do
21
+ FileUtils.rm node_json_output_path, :force => true
22
+ end
23
+
24
+ it 'should save the node json file to the specified directory' do
25
+ File.exist?(node_json_output_path).should be_false
26
+ subject.save_node_json(node_json_output_path)
27
+ File.exist?(node_json_output_path).should be_true
28
+ end
29
+
30
+ it 'should include chef configuration yml data as json' do
31
+ subject.configure { |config| config.yml_files = chef_fixture('foo.yml') }
32
+ subject.save_node_json(node_json_output_path)
33
+ data_from_json = JSON.parse(File.read(node_json_output_path))
34
+ data_from_json['blah'].should == 'bar'
35
+ end
36
+ end
37
+
38
+ describe '.config' do
39
+ describe 'with no yml files' do
40
+ it 'should return an empty mash' do
41
+ subject.config.should == Hashie::Mash.new
42
+ end
43
+ end
44
+
45
+ describe "yml files" do
46
+ it 'should combine multiple yaml files into a mash' do
47
+ subject.configure { |config| config.yml_files = [chef_fixture('foo.yml'), chef_fixture('bar.yml')] }
48
+ subject.config.yml_files.should == [chef_fixture('foo.yml'), chef_fixture('bar.yml')]
49
+ subject.config.blah.should == 'bar' # From foo.yml
50
+ subject.config.baz.should == 'baz' # From bar.yml
51
+ subject.config.colors.to_hash.symbolize_keys.should == {:blue => 'blue', :green => 'green', :red => 'red'}
52
+ end
53
+
54
+ it 'should return an empty array if there are no yml files' do
55
+ subject.configure {}
56
+ subject.config.yml_files.should == []
57
+ end
58
+
59
+ it 'should not raise an error if there is a file does does not exist' do
60
+ expect do
61
+ subject.configure { |config| config.yml_files = ['does_not_exist.yml'] }
62
+ end.should_not raise_error
63
+ end
64
+ end
65
+ describe 'json config files' do
66
+ before do
67
+ pending
68
+ end
69
+ it 'should combine multiple json files into a mash' do
70
+ subject.configure { |config| config.json_files = [chef_fixture('foo.json'), chef_fixture('bar.json')] }
71
+ subject.config.json_files.should == [chef_fixture('foo.json'), chef_fixture('bar.json')]
72
+ subject.config.blah.should == 'bar' # From foo.json
73
+ subject.config.baz.should == 'baz' # From bar.json
74
+ subject.config.colors.to_hash.symbolize_keys.should == {:blue => 'blue', :green => 'green', :red => 'red'}
75
+ end
76
+
77
+ it 'should return an empty array if there are no json files' do
78
+ subject.configure {}
79
+ subject.config.json_files.should == []
80
+ end
81
+
82
+ it 'should have the values in the json files override the values from the json files' do
83
+ end
84
+ end
85
+
86
+ describe "cookbooks path" do
87
+ it "should work if a single cookbook path is specified" do
88
+ subject.configure { |config| config.cookbook_path = 'cookbooks' }
89
+ subject.config.cookbook_path.should == ['cookbooks']
90
+ end
91
+
92
+ it "should work if multiple cookbook paths are specified" do
93
+ subject.configure { |config| config.cookbook_path = ['cookbooks1', 'cookbooks2'] }
94
+ subject.config.cookbook_path.should == ['cookbooks1', 'cookbooks2']
95
+ end
96
+
97
+ it "should return an empty array if no cookbook paths are specified" do
98
+ subject.configure {}
99
+ subject.config.cookbook_path.should == []
100
+ end
101
+ end
102
+
103
+ describe "specs path" do
104
+ it "should work if a single spec path is specified" do
105
+ subject.configure { |config| config.spec_path = 'specs' }
106
+ subject.config.spec_path.should == ['specs']
107
+ end
108
+
109
+ it "should work if multiple spec paths are specified" do
110
+ subject.configure { |config| config.spec_path = ['specs1', 'specs2'] }
111
+ subject.config.spec_path.should == ['specs1', 'specs2']
112
+ end
113
+
114
+ it "should return an empty array if no spec paths are specified" do
115
+ subject.configure {}
116
+ subject.config.spec_path.should == []
117
+ end
118
+ end
119
+
120
+ describe "roles path" do
121
+ it "should work if a single file is specified" do
122
+ subject.configure { |config| config.roles_path = 'roles' }
123
+ subject.config.roles_path.should == ['roles']
124
+ end
125
+
126
+ it "should work if multiple files are specified" do
127
+ subject.configure { |config| config.roles_path = ['roles1', 'roles2'] }
128
+ subject.config.roles_path.should == ['roles1', 'roles2']
129
+ end
130
+
131
+ it "should return an empty array if no roles paths are specified" do
132
+ subject.configure {}
133
+ subject.config.roles_path.should == []
134
+ end
135
+ end
136
+
137
+ describe "node attributes" do
138
+ it "should merge in the other node attributes from the hash" do
139
+ subject.configure { |config| config.node_attributes = {:another_node_attribute => 'red'} }
140
+ subject.config.another_node_attribute.should == 'red'
141
+ end
142
+
143
+ it "should not blow up if there no node attributes are specified" do
144
+ lambda { subject.configure {} }.should_not raise_error
145
+ end
146
+ end
147
+
148
+ describe "#remote_chef_dir" do
149
+ it "should default to /var/chef if no option is given" do
150
+ subject.configure {}
151
+ subject.config.remote_chef_dir.should == '/var/chef'
152
+ end
153
+
154
+ it "should be able to be overriden" do
155
+ subject.configure { |config| config.remote_chef_dir = '/foo/shef' }
156
+ subject.config.remote_chef_dir.should == '/foo/shef'
157
+ end
158
+ end
159
+ end
160
+
161
+ context 'with a config' do
162
+ before do
163
+ subject.configure do |config|
164
+ config.yml_files = [chef_fixture('chef.yml')]
165
+ end
166
+ end
167
+
168
+ describe '.servers' do
169
+ it 'returns all servers' do
170
+ subject.servers.size.should == 3
171
+ subject.servers['db.sharespost.com'].color.should == 'yellow'
172
+ end
173
+ end
174
+
175
+ describe '.find_servers' do
176
+ it 'should return servers that match the criteria' do
177
+ subject.find_servers(:rails_env => 'demo').keys.should == ['web.sharespost.com', 'demo.sharespost.com']
178
+ end
179
+
180
+ it 'should return all servers if there are no criteria' do
181
+ subject.find_servers.keys.should =~ ['db.sharespost.com', 'web.sharespost.com', 'demo.sharespost.com']
182
+ end
183
+
184
+ it 'should return servers that match the criteria (with multiple criteria)' do
185
+ subject.find_servers(:rails_env => 'demo', :color => 'blue').keys.should == ['web.sharespost.com']
186
+ end
187
+
188
+ it "should return nil if there are no servers specified in the yaml file" do
189
+ subject.configure { |config| config.yml_files = chef_fixture('hello_world_chef.yml') }
190
+ subject.find_servers(:rails_env => 'demo').should be_nil
191
+ end
192
+ end
193
+
194
+ describe '.find_server' do
195
+ it 'should return the first server that matchs the criteria' do
196
+ subject.find_server(:rails_env => 'demo').keys.should == ['web.sharespost.com']
197
+ end
198
+
199
+ it 'should return nil if there are no servers specifie in the yml files' do
200
+ subject.configure { |config| config.yml_files = chef_fixture('hello_world_chef.yml') }
201
+ subject.find_server(:rails_env => 'demo').should be_nil
202
+ end
203
+ end
204
+
205
+ describe '.find_server_config' do
206
+ it 'should return the first server that matchs the criteria' do
207
+ subject.find_server_config(:rails_env => 'demo').to_hash.should == {"color" => "blue", "recipes" => ["recipe[hello_world]"], "rails_env" => "demo", "ip_address" => IP_ADDRESS_OF_REMY_TEST}
208
+ end
209
+
210
+ it 'should return nil if no server info is found' do
211
+ subject.find_server_config(:rails_env => 'foo').should be_nil
212
+ end
213
+
214
+ it 'should return nil if there are no servers in the yml files' do
215
+ subject.configure { |config| config.yml_files = chef_fixture('hello_world_chef.yml') }
216
+ subject.find_server_config(:rails_env => 'foo').should be_nil
217
+ end
218
+ end
219
+
220
+ describe '.find_server_config_by_name' do
221
+ it 'should return the server that matches the name' do
222
+ subject.find_server_config_by_name('db.sharespost.com').to_hash.should == {"encoding" => "utf8", "adapter" => "mysql2", "color" => "yellow", "rails_env" => "production", "ip_address" => "51.51.51.51"}
223
+ end
224
+
225
+ it 'should return nil if theres no server that matches the name' do
226
+ subject.find_server_config_by_name('db.asdfjkll.com').should be_nil
227
+ end
228
+
229
+ it 'should return nil (and not blow up) if there are no servers in the yml files' do
230
+ subject.configure { |config| config.yml_files = chef_fixture('hello_world_chef.yml') }
231
+ subject.find_server_config_by_name('db.asdfjkll.com').should be_nil
232
+ end
233
+
234
+ it 'should return nil (and not blow up) if there is no Remy config' do
235
+ Remy.instance_variable_set('@config', nil)
236
+ subject.find_server_config_by_name('db.asdfjkll.com').should be_nil
237
+ end
238
+ end
239
+
240
+ describe '.cloud_config' do
241
+ it 'should return nil if it has not been specified in the yml files' do
242
+ subject.configure { |config| config.yml_files = chef_fixture('hello_world_chef.yml') }
243
+ subject.cloud_config.should be_nil
244
+ end
245
+
246
+ it 'should return the cloud config options if present in the yml files' do
247
+ subject.cloud_config.should == Hashie::Mash.new(
248
+ :cloud_api_key => 'abcdefg12345',
249
+ :cloud_provider => 'Rackspace',
250
+ :cloud_username => 'sharespost',
251
+ :flavor_id => 4,
252
+ :image_id => 49,
253
+ :server_name => 'new-server.somedomain.com')
254
+
255
+ end
256
+
257
+ it 'should return nil if there is currently no Remy config' do
258
+ subject.instance_variable_set('@config', nil)
259
+ subject.cloud_config.should be_nil
260
+ end
261
+ end
262
+
263
+ describe '.bootstrap' do
264
+ it 'should return nil if it has not been specified in the yml files' do
265
+ subject.configure { |config| config.yml_files = chef_fixture('hello_world_chef.yml') }
266
+ subject.bootstrap.should be_nil
267
+ end
268
+
269
+ it 'should return the bootstrap options if present in the yml files' do
270
+ subject.bootstrap.should == Hashie::Mash.new(
271
+ :ruby_version => '1.9.2',
272
+ :gems => {
273
+ :chef => '10.12.0',
274
+ :rspec => '2.11.0',
275
+ :bundler => '3.0.0'
276
+ })
277
+ end
278
+
279
+ it 'should return nil if there is currently no Remy config' do
280
+ subject.instance_variable_set('@config', nil)
281
+ subject.bootstrap.should be_nil
282
+ end
283
+ end
284
+ end
285
+
286
+ describe "#initialize and the node config" do
287
+ it 'should use the top-level IP address in the yml files, if one is present, and an ip address is not passed in as an argument' do
288
+ subject.configure { |config| config.yml_files = chef_fixture('hello_world_chef.yml') }
289
+ chef = Remy::Chef.new
290
+ node_config(chef).ip_address.should == IP_ADDRESS_OF_REMY_TEST
291
+ node_config(chef).color.should == 'blue'
292
+ node_config(chef).recipes.should == ['recipe[hello_world]']
293
+ end
294
+
295
+ it 'should allow the top-level values in the yml files (including the ip address) to be overridden' do
296
+ subject.configure { |config| config.yml_files = chef_fixture('hello_world_chef.yml') }
297
+ chef = Remy::Chef.new(:ip_address => '1.2.3.4', :color => 'green')
298
+ node_config(chef).ip_address.should == '1.2.3.4'
299
+ node_config(chef).color.should == 'green'
300
+ node_config(chef).recipes.should == ['recipe[hello_world]']
301
+ end
302
+
303
+ it 'should return properties from the :servers section of the yml file if the ip address is found in there' do
304
+ subject.configure { |config| config.yml_files = chef_fixture('chef.yml') }
305
+ chef = Remy::Chef.new(:ip_address => '51.51.51.51')
306
+ node_config(chef).ip_address.should == '51.51.51.51'
307
+ node_config(chef).rails_env.should == 'production'
308
+ node_config(chef).color.should == 'yellow'
309
+ node_config(chef).adapter.should == 'mysql2'
310
+ node_config(chef).encoding.should == 'utf8'
311
+ end
312
+
313
+ it 'should allow properties from the servers section of the yml file to be overridden plus additional options added' do
314
+ subject.configure { |config| config.yml_files = chef_fixture('chef.yml') }
315
+ chef = Remy::Chef.new(:ip_address => '51.51.51.51', :color => 'purple', :temperature => 'warm')
316
+ node_config(chef).color.should == 'purple' # Overrides 'yellow' from the yml files
317
+ node_config(chef).temperature.should == 'warm' # A new node attribute which is not present in the yml files
318
+ end
319
+
320
+ it 'should allow the chef args to be specified (and not merge this chef_args value into the node config)' do
321
+ subject.configure { |config| config.yml_files = chef_fixture('chef.yml') }
322
+ chef = Remy::Chef.new(:chef_args => '-l debug')
323
+ node_config(chef).chef_args.should be_nil
324
+ chef.instance_variable_get(:@chef_args).should == '-l debug'
325
+ end
326
+
327
+ it 'should allow the quiet option to be specified (and not merge this option into the node config)' do
328
+ subject.configure { |config| config.yml_files = chef_fixture('chef.yml') }
329
+ chef = Remy::Chef.new(:quiet => true)
330
+ node_config(chef).quiet.should be_nil
331
+ chef.instance_variable_get(:@quiet).should be_true
332
+ end
333
+
334
+ it 'should not modify the global Remy config, but rather only the node config for this particular Chef node' do
335
+ subject.configure { |config| config.yml_files = chef_fixture('bar.yml') }
336
+ subject.config.another_node_attribute.should == 'hot'
337
+ chef = Remy::Chef.new(:another_node_attribute => 'cold')
338
+ node_config(chef).another_node_attribute.should == 'cold'
339
+ subject.config.another_node_attribute.should == 'hot' # Unchanged from its original value # do some checks
340
+ end
341
+ end
342
+
343
+ describe '#run' do
344
+ before do
345
+ subject.configure { |config| config.yml_files = chef_fixture('chef.yml') }
346
+ end
347
+
348
+ it 'should work with a hash as its argument' do
349
+ chef = Remy::Chef.new(:ip_address => IP_ADDRESS_OF_REMY_TEST)
350
+ node_config(chef).ip_address.should == IP_ADDRESS_OF_REMY_TEST
351
+ node_config(chef).recipes.should == ['recipe[hello_world]']
352
+ end
353
+
354
+ it 'should work with JSON as its argument' do
355
+ chef = Remy::Chef.new("{\"ip_address\":\"#{IP_ADDRESS_OF_REMY_TEST}\"}")
356
+ node_config(chef).ip_address.should == IP_ADDRESS_OF_REMY_TEST
357
+ node_config(chef).recipes.should == ['recipe[hello_world]']
358
+ end
359
+ end
360
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ describe Remy::Config::Node do
3
+ subject { Remy::Config::Node }
4
+ before do
5
+ subject.instance_variable_set(:@config, nil)
6
+ end
7
+
8
+ after do
9
+ subject.instance_variable_set(:@config, nil)
10
+ end
11
+
12
+ describe '.config' do
13
+ describe "from json file" do
14
+ it 'should extract the contents of the json file' do
15
+ subject.configure { |config| config.json_file = chef_fixture('node.json') }
16
+ subject.config.blah.should == 'bar'
17
+ end
18
+ end
19
+ end
20
+ end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Remy::Chef do
4
4
  before do
5
- Remy.configure do |config|
5
+ Remy::Config::Chef.configure do |config|
6
6
  config.yml_files = ['../../fixtures/foo.yml', '../../fixtures/bar.yml', '../../fixtures/chef.yml'].map { |f| File.join(File.dirname(__FILE__), f) }
7
7
  config.cookbook_path = ["../../../chef/cookbooks"].map { |f| File.join(File.dirname(__FILE__), f) }
8
8
  config.spec_path = ["../../../chef/spec"].map { |f| File.join(File.dirname(__FILE__), f) }
@@ -11,7 +11,7 @@ describe Remy::Chef do
11
11
 
12
12
  describe '#run' do
13
13
  def clean_up_remote_chef_test_files(chef)
14
- chef.remote_execute "rm -rf /tmp/hello_world.txt #{Remy.configuration.remote_chef_dir}" if Remy.configuration.remote_chef_dir && Remy.configuration.remote_chef_dir.size > 2
14
+ chef.remote_execute "rm -rf /tmp/hello_world.txt #{Remy::Config::Chef.config.remote_chef_dir}" if Remy::Config::Chef.config.remote_chef_dir && Remy::Config::Chef.config.remote_chef_dir.size > 2
15
15
  end
16
16
 
17
17
  def verify_contents_of_hello_world(chef)
@@ -27,13 +27,13 @@ describe Remy::Chef do
27
27
  end
28
28
 
29
29
  it 'should work with a hash as its argument' do
30
- run_chef(:ip_address => IP_ADDRESS) do |chef|
30
+ run_chef(:ip_address => IP_ADDRESS_OF_REMY_TEST) do |chef|
31
31
  verify_contents_of_hello_world(chef)
32
32
  end
33
33
  end
34
34
 
35
35
  it 'should work with JSON as its argument' do
36
- run_chef("{\"ip_address\":\"#{IP_ADDRESS}\"}") do |chef|
36
+ run_chef("{\"ip_address\":\"#{IP_ADDRESS_OF_REMY_TEST}\"}") do |chef|
37
37
  verify_contents_of_hello_world(chef)
38
38
  end
39
39
  end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Remy::Utility do
4
+ describe 'instance methods' do
5
+ subject do
6
+ Class.new do
7
+ include Remy::Utility
8
+ end.new
9
+ end
10
+ describe '#flatten_paths' do
11
+ let(:base_path) { }
12
+ let(:expected_paths) { [File.expand_path('a'), File.expand_path('b')] }
13
+ it 'should return a map of paths for arrays' do
14
+ subject.flatten_paths(['a'], ['b']).should == expected_paths
15
+ end
16
+
17
+ it 'should return a map of paths for strings (regression for 1.9.2)' do
18
+ subject.flatten_paths('a', 'b').should == expected_paths
19
+ end
20
+ end
21
+ end
22
+ end