remy 0.0.3 → 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,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