clc-promote 0.8.7 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,18 +1,21 @@
1
1
  require 'promote'
2
2
 
3
3
  describe Promote::Promoter do
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'}) }
4
+ let(:config) do
5
+ Promote::Config.new(
6
+ node_name: 'user',
7
+ cookbook_directory: '/cookbooks',
8
+ client_key: 'key',
9
+ chef_server_url: 'https://some.chef.server'
10
+ )
11
+ end
9
12
 
10
13
  let(:ui) { Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {}) }
11
14
 
12
15
  subject { Promote::Promoter.new(config) }
13
16
 
14
- context "promote_to" do
15
- let(:fake_file){double('file')}
17
+ context 'promote_to' do
18
+ let(:fake_file) { double('file') }
16
19
  let(:env1) do
17
20
  <<-EOS
18
21
  {
@@ -37,18 +40,21 @@ describe Promote::Promoter do
37
40
  "cookbook_versions": {
38
41
  "build-essential": "1.0.0",
39
42
  "platform_haproxy": "1.0.0"
40
- }
43
+ }
41
44
  }
42
45
  EOS
43
46
  end
44
47
 
45
- before {
46
- allow(File).to receive(:read).with(/env1\.json$/).and_return(env1)
47
- allow(File).to receive(:read).with(/env2\.json$/).and_return(env2)
48
- allow(File).to receive(:open).with(/env2\.json$/, "w").and_yield(fake_file)
49
- }
48
+ before do
49
+ allow(File).to receive(:read).with(/env1\.json$/)
50
+ .and_return(env1)
51
+ allow(File).to receive(:read).with(/env2\.json$/)
52
+ .and_return(env2)
53
+ allow(File).to receive(:open).with(/env2\.json$/, 'w')
54
+ .and_yield(fake_file)
55
+ end
50
56
 
51
- it "copies the cookbook constraints" do
57
+ it 'copies the cookbook constraints' do
52
58
  expect(fake_file).to receive(:<<).with(an_instance_of(String)) do |arg|
53
59
  parsed = JSON.parse(arg)
54
60
  expect(parsed['cookbook_versions'].length).to eq(3)
@@ -56,69 +62,100 @@ describe Promote::Promoter do
56
62
  expect(parsed['cookbook_versions']['newrelic']).to eq('2.0.0')
57
63
  expect(parsed['cookbook_versions']['platform_haproxy']).to eq('2.0.0')
58
64
  end
59
- subject.promote_to("env1", "env2")
65
+ subject.promote_to('env1', 'env2')
60
66
  end
61
67
  end
62
68
 
63
- context "monitor_promotion" do
64
- let(:finder_good){ double('node_finder', :search => [good_node]) }
65
- let(:finder_bad){ double('node_finder', :search => [bad_node]) }
66
- let (:good_node) {
69
+ context 'monitor_promotion' do
70
+ let(:finder_good) { double('node_finder', search: [good_node]) }
71
+ let(:finder_bad) { double('node_finder', search: [bad_node]) }
72
+ let(:good_node) do
67
73
  node = Chef::Node.new
68
- node.name "good_node"
69
- node.default["ohai_time"] = Time.now.to_i + 3600
74
+ node.name 'good_node'
75
+ node.default['ohai_time'] = Time.now.to_i + 3600
70
76
  node
71
- }
72
- let (:bad_node) {
77
+ end
78
+ let(:bad_node) do
73
79
  node = Chef::Node.new
74
- node.name "bad_node"
75
- node.default["ohai_time"] = Time.now.to_i - 3600
80
+ node.name 'bad_node'
81
+ node.default['ohai_time'] = Time.now.to_i - 3600
76
82
  node
77
- }
83
+ end
78
84
  let(:uploader) { double('uploader') }
79
85
  let(:ui) { nil }
80
86
 
81
- before {
87
+ before do
82
88
  allow(Promote::NodeFinder).to receive(:new).and_return(finder_good)
83
89
  allow(Promote::Uploader).to receive(:new).and_return(uploader)
84
- }
90
+ end
85
91
 
86
- context "all environments succeed" do
87
- it "promotes all nodes" do
88
- %w{env2 env3 env4}.each do |env|
89
- expect(subject).to receive(:promote_to).with("env1", env, ui)
92
+ context 'all environments succeed' do
93
+ it 'promotes all nodes' do
94
+ %w(env2 env3 env4).each do |env|
95
+ expect(subject).to receive(:promote_to).with('env1', env, ui)
90
96
  expect(uploader).to receive(:upload_environment).with(env, ui)
91
97
  end
92
- subject.monitor_promotion("env1", ["env2", "env3", "env4"], 0.25, false, 1, ui)
98
+ subject.monitor_promotion(
99
+ 'env1',
100
+ %w(env2 env3 env4),
101
+ 0.25,
102
+ false,
103
+ 1,
104
+ ui
105
+ )
93
106
  end
94
107
  end
95
108
 
96
- context "source environment does not fully converge" do
97
- before {
98
- allow(Promote::NodeFinder).to receive(:new).with("chef_environment:env1", config).and_return(finder_bad)
99
- }
109
+ context 'source environment does not fully converge' do
110
+ before do
111
+ allow(Promote::NodeFinder).to(
112
+ receive(:new).with('chef_environment:env1', config)
113
+ .and_return(finder_bad)
114
+ )
115
+ end
100
116
 
101
- it "promotes no nodes" do
117
+ it 'promotes no nodes' do
102
118
  expect(subject).not_to receive(:promote_to)
103
119
  expect(uploader).not_to receive(:upload_environment)
104
120
 
105
- expect{ subject.monitor_promotion("env1", ["env2", "env3", "env4"], 0.25, false, 1, ui) }.to raise_error(/env1$/)
121
+ expect do
122
+ subject.monitor_promotion(
123
+ 'env1',
124
+ %w(env2 env3 env4),
125
+ 0.25,
126
+ false,
127
+ 1,
128
+ ui
129
+ )
130
+ end.to raise_error(/env1$/)
106
131
  end
107
132
  end
108
133
 
109
- context "stops promotion when promotion fails" do
110
- before {
111
- allow(Promote::NodeFinder).to receive(:new).with("chef_environment:env3", config).and_return(finder_bad)
112
- }
134
+ context 'stops promotion when promotion fails' do
135
+ before do
136
+ allow(Promote::NodeFinder).to(
137
+ receive(:new).with('chef_environment:env3', config)
138
+ .and_return(finder_bad)
139
+ )
140
+ end
113
141
 
114
- it "stops on failure" do
115
- %w{env2 env3}.each do |env|
116
- expect(subject).to receive(:promote_to).with("env1", env, ui)
142
+ it 'stops on failure' do
143
+ %w(env2 env3).each do |env|
144
+ expect(subject).to receive(:promote_to).with('env1', env, ui)
117
145
  expect(uploader).to receive(:upload_environment).with(env, ui)
118
146
  end
119
- expect(subject).not_to receive(:promote_to).with("env1", "env4", ui)
120
- expect(uploader).not_to receive(:upload_environment).with("env4")
121
- expect{ subject.monitor_promotion("env1", ["env2", "env3", "env4"], 0.25, false, 1, ui) }.to raise_error(/env3$/)
147
+ expect(subject).not_to receive(:promote_to).with('env1', 'env4', ui)
148
+ expect(uploader).not_to receive(:upload_environment).with('env4')
149
+ expect do
150
+ subject.monitor_promotion(
151
+ 'env1',
152
+ %w(env2 env3 env4),
153
+ 0.25,
154
+ false,
155
+ 1,
156
+ ui
157
+ )
158
+ end.to raise_error(/env3$/)
122
159
  end
123
160
  end
124
161
  end
@@ -2,289 +2,289 @@ require 'promote'
2
2
  require_relative '../support/dummy_metadata'
3
3
 
4
4
  describe Promote::Uploader do
5
- let(:knife_config) {{ :cookbook_path => "path"}}
6
- let(:temp_dir) { "/tmp/berks" }
7
- let(:config) { Promote::Config.new({
8
- :node_name => 'user',
9
- :cookbook_directory => '/cookbooks',
10
- :client_key => 'key',
11
- :temp_directory => temp_dir,
12
- :chef_server_url => 'https://some.chef.server'}) }
13
-
14
- subject { Promote::Uploader.new(config) }
15
-
16
- before {
17
- Chef::Config[:chef_repo_path] = config.repo_root
18
- allow(Chef::ChefFS::FileSystem).to receive(:copy_to)
19
- }
20
-
21
- context "upload cookbooks" do
22
- let(:env_name) { "QA1" }
23
- let(:metadata) { PromoteSpecs::DummyMetadata.new({'version' => "1.1.1"}) }
24
- let(:environment) do
25
- <<-EOS
26
- {
27
- "name": "#{env_name}",
28
- "chef_type": "environment",
29
- "json_class": "Chef::Environment",
30
- "cookbook_versions": {
31
- "int_cookbook1": "1.1.1",
32
- "int_cookbook3": "1.1.1",
33
- "cookbook3": "3.3.3"
34
- }
35
- }
36
- EOS
37
- end
38
- let(:berks_cookbooks) {[
39
- "/berks/cookbook1-1.1.1",
40
- "/berks/cookbook1-1.1.2",
41
- "/berks/cookbook2-2.2.2",
42
- "/berks/cookbook3-3.3.3",
43
- "/berks/cookbook4-3.3.3",
44
- ]}
45
- let(:internal_cookbooks) {[
46
- "/cookbooks/int_cookbook1",
47
- "/cookbooks/int_cookbook2",
48
- "/cookbooks/int_cookbook3",
49
- ]}
50
- let(:server_cookbooks){{
51
- "cookbook1" => {"versions" => [{"version" => "1.1.1"}]},
52
- "cookbook2" => {"versions" => [{"version" => "1.1.1"}]},
53
- "int_cookbook1" => {"versions" => [{"version" => "1.1.1"}]},
54
- "int_cookbook2" => {"versions" => [{"version" => "2.2.2"}]}
55
- }}
56
- let(:rest){double('rest')}
57
- let(:knife) { instance_double('CookbookUpload', :run => nil) }
58
-
59
- before {
60
- allow(File).to receive(:read).with(File.join(config.environment_directory, "#{env_name}.json")).and_return(environment)
61
- allow(File).to receive(:read).with(/metadata\.json$/).and_return('')
62
- allow(Chef::REST).to receive(:new).and_return(rest)
63
- allow(rest).to receive(:get_rest).and_return(server_cookbooks)
64
- allow(Chef::Cookbook::Metadata).to receive(:new).and_return(metadata)
65
- allow(Chef::Knife::CookbookUpload).to receive(:new).and_return(knife)
66
- allow(Dir).to receive(:glob).with(File.expand_path("~/.berkshelf/cookbooks/*")).and_return(berks_cookbooks)
67
- allow(Dir).to receive(:glob).with(File.join(config.cookbook_directory, "*")).and_return(internal_cookbooks)
68
- allow(Dir).to receive(:glob).with(File.join(config.temp_directory, "*")).and_return(internal_cookbooks)
69
- allow(Dir).to receive(:mkdir)
70
- allow(Dir).to receive(:exist?).and_return(false)
71
- allow(knife).to receive(:config).and_return(knife_config)
72
- allow(FileUtils).to receive(:copy_entry)
73
- allow(File).to receive(:exist?).with(/metadata\.rb$/).and_return(true)
74
- }
75
-
76
- it "copies updated cookbooks to temp directory" do
77
- expect(FileUtils).not_to receive(:copy_entry).with("/berks/cookbook1-1.1.1", File.join(config.temp_directory, "cookbook1"))
78
- expect(FileUtils).not_to receive(:copy_entry).with("/berks/cookbook1-1.1.2", File.join(config.temp_directory, "cookbook1"))
79
- expect(FileUtils).not_to receive(:copy_entry).with("/berks/cookbook4-3.3.3", File.join(config.temp_directory, "cookbook4"))
80
- expect(FileUtils).not_to receive(:copy_entry).with("/berks/cookbook2-2.2.2", File.join(config.temp_directory, "cookbook2"))
81
- expect(FileUtils).to receive(:copy_entry).with("/berks/cookbook3-3.3.3", File.join(config.temp_directory, "cookbook3"))
82
- expect(FileUtils).not_to receive(:copy_entry).with("/cookbooks/int_cookbook2", File.join(config.temp_directory, "int_cookbook2"))
83
- expect(FileUtils).not_to receive(:copy_entry).with("/cookbooks/int_cookbook1", File.join(config.temp_directory, "int_cookbook1"))
84
- expect(FileUtils).to receive(:copy_entry).with("/cookbooks/int_cookbook3", File.join(config.temp_directory, "int_cookbook3"))
85
- subject.upload_cookbooks(env_name)
86
- end
87
- it "uploads cookbooks to chef server" do
88
- expect(knife).to receive(:run)
89
-
90
- subject.upload_cookbooks(env_name)
91
- end
92
- it "Creates temp directory" do
93
- expect(Dir).to receive(:mkdir).with(config.temp_directory)
94
-
95
- subject.upload_cookbooks(env_name)
96
- end
97
- it "uploads cookbooks from config temp path" do
98
- subject.upload_cookbooks(env_name)
99
- expect(knife.config[:cookbook_path]).to eq(config.temp_directory)
100
- end
101
- it "uploads all cookbooks" do
102
- subject.upload_cookbooks(env_name)
103
- expect(knife.config[:all]).to eq(true)
104
- end
105
- it "freezes all cookbooks" do
106
- subject.upload_cookbooks(env_name)
107
- expect(knife.config[:freeze]).to eq(true)
108
- end
109
-
110
- context "no environment is given" do
111
- it "copies updated cookbooks and does not filter by environment" do
112
- expect(FileUtils).not_to receive(:copy_entry).with("/berks/cookbook1-1.1.1", File.join(config.temp_directory, "cookbook1"))
113
- expect(FileUtils).to receive(:copy_entry).with("/berks/cookbook1-1.1.2", File.join(config.temp_directory, "cookbook1"))
114
- expect(FileUtils).to receive(:copy_entry).with("/berks/cookbook4-3.3.3", File.join(config.temp_directory, "cookbook4"))
115
- expect(FileUtils).to receive(:copy_entry).with("/berks/cookbook2-2.2.2", File.join(config.temp_directory, "cookbook2"))
116
- expect(FileUtils).to receive(:copy_entry).with("/berks/cookbook3-3.3.3", File.join(config.temp_directory, "cookbook3"))
117
- expect(FileUtils).to receive(:copy_entry).with("/cookbooks/int_cookbook2", File.join(config.temp_directory, "int_cookbook2"))
118
- expect(FileUtils).not_to receive(:copy_entry).with("/cookbooks/int_cookbook1", File.join(config.temp_directory, "int_cookbook1"))
119
- expect(FileUtils).to receive(:copy_entry).with("/cookbooks/int_cookbook3", File.join(config.temp_directory, "int_cookbook3"))
120
- subject.upload_cookbooks
121
- end
122
- end
123
-
124
- context "temp directory already exists" do
125
- before {allow(Dir).to receive(:exist?).and_return(true)}
126
-
127
- it "deletes temp directory" do
128
- expect(FileUtils).to receive(:rm_rf).with(config.temp_directory)
129
- subject.upload_cookbooks(env_name)
130
- end
131
- end
132
-
133
- context "no metadata.rb file exists for cookbook" do
134
- before {allow(File).to receive(:exist?).with(/rb$/).and_return(false)}
135
-
136
- it "loads json instead of ruby file" do
137
- expect(metadata).to receive(:from_json).at_least(1).times
138
- expect(metadata).not_to receive(:from_file)
139
- subject.upload_cookbooks(env_name)
140
- end
141
- end
142
-
143
- context "nothing to upload" do
144
- let(:berks_cookbooks) {[]}
145
- let(:internal_cookbooks) {[]}
146
-
147
- it "does not call knife" do
148
- expect(Chef::Knife::CookbookUpload).not_to receive(:new)
149
-
150
- subject.upload_cookbooks(env_name)
151
- end
152
- end
153
-
154
- context "config missing node_name" do
155
- let(:config) { Promote::Config.new({
156
- :client_key => 'key',
157
- :chef_server_url => 'https://some.chef.server'}) }
158
-
159
- it "raises error that node_name is missing" do
160
- expect{subject.upload_cookbooks(env_name)}.to raise_error(/node_name/)
161
- end
162
- end
163
-
164
- context "config missing client_key" do
165
- let(:config) { Promote::Config.new({
166
- :node_name => 'user',
167
- :chef_server_url => 'https://some.chef.server'}) }
168
-
169
- it "raises error that client_key is missing" do
170
- expect{subject.upload_cookbooks(env_name)}.to raise_error(/client_key/)
171
- end
172
- end
173
-
174
- context "config missing chef_server_url" do
175
- let(:config) { Promote::Config.new({
176
- :node_name => 'user',
177
- :client_key => 'key'}) }
178
-
179
- it "raises error that chef_server_url is missing" do
180
- expect{subject.upload_cookbooks(env_name)}.to raise_error(/chef_server_url/)
181
- end
182
- end
183
- end
184
-
185
- context "upload json artifacts" do
186
- context "upload an environment" do
187
- let(:env_name) { "my_test" }
188
-
189
- it "uploads the environment" do
190
- expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(an_instance_of(Chef::ChefFS::FilePattern), anything(), anything(), anything(), anything(), anything(), anything()) do |arg|
191
- expect(arg.pattern).to eq(File.join("/environments", "#{env_name}.json"))
192
- end
193
- subject.upload_environment(env_name)
194
- end
195
- end
196
-
197
- context "upload all environments" do
198
- it "uploads the environment" do
199
- local_environments = Chef::ChefFS::Config.new.local_fs.child_paths["environments"]
200
-
201
- expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
202
- an_instance_of(Chef::ChefFS::FilePattern),
203
- an_instance_of(Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
204
- anything(),
205
- anything(),
206
- anything(),
207
- anything(),
208
- anything()
209
- ) do |file_pattern, source|
210
- expect(file_pattern.pattern).to eq(File.join("/environments/*.json"))
211
- expect(source.child_paths["environments"]).to eq(local_environments)
212
- end
213
- subject.upload_environments
214
- end
215
- end
216
-
217
- context "upload all roles" do
218
- it "uploads the role" do
219
- local_roles = Chef::ChefFS::Config.new.local_fs.child_paths["roles"]
220
-
221
- expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
222
- an_instance_of(Chef::ChefFS::FilePattern),
223
- an_instance_of(Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
224
- anything(),
225
- anything(),
226
- anything(),
227
- anything(),
228
- anything()
229
- ) do |file_pattern, source|
230
- expect(file_pattern.pattern).to eq(File.join("/roles/*.json"))
231
- expect(source.child_paths["roles"]).to eq(local_roles)
232
- end
233
- subject.upload_roles
234
- end
235
- end
236
-
237
- context "upload_data_bags" do
238
- let(:temp_data_bags) { File.join(config.temp_directory, "data_bags") }
239
- let(:fake_bag_file) { File.join("bags", "bag.json") }
240
- let(:secret_key_file) { File.join("bags", "bag_secrets_keys.json") }
241
- let(:config) { Promote::Config.new({
242
- :temp_directory => "/tmp/promote_tests",
243
- :repo_root => "/tmp/promote_repo",
244
- :node_name => 'user',
245
- :client_key => 'key',
246
- :chef_server_url => 'https://some.chef.server'}) }
247
-
248
- before {
249
- fake_bag_path = File.join(config.data_bag_directory, fake_bag_file)
250
- FileUtils.mkdir_p(File.dirname(fake_bag_path))
251
- FileUtils.touch(fake_bag_path)
252
- FileUtils.touch(File.join(config.data_bag_directory, secret_key_file))
253
- }
254
-
255
- after {
256
- FileUtils.rm_rf(config.temp_directory)
257
- FileUtils.rm_rf(config.repo_root)
258
- }
259
-
260
- it "copies the data_bags to a temp folder" do
261
- subject.upload_data_bags
262
-
263
- expect(File).to exist(File.join(temp_data_bags, fake_bag_file))
264
- end
265
-
266
- it "does not copy key files" do
267
- subject.upload_data_bags
268
-
269
- expect(File).not_to exist(File.join(temp_data_bags, secret_key_file))
270
- end
271
-
272
- it "uploads the data_bags to chef" do
273
- expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
274
- an_instance_of(Chef::ChefFS::FilePattern),
275
- an_instance_of(Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
276
- anything(),
277
- anything(),
278
- anything(),
279
- anything(),
280
- anything()
281
- ) do |file_pattern, source|
282
- expect(file_pattern.pattern).to eq("/data_bags/**/*.json")
283
- expect(source.child_paths["data_bags"]).to eq([temp_data_bags])
284
- end
285
-
286
- subject.upload_data_bags
287
- end
288
- end
289
- end
5
+ let(:knife_config) {{ :cookbook_path => 'path'}}
6
+ let(:temp_dir) { '/tmp/berks' }
7
+ let(:config) { Promote::Config.new({
8
+ :node_name => 'user',
9
+ :cookbook_directory => '/cookbooks',
10
+ :client_key => 'key',
11
+ :temp_directory => temp_dir,
12
+ :chef_server_url => 'https://some.chef.server'}) }
13
+
14
+ subject { Promote::Uploader.new(config) }
15
+
16
+ before {
17
+ Chef::Config[:chef_repo_path] = config.repo_root
18
+ allow(Chef::ChefFS::FileSystem).to receive(:copy_to)
19
+ }
20
+
21
+ context 'upload cookbooks' do
22
+ let(:env_name) { 'QA1' }
23
+ let(:metadata) { PromoteSpecs::DummyMetadata.new({'version' => '1.1.1'}) }
24
+ let(:environment) do
25
+ <<-EOS
26
+ {
27
+ "name": "#{env_name}",
28
+ "chef_type": "environment",
29
+ "json_class": "Chef::Environment",
30
+ "cookbook_versions": {
31
+ "int_cookbook1": "1.1.1",
32
+ "int_cookbook3": "1.1.1",
33
+ "cookbook3": "3.3.3"
34
+ }
35
+ }
36
+ EOS
37
+ end
38
+ let(:berks_cookbooks) {[
39
+ '/berks/cookbook1-1.1.1',
40
+ '/berks/cookbook1-1.1.2',
41
+ '/berks/cookbook2-2.2.2',
42
+ '/berks/cookbook3-3.3.3',
43
+ '/berks/cookbook4-3.3.3',
44
+ ]}
45
+ let(:internal_cookbooks) {[
46
+ '/cookbooks/int_cookbook1',
47
+ '/cookbooks/int_cookbook2',
48
+ '/cookbooks/int_cookbook3',
49
+ ]}
50
+ let(:server_cookbooks){{
51
+ 'cookbook1' => {'versions' => [{'version' => '1.1.1'}]},
52
+ 'cookbook2' => {'versions' => [{'version' => '1.1.1'}]},
53
+ 'int_cookbook1' => {'versions' => [{'version' => '1.1.1'}]},
54
+ 'int_cookbook2' => {'versions' => [{'version' => '2.2.2'}]}
55
+ }}
56
+ let(:rest){double('rest')}
57
+ let(:knife) { instance_double('CookbookUpload', :run => nil) }
58
+
59
+ before {
60
+ allow(File).to receive(:read).with(File.join(config.environment_directory, "#{env_name}.json")).and_return(environment)
61
+ allow(File).to receive(:read).with(/metadata\.json$/).and_return('')
62
+ allow(Chef::REST).to receive(:new).and_return(rest)
63
+ allow(rest).to receive(:get_rest).and_return(server_cookbooks)
64
+ allow(Chef::Cookbook::Metadata).to receive(:new).and_return(metadata)
65
+ allow(Chef::Knife::CookbookUpload).to receive(:new).and_return(knife)
66
+ allow(Dir).to receive(:glob).with(File.expand_path('~/.berkshelf/cookbooks/*')).and_return(berks_cookbooks)
67
+ allow(Dir).to receive(:glob).with(File.join(config.cookbook_directory, '*')).and_return(internal_cookbooks)
68
+ allow(Dir).to receive(:glob).with(File.join(config.temp_directory, '*')).and_return(internal_cookbooks)
69
+ allow(Dir).to receive(:mkdir)
70
+ allow(Dir).to receive(:exist?).and_return(false)
71
+ allow(knife).to receive(:config).and_return(knife_config)
72
+ allow(FileUtils).to receive(:copy_entry)
73
+ allow(File).to receive(:exist?).with(/metadata\.rb$/).and_return(true)
74
+ }
75
+
76
+ it 'copies updated cookbooks to temp directory' do
77
+ expect(FileUtils).not_to receive(:copy_entry).with('/berks/cookbook1-1.1.1', File.join(config.temp_directory, 'cookbook1'))
78
+ expect(FileUtils).not_to receive(:copy_entry).with('/berks/cookbook1-1.1.2', File.join(config.temp_directory, 'cookbook1'))
79
+ expect(FileUtils).not_to receive(:copy_entry).with('/berks/cookbook4-3.3.3', File.join(config.temp_directory, 'cookbook4'))
80
+ expect(FileUtils).not_to receive(:copy_entry).with('/berks/cookbook2-2.2.2', File.join(config.temp_directory, 'cookbook2'))
81
+ expect(FileUtils).to receive(:copy_entry).with('/berks/cookbook3-3.3.3', File.join(config.temp_directory, 'cookbook3'))
82
+ expect(FileUtils).not_to receive(:copy_entry).with('/cookbooks/int_cookbook2', File.join(config.temp_directory, 'int_cookbook2'))
83
+ expect(FileUtils).not_to receive(:copy_entry).with('/cookbooks/int_cookbook1', File.join(config.temp_directory, 'int_cookbook1'))
84
+ expect(FileUtils).to receive(:copy_entry).with('/cookbooks/int_cookbook3', File.join(config.temp_directory, 'int_cookbook3'))
85
+ subject.upload_cookbooks(env_name)
86
+ end
87
+ it 'uploads cookbooks to chef server' do
88
+ expect(knife).to receive(:run)
89
+
90
+ subject.upload_cookbooks(env_name)
91
+ end
92
+ it 'Creates temp directory' do
93
+ expect(Dir).to receive(:mkdir).with(config.temp_directory)
94
+
95
+ subject.upload_cookbooks(env_name)
96
+ end
97
+ it 'uploads cookbooks from config temp path' do
98
+ subject.upload_cookbooks(env_name)
99
+ expect(knife.config[:cookbook_path]).to eq(config.temp_directory)
100
+ end
101
+ it 'uploads all cookbooks' do
102
+ subject.upload_cookbooks(env_name)
103
+ expect(knife.config[:all]).to eq(true)
104
+ end
105
+ it 'freezes all cookbooks' do
106
+ subject.upload_cookbooks(env_name)
107
+ expect(knife.config[:freeze]).to eq(true)
108
+ end
109
+
110
+ context 'no environment is given' do
111
+ it 'copies updated cookbooks and does not filter by environment' do
112
+ expect(FileUtils).not_to receive(:copy_entry).with('/berks/cookbook1-1.1.1', File.join(config.temp_directory, 'cookbook1'))
113
+ expect(FileUtils).to receive(:copy_entry).with('/berks/cookbook1-1.1.2', File.join(config.temp_directory, 'cookbook1'))
114
+ expect(FileUtils).to receive(:copy_entry).with('/berks/cookbook4-3.3.3', File.join(config.temp_directory, 'cookbook4'))
115
+ expect(FileUtils).to receive(:copy_entry).with('/berks/cookbook2-2.2.2', File.join(config.temp_directory, 'cookbook2'))
116
+ expect(FileUtils).to receive(:copy_entry).with('/berks/cookbook3-3.3.3', File.join(config.temp_directory, 'cookbook3'))
117
+ expect(FileUtils).to receive(:copy_entry).with('/cookbooks/int_cookbook2', File.join(config.temp_directory, 'int_cookbook2'))
118
+ expect(FileUtils).not_to receive(:copy_entry).with('/cookbooks/int_cookbook1', File.join(config.temp_directory, 'int_cookbook1'))
119
+ expect(FileUtils).to receive(:copy_entry).with('/cookbooks/int_cookbook3', File.join(config.temp_directory, 'int_cookbook3'))
120
+ subject.upload_cookbooks
121
+ end
122
+ end
123
+
124
+ context 'temp directory already exists' do
125
+ before {allow(Dir).to receive(:exist?).and_return(true)}
126
+
127
+ it 'deletes temp directory' do
128
+ expect(FileUtils).to receive(:rm_rf).with(config.temp_directory)
129
+ subject.upload_cookbooks(env_name)
130
+ end
131
+ end
132
+
133
+ context 'no metadata.rb file exists for cookbook' do
134
+ before {allow(File).to receive(:exist?).with(/rb$/).and_return(false)}
135
+
136
+ it 'loads json instead of ruby file' do
137
+ expect(metadata).to receive(:from_json).at_least(1).times
138
+ expect(metadata).not_to receive(:from_file)
139
+ subject.upload_cookbooks(env_name)
140
+ end
141
+ end
142
+
143
+ context 'nothing to upload' do
144
+ let(:berks_cookbooks) {[]}
145
+ let(:internal_cookbooks) {[]}
146
+
147
+ it 'does not call knife' do
148
+ expect(Chef::Knife::CookbookUpload).not_to receive(:new)
149
+
150
+ subject.upload_cookbooks(env_name)
151
+ end
152
+ end
153
+
154
+ context 'config missing node_name' do
155
+ let(:config) { Promote::Config.new({
156
+ :client_key => 'key',
157
+ :chef_server_url => 'https://some.chef.server'}) }
158
+
159
+ it 'raises error that node_name is missing' do
160
+ expect{subject.upload_cookbooks(env_name)}.to raise_error(/node_name/)
161
+ end
162
+ end
163
+
164
+ context 'config missing client_key' do
165
+ let(:config) { Promote::Config.new({
166
+ :node_name => 'user',
167
+ :chef_server_url => 'https://some.chef.server'}) }
168
+
169
+ it 'raises error that client_key is missing' do
170
+ expect{subject.upload_cookbooks(env_name)}.to raise_error(/client_key/)
171
+ end
172
+ end
173
+
174
+ context 'config missing chef_server_url' do
175
+ let(:config) { Promote::Config.new({
176
+ :node_name => 'user',
177
+ :client_key => 'key'}) }
178
+
179
+ it 'raises error that chef_server_url is missing' do
180
+ expect{subject.upload_cookbooks(env_name)}.to raise_error(/chef_server_url/)
181
+ end
182
+ end
183
+ end
184
+
185
+ context 'upload json artifacts' do
186
+ context 'upload an environment' do
187
+ let(:env_name) { 'my_test' }
188
+
189
+ it 'uploads the environment' do
190
+ expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(an_instance_of(Chef::ChefFS::FilePattern), anything(), anything(), anything(), anything(), anything(), anything()) do |arg|
191
+ expect(arg.pattern).to eq(File.join('/environments', "#{env_name}.json"))
192
+ end
193
+ subject.upload_environment(env_name)
194
+ end
195
+ end
196
+
197
+ context 'upload all environments' do
198
+ it 'uploads the environment' do
199
+ local_environments = Chef::ChefFS::Config.new.local_fs.child_paths['environments']
200
+
201
+ expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
202
+ an_instance_of(Chef::ChefFS::FilePattern),
203
+ an_instance_of(Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
204
+ anything(),
205
+ anything(),
206
+ anything(),
207
+ anything(),
208
+ anything()
209
+ ) do |file_pattern, source|
210
+ expect(file_pattern.pattern).to eq(File.join('/environments/*.json'))
211
+ expect(source.child_paths['environments']).to eq(local_environments)
212
+ end
213
+ subject.upload_environments
214
+ end
215
+ end
216
+
217
+ context 'upload all roles' do
218
+ it 'uploads the role' do
219
+ local_roles = Chef::ChefFS::Config.new.local_fs.child_paths['roles']
220
+
221
+ expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
222
+ an_instance_of(Chef::ChefFS::FilePattern),
223
+ an_instance_of(Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
224
+ anything(),
225
+ anything(),
226
+ anything(),
227
+ anything(),
228
+ anything()
229
+ ) do |file_pattern, source|
230
+ expect(file_pattern.pattern).to eq(File.join('/roles/*.json'))
231
+ expect(source.child_paths['roles']).to eq(local_roles)
232
+ end
233
+ subject.upload_roles
234
+ end
235
+ end
236
+
237
+ context 'upload_data_bags' do
238
+ let(:temp_data_bags) { File.join(config.temp_directory, 'data_bags') }
239
+ let(:fake_bag_file) { File.join('bags', 'bag.json') }
240
+ let(:secret_key_file) { File.join('bags', 'bag_secrets_keys.json') }
241
+ let(:config) { Promote::Config.new({
242
+ :temp_directory => '/tmp/promote_tests',
243
+ :repo_root => '/tmp/promote_repo',
244
+ :node_name => 'user',
245
+ :client_key => 'key',
246
+ :chef_server_url => 'https://some.chef.server'}) }
247
+
248
+ before {
249
+ fake_bag_path = File.join(config.data_bag_directory, fake_bag_file)
250
+ FileUtils.mkdir_p(File.dirname(fake_bag_path))
251
+ FileUtils.touch(fake_bag_path)
252
+ FileUtils.touch(File.join(config.data_bag_directory, secret_key_file))
253
+ }
254
+
255
+ after {
256
+ FileUtils.rm_rf(config.temp_directory)
257
+ FileUtils.rm_rf(config.repo_root)
258
+ }
259
+
260
+ it 'copies the data_bags to a temp folder' do
261
+ subject.upload_data_bags
262
+
263
+ expect(File).to exist(File.join(temp_data_bags, fake_bag_file))
264
+ end
265
+
266
+ it 'does not copy key files' do
267
+ subject.upload_data_bags
268
+
269
+ expect(File).not_to exist(File.join(temp_data_bags, secret_key_file))
270
+ end
271
+
272
+ it 'uploads the data_bags to chef' do
273
+ expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
274
+ an_instance_of(Chef::ChefFS::FilePattern),
275
+ an_instance_of(Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
276
+ anything(),
277
+ anything(),
278
+ anything(),
279
+ anything(),
280
+ anything()
281
+ ) do |file_pattern, source|
282
+ expect(file_pattern.pattern).to eq('/data_bags/**/*.json')
283
+ expect(source.child_paths['data_bags']).to eq([temp_data_bags])
284
+ end
285
+
286
+ subject.upload_data_bags
287
+ end
288
+ end
289
+ end
290
290
  end