clc-promote 0.4.5 → 0.7.8
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.
- checksums.yaml +4 -4
- data/README.md +18 -8
- data/Rakefile +3 -0
- data/clc-promote.gemspec +3 -2
- data/lib/chef/knife/promote.rb +46 -17
- data/lib/kitchen/provisioner/environment.rb +1 -1
- data/lib/promote.rb +3 -2
- data/lib/promote/config.rb +11 -2
- data/lib/promote/cookbook.rb +17 -5
- data/lib/promote/git_repo.rb +22 -1
- data/lib/promote/node_finder.rb +18 -0
- data/lib/promote/promoter.rb +37 -12
- data/lib/promote/rake_tasks.rb +63 -18
- data/lib/promote/role_file.rb +26 -0
- data/lib/promote/uploader.rb +45 -13
- data/lib/promote/version.rb +2 -2
- data/lib/promote/versioner.rb +44 -9
- data/spec/unit/promote/config_spec.rb +70 -18
- data/spec/unit/promote/promoter_spec.rb +51 -8
- data/spec/unit/promote/uploader_spec.rb +97 -22
- data/spec/unit/promote/versioner_spec.rb +151 -16
- metadata +26 -4
@@ -1,12 +1,15 @@
|
|
1
1
|
require 'promote'
|
2
2
|
|
3
3
|
describe Promote::Promoter do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
let(:config) { Promote::Config.new({
|
5
|
+
:node_name => 'user',
|
6
|
+
:cookbook_directory => '/cookbooks',
|
7
|
+
:client_key => 'key',
|
8
|
+
:chef_server_url => 'https://some.chef.server'}) }
|
9
|
+
|
10
|
+
subject { Promote::Promoter.new(config) }
|
11
|
+
|
12
|
+
context "promote_to" do
|
10
13
|
let(:fake_file){double('file')}
|
11
14
|
let(:env1) do
|
12
15
|
<<-EOS
|
@@ -43,8 +46,6 @@ describe Promote::Promoter do
|
|
43
46
|
allow(File).to receive(:open).with(/env2\.json$/, "w").and_yield(fake_file)
|
44
47
|
}
|
45
48
|
|
46
|
-
subject { Promote::Promoter.new(config) }
|
47
|
-
|
48
49
|
it "copies the cookbook constraints" do
|
49
50
|
expect(fake_file).to receive(:<<).with(an_instance_of(String)) do |arg|
|
50
51
|
parsed = JSON.parse(arg)
|
@@ -56,4 +57,46 @@ describe Promote::Promoter do
|
|
56
57
|
subject.promote_to("env1", "env2")
|
57
58
|
end
|
58
59
|
end
|
60
|
+
|
61
|
+
context "monitor_promotion" do
|
62
|
+
let(:finder_good){ double('node_finder', :search => [good_node]) }
|
63
|
+
let(:finder_bad){ double('node_finder', :search => [bad_node]) }
|
64
|
+
let (:good_node) {
|
65
|
+
node = Chef::Node.new
|
66
|
+
node.default["ohai_time"] = Time.now.to_i + 3600
|
67
|
+
node
|
68
|
+
}
|
69
|
+
let (:bad_node) {
|
70
|
+
node = Chef::Node.new
|
71
|
+
node.default["ohai_time"] = Time.now.to_i - 3600
|
72
|
+
node
|
73
|
+
}
|
74
|
+
|
75
|
+
before {
|
76
|
+
allow(Promote::NodeFinder).to receive(:new).and_return(finder_good)
|
77
|
+
}
|
78
|
+
|
79
|
+
context "all environments succeed" do
|
80
|
+
it "promotes all nodes" do
|
81
|
+
expect(subject).to receive(:promote_to).with("env1", "env2", nil)
|
82
|
+
expect(subject).to receive(:promote_to).with("env1", "env3", nil)
|
83
|
+
expect(subject).to receive(:promote_to).with("env1", "env4", nil)
|
84
|
+
subject.monitor_promotion("env1", ["env2", "env3", "env4"], 1)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "stops promotion when promotion fails" do
|
89
|
+
before {
|
90
|
+
allow(Promote::NodeFinder).to receive(:new).with("chef_environment:env3", config).and_return(finder_bad)
|
91
|
+
}
|
92
|
+
|
93
|
+
it "stops on failure" do
|
94
|
+
|
95
|
+
expect(subject).to receive(:promote_to).with("env1", "env2", nil)
|
96
|
+
expect(subject).not_to receive(:promote_to).with("env1", "env3", nil)
|
97
|
+
expect(subject).not_to receive(:promote_to).with("env1", "env4", nil)
|
98
|
+
subject.monitor_promotion("env1", ["env2", "env3", "env4"], 1)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
59
102
|
end
|
@@ -4,15 +4,19 @@ require_relative '../support/dummy_metadata'
|
|
4
4
|
describe Promote::Uploader do
|
5
5
|
let(:knife_config) {{ :cookbook_path => "path"}}
|
6
6
|
let(:temp_dir) { "/tmp/berks" }
|
7
|
-
let(:config) { Promote::Config.new({
|
8
|
-
:node_name => 'user',
|
7
|
+
let(:config) { Promote::Config.new({
|
8
|
+
:node_name => 'user',
|
9
9
|
:cookbook_directory => '/cookbooks',
|
10
|
-
:client_key => 'key',
|
10
|
+
:client_key => 'key',
|
11
11
|
:temp_directory => temp_dir,
|
12
12
|
:chef_server_url => 'https://some.chef.server'}) }
|
13
13
|
|
14
14
|
subject { Promote::Uploader.new(config) }
|
15
15
|
|
16
|
+
before {
|
17
|
+
allow(Chef::ChefFS::FileSystem).to receive(:copy_to)
|
18
|
+
}
|
19
|
+
|
16
20
|
context "upload cookbooks" do
|
17
21
|
let(:env_name) { "QA1" }
|
18
22
|
let(:metadata) { PromoteSpecs::DummyMetadata.new({'version' => "1.1.1"}) }
|
@@ -50,6 +54,7 @@ describe Promote::Uploader do
|
|
50
54
|
}}
|
51
55
|
let(:rest){double('rest')}
|
52
56
|
let(:knife) { instance_double('CookbookUpload', :run => nil) }
|
57
|
+
|
53
58
|
before {
|
54
59
|
allow(File).to receive(:read).with(File.join(config.environment_directory, "#{env_name}.json")).and_return(environment)
|
55
60
|
allow(File).to receive(:read).with(/metadata\.json$/).and_return('')
|
@@ -59,6 +64,7 @@ describe Promote::Uploader do
|
|
59
64
|
allow(Chef::Knife::CookbookUpload).to receive(:new).and_return(knife)
|
60
65
|
allow(Dir).to receive(:glob).with(File.expand_path("~/.berkshelf/cookbooks/*")).and_return(berks_cookbooks)
|
61
66
|
allow(Dir).to receive(:glob).with(File.join(config.cookbook_directory, "*")).and_return(internal_cookbooks)
|
67
|
+
allow(Dir).to receive(:glob).with(File.join(config.temp_directory, "*")).and_return(internal_cookbooks)
|
62
68
|
allow(Dir).to receive(:mkdir)
|
63
69
|
allow(Dir).to receive(:exist?).and_return(false)
|
64
70
|
allow(knife).to receive(:config).and_return(knife_config)
|
@@ -117,7 +123,7 @@ describe Promote::Uploader do
|
|
117
123
|
context "temp directory already exists" do
|
118
124
|
before {allow(Dir).to receive(:exist?).and_return(true)}
|
119
125
|
|
120
|
-
it "deletes temp directory" do
|
126
|
+
it "deletes temp directory" do
|
121
127
|
expect(FileUtils).to receive(:rm_rf).with(config.temp_directory)
|
122
128
|
subject.upload_cookbooks(env_name)
|
123
129
|
end
|
@@ -126,7 +132,7 @@ describe Promote::Uploader do
|
|
126
132
|
context "no metadata.rb file exists for cookbook" do
|
127
133
|
before {allow(File).to receive(:exist?).with(/rb$/).and_return(false)}
|
128
134
|
|
129
|
-
it "loads json instead of ruby file" do
|
135
|
+
it "loads json instead of ruby file" do
|
130
136
|
expect(metadata).to receive(:from_json).at_least(1).times
|
131
137
|
expect(metadata).not_to receive(:from_file)
|
132
138
|
subject.upload_cookbooks(env_name)
|
@@ -137,7 +143,7 @@ describe Promote::Uploader do
|
|
137
143
|
let(:berks_cookbooks) {[]}
|
138
144
|
let(:internal_cookbooks) {[]}
|
139
145
|
|
140
|
-
it "does not call knife" do
|
146
|
+
it "does not call knife" do
|
141
147
|
expect(Chef::Knife::CookbookUpload).not_to receive(:new)
|
142
148
|
|
143
149
|
subject.upload_cookbooks(env_name)
|
@@ -145,31 +151,31 @@ describe Promote::Uploader do
|
|
145
151
|
end
|
146
152
|
|
147
153
|
context "config missing node_name" do
|
148
|
-
let(:config) { Promote::Config.new({
|
149
|
-
:client_key => 'key',
|
154
|
+
let(:config) { Promote::Config.new({
|
155
|
+
:client_key => 'key',
|
150
156
|
:chef_server_url => 'https://some.chef.server'}) }
|
151
157
|
|
152
|
-
it "raises error that node_name is missing" do
|
158
|
+
it "raises error that node_name is missing" do
|
153
159
|
expect{subject.upload_cookbooks(env_name)}.to raise_error(/node_name/)
|
154
160
|
end
|
155
161
|
end
|
156
162
|
|
157
163
|
context "config missing client_key" do
|
158
|
-
let(:config) { Promote::Config.new({
|
159
|
-
:node_name => 'user',
|
164
|
+
let(:config) { Promote::Config.new({
|
165
|
+
:node_name => 'user',
|
160
166
|
:chef_server_url => 'https://some.chef.server'}) }
|
161
167
|
|
162
|
-
it "raises error that client_key is missing" do
|
168
|
+
it "raises error that client_key is missing" do
|
163
169
|
expect{subject.upload_cookbooks(env_name)}.to raise_error(/client_key/)
|
164
170
|
end
|
165
171
|
end
|
166
172
|
|
167
173
|
context "config missing chef_server_url" do
|
168
|
-
let(:config) { Promote::Config.new({
|
169
|
-
:node_name => 'user',
|
174
|
+
let(:config) { Promote::Config.new({
|
175
|
+
:node_name => 'user',
|
170
176
|
:client_key => 'key'}) }
|
171
177
|
|
172
|
-
it "raises error that chef_server_url is missing" do
|
178
|
+
it "raises error that chef_server_url is missing" do
|
173
179
|
expect{subject.upload_cookbooks(env_name)}.to raise_error(/chef_server_url/)
|
174
180
|
end
|
175
181
|
end
|
@@ -178,7 +184,7 @@ describe Promote::Uploader do
|
|
178
184
|
context "upload json artifacts" do
|
179
185
|
context "upload an environment" do
|
180
186
|
let(:env_name) { "my_test" }
|
181
|
-
|
187
|
+
|
182
188
|
it "uploads the environment" do
|
183
189
|
expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(an_instance_of(Chef::ChefFS::FilePattern), anything(), anything(), anything(), anything()) do |arg|
|
184
190
|
expect(arg.pattern).to eq(File.join("/environments", "#{env_name}.json"))
|
@@ -189,18 +195,87 @@ describe Promote::Uploader do
|
|
189
195
|
|
190
196
|
context "upload all environments" do
|
191
197
|
it "uploads the environment" do
|
192
|
-
|
193
|
-
|
198
|
+
local_environments = Chef::ChefFS::Config.new.local_fs.child_paths["environments"]
|
199
|
+
|
200
|
+
expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
|
201
|
+
an_instance_of(Chef::ChefFS::FilePattern),
|
202
|
+
an_instance_of(Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
|
203
|
+
anything(),
|
204
|
+
anything(),
|
205
|
+
anything()
|
206
|
+
) do |file_pattern, source|
|
207
|
+
expect(file_pattern.pattern).to eq(File.join("/environments/*.json"))
|
208
|
+
expect(source.child_paths["environments"]).to eq(local_environments)
|
194
209
|
end
|
195
210
|
subject.upload_environments
|
196
211
|
end
|
197
212
|
end
|
198
213
|
|
199
|
-
context "upload
|
200
|
-
it "uploads the
|
201
|
-
|
202
|
-
|
214
|
+
context "upload all roles" do
|
215
|
+
it "uploads the role" do
|
216
|
+
local_roles = Chef::ChefFS::Config.new.local_fs.child_paths["roles"]
|
217
|
+
|
218
|
+
expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
|
219
|
+
an_instance_of(Chef::ChefFS::FilePattern),
|
220
|
+
an_instance_of(Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
|
221
|
+
anything(),
|
222
|
+
anything(),
|
223
|
+
anything()
|
224
|
+
) do |file_pattern, source|
|
225
|
+
expect(file_pattern.pattern).to eq(File.join("/roles/*.json"))
|
226
|
+
expect(source.child_paths["roles"]).to eq(local_roles)
|
227
|
+
end
|
228
|
+
subject.upload_roles
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
context "upload_data_bags" do
|
233
|
+
let(:temp_data_bags) { File.join(config.temp_directory, "data_bags") }
|
234
|
+
let(:fake_bag_file) { File.join("bags", "bag.json") }
|
235
|
+
let(:secret_key_file) { File.join("bags", "bag_secrets_keys.json") }
|
236
|
+
let(:config) { Promote::Config.new({
|
237
|
+
:temp_directory => "/tmp/promote_tests",
|
238
|
+
:repo_root => "/tmp/promote_repo",
|
239
|
+
:node_name => 'user',
|
240
|
+
:client_key => 'key',
|
241
|
+
:chef_server_url => 'https://some.chef.server'}) }
|
242
|
+
|
243
|
+
before {
|
244
|
+
fake_bag_path = File.join(config.data_bag_directory, fake_bag_file)
|
245
|
+
FileUtils.mkdir_p(File.dirname(fake_bag_path))
|
246
|
+
FileUtils.touch(fake_bag_path)
|
247
|
+
FileUtils.touch(File.join(config.data_bag_directory, secret_key_file))
|
248
|
+
}
|
249
|
+
|
250
|
+
after {
|
251
|
+
FileUtils.rm_rf(config.temp_directory)
|
252
|
+
FileUtils.rm_rf(config.repo_root)
|
253
|
+
}
|
254
|
+
|
255
|
+
it "copies the data_bags to a temp folder" do
|
256
|
+
subject.upload_data_bags
|
257
|
+
|
258
|
+
expect(File).to exist(File.join(temp_data_bags, fake_bag_file))
|
259
|
+
end
|
260
|
+
|
261
|
+
it "does not copy key files" do
|
262
|
+
subject.upload_data_bags
|
263
|
+
|
264
|
+
expect(File).not_to exist(File.join(temp_data_bags, secret_key_file))
|
265
|
+
end
|
266
|
+
|
267
|
+
it "uploads the data_bags to chef" do
|
268
|
+
expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
|
269
|
+
an_instance_of(Chef::ChefFS::FilePattern),
|
270
|
+
an_instance_of(Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
|
271
|
+
anything(),
|
272
|
+
anything(),
|
273
|
+
anything()
|
274
|
+
) do |file_pattern, source|
|
275
|
+
expect(file_pattern.pattern).to eq("/data_bags/**/*.json")
|
276
|
+
expect(source.child_paths["data_bags"]).to eq([temp_data_bags])
|
203
277
|
end
|
278
|
+
|
204
279
|
subject.upload_data_bags
|
205
280
|
end
|
206
281
|
end
|
@@ -57,8 +57,8 @@ describe Promote::Versioner do
|
|
57
57
|
|
58
58
|
context 'version_cookbooks' do
|
59
59
|
let(:cookbooks) {[
|
60
|
-
File.join(subject.config.cookbook_directory, "cookbook1"),
|
61
|
-
File.join(subject.config.cookbook_directory, "cookbook2"),
|
60
|
+
File.join(subject.config.cookbook_directory, "cookbook1"),
|
61
|
+
File.join(subject.config.cookbook_directory, "cookbook2"),
|
62
62
|
File.join(subject.config.cookbook_directory, "cookbook3")
|
63
63
|
]}
|
64
64
|
before {
|
@@ -171,6 +171,120 @@ describe Promote::Versioner do
|
|
171
171
|
end
|
172
172
|
end
|
173
173
|
|
174
|
+
context 'version_role' do
|
175
|
+
before {
|
176
|
+
regex = File.join(config.role_directory,'test.json')
|
177
|
+
allow(File).to receive(:read).with(regex).and_return(artifact_file)
|
178
|
+
allow(File).to receive(:open).with(regex, "w").and_yield(fake_file)
|
179
|
+
}
|
180
|
+
|
181
|
+
context 'when versioning a new role with no version' do
|
182
|
+
let(:artifact_file) do
|
183
|
+
<<-EOS
|
184
|
+
{
|
185
|
+
"name": "QA1",
|
186
|
+
"chef_type": "role",
|
187
|
+
"json_class": "Chef::Role",
|
188
|
+
"override_attributes": {
|
189
|
+
"foo": "bar"
|
190
|
+
}
|
191
|
+
}
|
192
|
+
EOS
|
193
|
+
end
|
194
|
+
it "writes the new version and sha to the file" do
|
195
|
+
parsed = JSON.parse(artifact_file)
|
196
|
+
parsed['override_attributes']['version'] = '1.2.2'
|
197
|
+
parsed['override_attributes']['sha1'] = 'aaa'
|
198
|
+
expect(fake_file).to receive(:<<).with(JSON.pretty_generate(parsed))
|
199
|
+
subject.version_role('test')
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
context 'when versioning a role with no override_attributes' do
|
204
|
+
let(:artifact_file) do
|
205
|
+
<<-EOS
|
206
|
+
{
|
207
|
+
"name": "QA1",
|
208
|
+
"chef_type": "role",
|
209
|
+
"json_class": "Chef::Role"
|
210
|
+
}
|
211
|
+
EOS
|
212
|
+
end
|
213
|
+
it "adds an override_attributes key to the role" do
|
214
|
+
parsed = JSON.parse(artifact_file)
|
215
|
+
override_hash = { "override_attributes" => {} }
|
216
|
+
parsed.merge!(override_hash)
|
217
|
+
expect(fake_file).to receive(:<<).with(JSON.pretty_generate(parsed))
|
218
|
+
subject.version_role('test')
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context 'when versioning a new role with old version' do
|
223
|
+
|
224
|
+
let(:artifact_file) do
|
225
|
+
<<-EOS
|
226
|
+
{
|
227
|
+
"name": "QA1",
|
228
|
+
"chef_type": "role",
|
229
|
+
"json_class": "Chef::Role",
|
230
|
+
"override_attributes": {
|
231
|
+
"foo": "bar",
|
232
|
+
"version": "1.0.0",
|
233
|
+
"sha1": "ccc"
|
234
|
+
}
|
235
|
+
}
|
236
|
+
EOS
|
237
|
+
end
|
238
|
+
|
239
|
+
it "writes the new version and sha to the file" do
|
240
|
+
parsed = JSON.parse(artifact_file)
|
241
|
+
parsed['override_attributes']['version'] = '1.2.2'
|
242
|
+
parsed['override_attributes']['sha1'] = 'aaa'
|
243
|
+
expect(fake_file).to receive(:<<).with(JSON.pretty_generate(parsed))
|
244
|
+
subject.version_role('test')
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'when committing a role with no changes' do
|
249
|
+
let(:artifact_file) do
|
250
|
+
<<-EOS
|
251
|
+
{
|
252
|
+
"name": "QA1",
|
253
|
+
"chef_type": "role",
|
254
|
+
"json_class": "Chef::Role",
|
255
|
+
"override_attributes": {
|
256
|
+
"foo": "bar",
|
257
|
+
"version": "1.2.2",
|
258
|
+
"sha1": "aaa"
|
259
|
+
}
|
260
|
+
}
|
261
|
+
EOS
|
262
|
+
end
|
263
|
+
|
264
|
+
it "does not write to the file" do
|
265
|
+
expect(fake_file).not_to receive(:<<)
|
266
|
+
subject.version_role('test')
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
context 'version_roles' do
|
272
|
+
let(:roles) {%w{dir/role1.json dir/role2.json dir/role3.json}}
|
273
|
+
before {
|
274
|
+
allow(subject).to receive(:version_role)
|
275
|
+
allow(Dir).to receive(:glob).with(
|
276
|
+
File.join(subject.config.role_directory, "*.json")).and_return(roles)
|
277
|
+
}
|
278
|
+
|
279
|
+
it "versions each role" do
|
280
|
+
roles.each do |role|
|
281
|
+
expect(subject).to receive(:version_role).with(
|
282
|
+
File.basename(role ,File.extname(role)))
|
283
|
+
end
|
284
|
+
subject.version_roles
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
174
288
|
context 'constrain_environment' do
|
175
289
|
before {
|
176
290
|
regex = File.join(config.environment_directory,'test.json')
|
@@ -232,59 +346,80 @@ describe Promote::Versioner do
|
|
232
346
|
let(:artifact_file) do
|
233
347
|
<<-EOS
|
234
348
|
{
|
235
|
-
"name": "
|
349
|
+
"name": "LKG",
|
350
|
+
"chef_type": "environment",
|
351
|
+
"json_class": "Chef::Environment",
|
352
|
+
"cookbook_versions": {
|
353
|
+
"cookbook1": "1.1.1.hash",
|
354
|
+
"cookbook2": "1.1.1.hash",
|
355
|
+
"cookbook3": "3.3.3.hash"
|
356
|
+
}
|
357
|
+
}
|
358
|
+
EOS
|
359
|
+
end
|
360
|
+
|
361
|
+
it "returns dirty" do
|
362
|
+
expect(subject.is_dirty('new', 'test', 'cookbook2', 'hash')).to be(true)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
context "cookbook has same version but different hash" do
|
366
|
+
|
367
|
+
let(:artifact_file) do
|
368
|
+
<<-EOS
|
369
|
+
{
|
370
|
+
"name": "LKG",
|
236
371
|
"chef_type": "environment",
|
237
372
|
"json_class": "Chef::Environment",
|
238
373
|
"cookbook_versions": {
|
239
|
-
"cookbook1": "1.1.1",
|
240
|
-
"cookbook2": "
|
241
|
-
"cookbook3": "3.3.3"
|
374
|
+
"cookbook1": "1.1.1.hash",
|
375
|
+
"cookbook2": "2.2.2.diff_hash",
|
376
|
+
"cookbook3": "3.3.3.hash"
|
242
377
|
}
|
243
378
|
}
|
244
379
|
EOS
|
245
380
|
end
|
246
381
|
|
247
382
|
it "returns dirty" do
|
248
|
-
expect(subject.is_dirty('new', 'test', 'cookbook2')).to be(true)
|
383
|
+
expect(subject.is_dirty('new', 'test', 'cookbook2', 'hash')).to be(true)
|
249
384
|
end
|
250
385
|
end
|
251
386
|
context "cookbook is not dirty" do
|
252
387
|
let(:artifact_file) do
|
253
388
|
<<-EOS
|
254
389
|
{
|
255
|
-
"name": "
|
390
|
+
"name": "LKG",
|
256
391
|
"chef_type": "environment",
|
257
392
|
"json_class": "Chef::Environment",
|
258
393
|
"cookbook_versions": {
|
259
|
-
"cookbook1": "1.1.1",
|
260
|
-
"cookbook2": "2.2.2",
|
261
|
-
"cookbook3": "3.3.3"
|
394
|
+
"cookbook1": "1.1.1.hash",
|
395
|
+
"cookbook2": "2.2.2.hash",
|
396
|
+
"cookbook3": "3.3.3.hash"
|
262
397
|
}
|
263
398
|
}
|
264
399
|
EOS
|
265
400
|
end
|
266
401
|
|
267
402
|
it "returns clean" do
|
268
|
-
expect(subject.is_dirty('new', 'test', 'cookbook2')).to be(false)
|
403
|
+
expect(subject.is_dirty('new', 'test', 'cookbook2', 'hash')).to be(false)
|
269
404
|
end
|
270
405
|
end
|
271
406
|
context "cookbook is new to environment" do
|
272
407
|
let(:artifact_file) do
|
273
408
|
<<-EOS
|
274
409
|
{
|
275
|
-
"name": "
|
410
|
+
"name": "LKG",
|
276
411
|
"chef_type": "environment",
|
277
412
|
"json_class": "Chef::Environment",
|
278
413
|
"cookbook_versions": {
|
279
|
-
"cookbook1": "1.1.1",
|
280
|
-
"cookbook3": "3.3.3"
|
414
|
+
"cookbook1": "1.1.1.hash",
|
415
|
+
"cookbook3": "3.3.3.hash"
|
281
416
|
}
|
282
417
|
}
|
283
418
|
EOS
|
284
419
|
end
|
285
420
|
|
286
421
|
it "returns dirty" do
|
287
|
-
expect(subject.is_dirty('new', 'test', 'cookbook2')).to be(true)
|
422
|
+
expect(subject.is_dirty('new', 'test', 'cookbook2', 'hash')).to be(true)
|
288
423
|
end
|
289
424
|
end
|
290
425
|
end
|