kitchen-scribe 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/.gitignore +1 -0
- data/.rvmrc +34 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +73 -0
- data/LICENSE +201 -0
- data/README.md +63 -0
- data/kitchen-scribe.gemspec +23 -0
- data/lib/chef/knife/scribe_copy.rb +165 -0
- data/lib/chef/knife/scribe_hire.rb +92 -0
- data/lib/kitchen-scribe/version.rb +4 -0
- data/spec/chef/knife/scribe_copy_spec.rb +492 -0
- data/spec/chef/knife/scribe_hire_spec.rb +253 -0
- data/spec/spec_helper.rb +23 -0
- metadata +127 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Pawel Kozlowski (<pawel.kozlowski@u2i.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 Pawel Kozlowski
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
|
20
|
+
require 'chef/mixin/shell_out'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
class ScribeHire < Chef::Knife
|
25
|
+
|
26
|
+
include Chef::Mixin::ShellOut
|
27
|
+
|
28
|
+
DEFAULT_CHRONICLE_PATH = ".chronicle"
|
29
|
+
DEFAULT_REMOTE_NAME = "origin"
|
30
|
+
|
31
|
+
banner "knife scribe hire"
|
32
|
+
|
33
|
+
option :chronicle_path,
|
34
|
+
:short => "-p PATH",
|
35
|
+
:long => "--chronicle-path PATH",
|
36
|
+
:description => "Path to the directory where the chronicle should be located",
|
37
|
+
:default => nil
|
38
|
+
|
39
|
+
option :remote_name,
|
40
|
+
:long => "--remote-name REMOTE_NAME",
|
41
|
+
:description => "Name of the remote chronicle repository",
|
42
|
+
:default => nil
|
43
|
+
|
44
|
+
option :remote_url,
|
45
|
+
:short => "-r REMOTE_URL",
|
46
|
+
:long => "--remote-url REMOTE_URL",
|
47
|
+
:description => "Url of the remote chronicle repository",
|
48
|
+
:default => nil
|
49
|
+
|
50
|
+
def run
|
51
|
+
configure
|
52
|
+
Dir.mkdir(config[:chronicle_path]) unless File.directory?(config[:chronicle_path])
|
53
|
+
init_chronicle
|
54
|
+
setup_remote if config[:remote_url]
|
55
|
+
["environments", "nodes", "roles"].each do |dir|
|
56
|
+
path = File.join(config[:chronicle_path], dir)
|
57
|
+
Dir.mkdir(path) unless File.directory?(path)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def configure
|
62
|
+
conf = { :chronicle_path => DEFAULT_CHRONICLE_PATH,
|
63
|
+
:remote_name => DEFAULT_REMOTE_NAME }
|
64
|
+
conf.merge!(Chef::Config[:knife][:scribe]) if Chef::Config[:knife][:scribe].kind_of? Hash
|
65
|
+
conf.each do |key, value|
|
66
|
+
config[key] ||= value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def init_chronicle
|
71
|
+
shell_out!("git init", { :cwd => config[:chronicle_path] })
|
72
|
+
end
|
73
|
+
|
74
|
+
def setup_remote
|
75
|
+
check_remote_command = "git config --get remote.#{config[:remote_name]}.url"
|
76
|
+
remote_status = shell_out!(check_remote_command, { :cwd => config[:chronicle_path], :returns => [0,1,2] })
|
77
|
+
case remote_status.exitstatus
|
78
|
+
when 0, 2
|
79
|
+
# In theory 2 should not happen unless somebody messed with
|
80
|
+
# the checkout manually, but using --replace-all option will fix it
|
81
|
+
unless remote_status.exitstatus != 2 && remote_status.stdout.strip.eql?(config[:remote_url])
|
82
|
+
update_remote_url_command = "git config --replace-all remote.#{config[:remote_name]}.url #{config[:remote_url]}"
|
83
|
+
shell_out!(update_remote_url_command, { :cwd => config[:chronicle_path] })
|
84
|
+
end
|
85
|
+
when 1
|
86
|
+
add_remote_command = "git remote add #{config[:remote_name]} #{config[:remote_url]}"
|
87
|
+
shell_out!(add_remote_command, { :cwd => config[:chronicle_path] })
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,492 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Pawel Kozlowski (<pawel.kozlowski@u2i.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 Pawel Kozlowski
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
20
|
+
|
21
|
+
describe Chef::Knife::ScribeCopy do
|
22
|
+
before(:each) do
|
23
|
+
@scribe = Chef::Knife::ScribeCopy.new
|
24
|
+
@scribe.configure
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#run" do
|
28
|
+
before(:each) do
|
29
|
+
@scribe.stub(:remote_configured?)
|
30
|
+
@scribe.stub(:pull)
|
31
|
+
@scribe.stub(:fetch_configs)
|
32
|
+
@scribe.stub(:commit)
|
33
|
+
@scribe.stub(:push)
|
34
|
+
@scribe.stub(:configure)
|
35
|
+
@scribe.stub(:switch_branches)
|
36
|
+
@scribe.stub(:fetch)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "configures itself" do
|
40
|
+
@scribe.should_receive(:configure)
|
41
|
+
@scribe.run
|
42
|
+
end
|
43
|
+
|
44
|
+
it "switches the branch" do
|
45
|
+
@scribe.should_receive(:switch_branches)
|
46
|
+
@scribe.run
|
47
|
+
end
|
48
|
+
|
49
|
+
it "checks if a given remote is configured" do
|
50
|
+
@scribe.should_receive(:remote_configured?)
|
51
|
+
@scribe.run
|
52
|
+
end
|
53
|
+
|
54
|
+
it "fetches the configs from the chef server" do
|
55
|
+
@scribe.should_receive(:fetch_configs)
|
56
|
+
@scribe.run
|
57
|
+
end
|
58
|
+
|
59
|
+
it "commits the changes" do
|
60
|
+
@scribe.should_receive(:commit)
|
61
|
+
@scribe.run
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "when the remote is not configured" do
|
65
|
+
before(:each) do
|
66
|
+
@scribe.stub(:remote_configured?) { false }
|
67
|
+
end
|
68
|
+
|
69
|
+
it "doesn't attempt to fetch from the remote repository" do
|
70
|
+
@scribe.should_not_receive(:fetch)
|
71
|
+
@scribe.run
|
72
|
+
end
|
73
|
+
|
74
|
+
it "doesn't attempt to pull the changes from the remote repository" do
|
75
|
+
@scribe.should_not_receive(:pull)
|
76
|
+
@scribe.run
|
77
|
+
end
|
78
|
+
|
79
|
+
it "doesn't attempt to push the changes to the remote repository" do
|
80
|
+
@scribe.should_not_receive(:push)
|
81
|
+
@scribe.run
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "when the remote is configured" do
|
87
|
+
before(:each) do
|
88
|
+
@scribe.stub(:remote_configured?) { true }
|
89
|
+
end
|
90
|
+
|
91
|
+
it "fetches changes from remote repository" do
|
92
|
+
@scribe.should_receive(:fetch)
|
93
|
+
@scribe.run
|
94
|
+
end
|
95
|
+
|
96
|
+
it "pulls changes from remote repository" do
|
97
|
+
@scribe.should_receive(:pull)
|
98
|
+
@scribe.run
|
99
|
+
end
|
100
|
+
|
101
|
+
it "pushes the changes to the remote repository" do
|
102
|
+
@scribe.should_receive(:push)
|
103
|
+
@scribe.run
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "#configure" do
|
109
|
+
|
110
|
+
describe "when no configuration is given" do
|
111
|
+
before(:each) do
|
112
|
+
@scribe.config = {}
|
113
|
+
Chef::Config[:knife][:scribe] = nil
|
114
|
+
end
|
115
|
+
|
116
|
+
it "uses the default values for all parameters" do
|
117
|
+
@scribe.configure
|
118
|
+
@scribe.config[:chronicle_path].should == Chef::Knife::ScribeCopy::DEFAULT_CHRONICLE_PATH
|
119
|
+
@scribe.config[:remote_name].should == Chef::Knife::ScribeCopy::DEFAULT_REMOTE_NAME
|
120
|
+
@scribe.config[:branch].should == Chef::Knife::ScribeCopy::DEFAULT_BRANCH
|
121
|
+
@scribe.config[:commit_message].should == Chef::Knife::ScribeCopy::DEFAULT_COMMIT_MESSAGE
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "when configuration is given through knife config" do
|
126
|
+
before(:each) do
|
127
|
+
Chef::Config[:knife][:scribe] = {}
|
128
|
+
Chef::Config[:knife][:scribe][:chronicle_path] = Chef::Knife::ScribeCopy::DEFAULT_CHRONICLE_PATH + "_knife"
|
129
|
+
Chef::Config[:knife][:scribe][:remote_name] = Chef::Knife::ScribeCopy::DEFAULT_REMOTE_NAME + "_knife"
|
130
|
+
Chef::Config[:knife][:scribe][:branch] = Chef::Knife::ScribeCopy::DEFAULT_BRANCH + "_knife"
|
131
|
+
Chef::Config[:knife][:scribe][:commit_message] = Chef::Knife::ScribeCopy::DEFAULT_COMMIT_MESSAGE + "_knife"
|
132
|
+
@scribe.config = {}
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "when no other configuration is given" do
|
136
|
+
before(:each) do
|
137
|
+
@scribe.config = {}
|
138
|
+
end
|
139
|
+
|
140
|
+
it "uses the configuration from knife config" do
|
141
|
+
@scribe.configure
|
142
|
+
@scribe.config[:chronicle_path].should == Chef::Config[:knife][:scribe][:chronicle_path]
|
143
|
+
@scribe.config[:remote_name].should == Chef::Config[:knife][:scribe][:remote_name]
|
144
|
+
@scribe.config[:branch].should == Chef::Config[:knife][:scribe][:branch]
|
145
|
+
@scribe.config[:commit_message].should == Chef::Config[:knife][:scribe][:commit_message]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "when command line configuration is given" do
|
150
|
+
before(:each) do
|
151
|
+
@scribe.config[:chronicle_path] = Chef::Knife::ScribeCopy::DEFAULT_CHRONICLE_PATH + "_cmd"
|
152
|
+
@scribe.config[:remote_name] = Chef::Knife::ScribeCopy::DEFAULT_REMOTE_NAME + "_cmd"
|
153
|
+
@scribe.config[:branch] = Chef::Knife::ScribeCopy::DEFAULT_BRANCH + "_cmd"
|
154
|
+
@scribe.config[:commit_message] = Chef::Knife::ScribeCopy::DEFAULT_COMMIT_MESSAGE + "_cmd"
|
155
|
+
end
|
156
|
+
|
157
|
+
it "uses the configuration from command line" do
|
158
|
+
@scribe.configure
|
159
|
+
@scribe.config[:chronicle_path].should == Chef::Knife::ScribeCopy::DEFAULT_CHRONICLE_PATH + "_cmd"
|
160
|
+
@scribe.config[:remote_name].should == Chef::Knife::ScribeCopy::DEFAULT_REMOTE_NAME + "_cmd"
|
161
|
+
@scribe.config[:branch].should == Chef::Knife::ScribeCopy::DEFAULT_BRANCH + "_cmd"
|
162
|
+
@scribe.config[:commit_message].should == Chef::Knife::ScribeCopy::DEFAULT_COMMIT_MESSAGE + "_cmd"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "#switch_branches" do
|
169
|
+
|
170
|
+
before(:each) do
|
171
|
+
@command_response = double('shell_out')
|
172
|
+
@command_response.stub(:exitstatus) { 0 }
|
173
|
+
@branch_command = "git branch"
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "when already on the branch" do
|
177
|
+
it "does nothing" do
|
178
|
+
@command_response.stub(:stdout) { "#{@scribe.config[:branch]}2\n* #{@scribe.config[:branch]}\n#a{@scribe.config[:branch]}" }
|
179
|
+
@scribe.should_receive(:shell_out!).with(@branch_command,
|
180
|
+
:cwd => @scribe.config[:chronicle_path]).and_return(@command_response)
|
181
|
+
switch_command = "git checkout -B #{@scribe.config[:branch]}"
|
182
|
+
@scribe.should_not_receive(:shell_out!).with(switch_command,
|
183
|
+
:cwd => @scribe.config[:chronicle_path])
|
184
|
+
@scribe.switch_branches
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe "when the branch exists but is not the current one" do
|
189
|
+
it "switches to the branch" do
|
190
|
+
@command_response.stub(:stdout) { "#{@scribe.config[:branch]}2\n #{@scribe.config[:branch]}\n#* a{@scribe.config[:branch]}" }
|
191
|
+
@scribe.should_receive(:shell_out!).with(@branch_command,
|
192
|
+
:cwd => @scribe.config[:chronicle_path]).and_return(@command_response)
|
193
|
+
switch_command = "git checkout -B #{@scribe.config[:branch]}"
|
194
|
+
@scribe.should_receive(:shell_out!).with(switch_command,
|
195
|
+
:cwd => @scribe.config[:chronicle_path])
|
196
|
+
@scribe.switch_branches
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "when the branch doesn't exist'" do
|
201
|
+
it "creates the branch and switches to it" do
|
202
|
+
@command_response.stub(:stdout) { "* #{@scribe.config[:branch]}2\n#a{@scribe.config[:branch]}" }
|
203
|
+
@scribe.should_receive(:shell_out!).with(@branch_command,
|
204
|
+
:cwd => @scribe.config[:chronicle_path]).and_return(@command_response)
|
205
|
+
switch_command = "git checkout -B #{@scribe.config[:branch]}"
|
206
|
+
@scribe.should_receive(:shell_out!).with(switch_command,
|
207
|
+
:cwd => @scribe.config[:chronicle_path])
|
208
|
+
@scribe.switch_branches
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
describe "#remote_configured?" do
|
215
|
+
|
216
|
+
before(:each) do
|
217
|
+
@command_response = double('shell_out')
|
218
|
+
@command_response.stub(:exitstatus) { 0 }
|
219
|
+
@remote_command = "git remote"
|
220
|
+
end
|
221
|
+
|
222
|
+
it "returns false if no remote is configured" do
|
223
|
+
@command_response.stub(:stdout) { "" }
|
224
|
+
@scribe.should_receive(:shell_out!).with(@remote_command,
|
225
|
+
:cwd => @scribe.config[:chronicle_path]).and_return(@command_response)
|
226
|
+
@scribe.remote_configured?.should be(false)
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
it "returns false if a given remote is not configured" do
|
231
|
+
@command_response.stub(:stdout) { "another_remote_name\nyet_another_remote_name\nAAA#{@scribe.config[:remote_name]}" }
|
232
|
+
@scribe.should_receive(:shell_out!).with(@remote_command,
|
233
|
+
:cwd => @scribe.config[:chronicle_path]).and_return(@command_response)
|
234
|
+
|
235
|
+
@scribe.remote_configured?.should be(false)
|
236
|
+
end
|
237
|
+
|
238
|
+
it "returns true if a given remote is configured" do
|
239
|
+
@command_response.stub(:stdout) { "another_#{@scribe.config[:remote_name]}\n#{@scribe.config[:remote_name]}\nyet_another_#{@scribe.config[:remote_name]}" }
|
240
|
+
@scribe.should_receive(:shell_out!).with(@remote_command,
|
241
|
+
:cwd => @scribe.config[:chronicle_path]).and_return(@command_response)
|
242
|
+
@scribe.remote_configured?.should be(true)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe "#fetch" do
|
247
|
+
it "fetches the changes from the remote repository" do
|
248
|
+
fetch_command = "git fetch #{@scribe.config[:remote_name]}"
|
249
|
+
@scribe.should_receive(:shell_out!).with(fetch_command,
|
250
|
+
:cwd => @scribe.config[:chronicle_path])
|
251
|
+
@scribe.fetch
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
|
256
|
+
describe "#pull" do
|
257
|
+
before(:each) do
|
258
|
+
@command_response = double('shell_out')
|
259
|
+
@command_response.stub(:exitstatus) { 0 }
|
260
|
+
end
|
261
|
+
|
262
|
+
describe "when a remote branch already exists" do
|
263
|
+
it "pulls from the remote repository" do
|
264
|
+
@command_response.stub(:stdout) { "#{@scribe.config[:branch]}\nremotes/#{@scribe.config[:remote_name]}/#{@scribe.config[:branch]}" }
|
265
|
+
check_remote_branch_command = "git branch -a"
|
266
|
+
@scribe.should_receive(:shell_out!).with(check_remote_branch_command,
|
267
|
+
:cwd => @scribe.config[:chronicle_path]).and_return(@command_response)
|
268
|
+
pull_command = "git pull #{@scribe.config[:remote_name]} #{@scribe.config[:branch]}"
|
269
|
+
@scribe.should_receive(:shell_out!).with(pull_command,
|
270
|
+
:cwd => @scribe.config[:chronicle_path])
|
271
|
+
@scribe.pull
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe "when a remote branch doesn't already exist" do
|
276
|
+
it "doesn't pull'" do
|
277
|
+
@command_response.stub(:stdout) { "#{@scribe.config[:branch]}2\nremotes/#{@scribe.config[:remote_name]}/#{@scribe.config[:branch]}2" }
|
278
|
+
check_remote_branch_command = "git branch -a"
|
279
|
+
@scribe.should_receive(:shell_out!).with(check_remote_branch_command,
|
280
|
+
:cwd => @scribe.config[:chronicle_path]).and_return(@command_response)
|
281
|
+
pull_command = "git pull #{@scribe.config[:remote_name]} #{@scribe.config[:branch]}"
|
282
|
+
@scribe.should_not_receive(:shell_out!).with(pull_command,
|
283
|
+
:cwd => @scribe.config[:chronicle_path])
|
284
|
+
@scribe.pull
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
describe "when the repository is empty" do
|
289
|
+
it "doesn't pull'" do
|
290
|
+
@command_response.stub(:stdout) { "" }
|
291
|
+
check_remote_branch_command = "git branch -a"
|
292
|
+
@scribe.should_receive(:shell_out!).with(check_remote_branch_command,
|
293
|
+
:cwd => @scribe.config[:chronicle_path]).and_return(@command_response)
|
294
|
+
pull_command = "git pull #{@scribe.config[:remote_name]} #{@scribe.config[:branch]}"
|
295
|
+
@scribe.should_not_receive(:shell_out!).with(pull_command,
|
296
|
+
:cwd => @scribe.config[:chronicle_path])
|
297
|
+
@scribe.pull
|
298
|
+
end
|
299
|
+
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
describe "#commit" do
|
304
|
+
before(:each) do
|
305
|
+
@command_response = double('shell_out')
|
306
|
+
@command_response.stub(:exitstatus) { 0 }
|
307
|
+
@command_response.stub(:stdout) { "" }
|
308
|
+
@scribe.config[:commit_message] = "Commit message at %TIME%"
|
309
|
+
end
|
310
|
+
|
311
|
+
it "adds all files prior to commit" do
|
312
|
+
expected_command = "git add ."
|
313
|
+
@scribe.should_receive(:shell_out!).with(expected_command,
|
314
|
+
:cwd => @scribe.config[:chronicle_path]).and_return(@command_response)
|
315
|
+
pull_command = "git pull remote_name branch_name"
|
316
|
+
@scribe.stub(:shell_out!)
|
317
|
+
@scribe.commit
|
318
|
+
end
|
319
|
+
|
320
|
+
it "commits all changes" do
|
321
|
+
expected_command = "git commit -m \"#{@scribe.config[:commit_message].gsub(/%TIME%/, Time.now.to_s)}\""
|
322
|
+
@scribe.stub(:shell_out!)
|
323
|
+
@scribe.should_receive(:shell_out!).with(expected_command,
|
324
|
+
:cwd => @scribe.config[:chronicle_path],
|
325
|
+
:returns => [0, 1]).and_return(@command_response)
|
326
|
+
@scribe.commit
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
describe "#push" do
|
331
|
+
it "pushes to the remote repository" do
|
332
|
+
push_command = "git push #{@scribe.config[:remote_name]} #{@scribe.config[:branch]}"
|
333
|
+
@scribe.should_receive(:shell_out!).with(push_command,
|
334
|
+
:cwd => @scribe.config[:chronicle_path])
|
335
|
+
@scribe.push
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
describe "#fetch_configs" do
|
340
|
+
before(:each) do
|
341
|
+
@scribe.stub(:fetch_environments)
|
342
|
+
@scribe.stub(:fetch_roles)
|
343
|
+
@scribe.stub(:fetch_nodes)
|
344
|
+
end
|
345
|
+
|
346
|
+
it "fetches environment configs" do
|
347
|
+
@scribe.should_receive(:fetch_environments)
|
348
|
+
@scribe.fetch_configs
|
349
|
+
end
|
350
|
+
|
351
|
+
it "fetches roles configs" do
|
352
|
+
@scribe.should_receive(:fetch_roles)
|
353
|
+
@scribe.fetch_configs
|
354
|
+
end
|
355
|
+
|
356
|
+
it "fetches nodes configs" do
|
357
|
+
@scribe.should_receive(:fetch_nodes)
|
358
|
+
@scribe.fetch_configs
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
describe "#fetch_environments" do
|
363
|
+
before(:each) do
|
364
|
+
@environment1 = { :test1 => :value1 }
|
365
|
+
@environment1.stub(:name) { "env_name1" }
|
366
|
+
@environment2 = { :test2 => :value2 }
|
367
|
+
@environment2.stub(:name) { "env_name2" }
|
368
|
+
Chef::Environment.stub(:list) { { @environment1.name => @environment1, @environment2.name => @environment2 } }
|
369
|
+
end
|
370
|
+
|
371
|
+
it "saves each env to a file" do
|
372
|
+
@scribe.should_receive(:save_to_file).with("environments", @environment1.name, @environment1)
|
373
|
+
@scribe.should_receive(:save_to_file).with("environments", @environment2.name, @environment2)
|
374
|
+
@scribe.fetch_environments
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
describe "#fetch_roles" do
|
379
|
+
before(:each) do
|
380
|
+
@role1 = { :test1 => :value1 }
|
381
|
+
@role1.stub(:name) { "role_name1" }
|
382
|
+
@role2 = { :test2 => :value2 }
|
383
|
+
@role2.stub(:name) { "role_name2" }
|
384
|
+
Chef::Role.stub(:list) { { @role1.name => @role1, @role2.name => @role2 } }
|
385
|
+
end
|
386
|
+
|
387
|
+
it "saves each role to a file" do
|
388
|
+
@scribe.should_receive(:save_to_file).with("roles", @role1.name, @role1)
|
389
|
+
@scribe.should_receive(:save_to_file).with("roles", @role2.name, @role2)
|
390
|
+
@scribe.fetch_roles
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
describe "#fetch_nodes" do
|
395
|
+
before(:each) do
|
396
|
+
@node1 = { :test1 => :value1 }
|
397
|
+
@node1.stub(:name) { "node_name1" }
|
398
|
+
@node1.stub(:chef_environment) { "chef_environment1" }
|
399
|
+
@node1.stub(:normal_attrs) { { :attr1 => "val1" } }
|
400
|
+
@node1.stub(:run_list) { ["cookbook1", "cookbook2"] }
|
401
|
+
@serialized_node1 = {"name" => @node1.name, "env" => @node1.chef_environment, "attribiutes" => @node1.normal_attrs, "run_list" => @node1.run_list}
|
402
|
+
@node2 = { :test2 => :value2 }
|
403
|
+
@node2.stub(:name) { "node_name2" }
|
404
|
+
@node2.stub(:chef_environment) { "chef_environment2" }
|
405
|
+
@node2.stub(:normal_attrs) { { :attrA => "valA" } }
|
406
|
+
@node2.stub(:run_list) { ["cookbookA", "cookbookB"] }
|
407
|
+
@serialized_node2 = {"name" => @node2.name, "env" => @node2.chef_environment, "attribiutes" => @node2.normal_attrs, "run_list" => @node2.run_list}
|
408
|
+
Chef::Node.stub(:list) { { @node1.name => @node1, @node2.name => @node2 } }
|
409
|
+
end
|
410
|
+
|
411
|
+
it "saves each node to a file" do
|
412
|
+
@scribe.should_receive(:save_to_file).with("nodes", @node1.name, @serialized_node1)
|
413
|
+
@scribe.should_receive(:save_to_file).with("nodes", @node2.name, @serialized_node2)
|
414
|
+
@scribe.fetch_nodes
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
describe "#save_to_file" do
|
419
|
+
before(:each) do
|
420
|
+
@f1 = double()
|
421
|
+
@f1.stub(:write)
|
422
|
+
@data = { :test_key2 => "test_value2", :test_key2 => "test_value2"}
|
423
|
+
end
|
424
|
+
|
425
|
+
it "saves deeply sorted data into a specific file in a specific directory" do
|
426
|
+
File.should_receive(:open).with(File.join(@scribe.config[:chronicle_path], "dir", "name.json"), "w").and_yield(@f1)
|
427
|
+
@scribe.should_receive(:deep_sort).with(@data).and_return({:sorted => "data"})
|
428
|
+
@f1.should_receive(:write).with(JSON.pretty_generate({:sorted => "data"}))
|
429
|
+
@scribe.save_to_file "dir", "name", @data
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
|
434
|
+
describe "#deep_sort" do
|
435
|
+
describe "when it gets a hash as a parameter" do
|
436
|
+
it "sorts the hash" do
|
437
|
+
sorted_hash = @scribe.deep_sort({:c => 3, :a => 1, :x => 0, :d => -2})
|
438
|
+
sorted_values = [[:a, 1], [:c,3], [:d,-2], [:x,0]]
|
439
|
+
i = 0
|
440
|
+
sorted_hash.each do |key, value|
|
441
|
+
key.should eql(sorted_values[i][0])
|
442
|
+
value.should eql(sorted_values[i][1])
|
443
|
+
i +=1
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
it "calls itself recursively with each value" do
|
448
|
+
hash_to_sort = {:g => 3, :b => 1, :z => 0, :h => -2}
|
449
|
+
@scribe.should_receive(:deep_sort).with(hash_to_sort).and_call_original
|
450
|
+
hash_to_sort.values.each {|value| @scribe.should_receive(:deep_sort).with(value)}
|
451
|
+
@scribe.deep_sort(hash_to_sort)
|
452
|
+
end
|
453
|
+
|
454
|
+
it "returns a deep sorted hash" do
|
455
|
+
hash_to_sort = {"zz" => { "z" => 0, "h" => -2}}
|
456
|
+
@scribe.deep_sort(hash_to_sort).should eql({"zz" => { "h" => -2, "z" => 0}})
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
describe "when it gets a simple array as a parameter" do
|
461
|
+
it "doesn't sort the array" do
|
462
|
+
array = [3, 1, 0, -2]
|
463
|
+
sorted_hash = @scribe.deep_sort(array)
|
464
|
+
sorted_hash.each_with_index do |value, index|
|
465
|
+
value.should eql(array[index])
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
it "calls itself recursively with each value" do
|
470
|
+
array = [3, 1, 0, -2]
|
471
|
+
@scribe.should_receive(:deep_sort).with(array).and_call_original
|
472
|
+
array.each {|value| @scribe.should_receive(:deep_sort).with(value)}
|
473
|
+
@scribe.deep_sort(array)
|
474
|
+
end
|
475
|
+
|
476
|
+
it "returns a deep sorted array" do
|
477
|
+
hash_to_sort = [{ "u" => 0, "h" => -2 }, { "u" => "test", "d" => -100 }]
|
478
|
+
@scribe.deep_sort(hash_to_sort).should eql([{ "h" => -2, "u" => 0 }, { "d" => -100, "u" => "test" }])
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
describe "when it gets something that's not a hash or an array as a prameter" do
|
483
|
+
it "returns the input param" do
|
484
|
+
str = "test"
|
485
|
+
@scribe.deep_sort(str).should equal(str)
|
486
|
+
@scribe.deep_sort(1).should equal(1)
|
487
|
+
@scribe.deep_sort(true).should equal(true)
|
488
|
+
@scribe.deep_sort(nil).should eql(nil)
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|