chef-dk 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -0
  3. data/lib/chef-dk/builtin_commands.rb +7 -0
  4. data/lib/chef-dk/command/env.rb +90 -0
  5. data/lib/chef-dk/command/export.rb +22 -1
  6. data/lib/chef-dk/command/generate.rb +1 -1
  7. data/lib/chef-dk/command/provision.rb +43 -0
  8. data/lib/chef-dk/command/push_archive.rb +126 -0
  9. data/lib/chef-dk/command/show_policy.rb +166 -0
  10. data/lib/chef-dk/command/verify.rb +58 -1
  11. data/lib/chef-dk/cookbook_omnifetch.rb +3 -2
  12. data/lib/chef-dk/exceptions.rb +27 -0
  13. data/lib/chef-dk/helpers.rb +29 -0
  14. data/lib/chef-dk/policyfile/chef_repo_cookbook_source.rb +8 -0
  15. data/lib/chef-dk/policyfile/chef_server_cookbook_source.rb +8 -0
  16. data/lib/chef-dk/policyfile/community_cookbook_source.rb +8 -0
  17. data/lib/chef-dk/policyfile/cookbook_locks.rb +76 -6
  18. data/lib/chef-dk/policyfile/dsl.rb +10 -5
  19. data/lib/chef-dk/policyfile/lister.rb +230 -0
  20. data/lib/chef-dk/policyfile/null_cookbook_source.rb +8 -0
  21. data/lib/chef-dk/policyfile_compiler.rb +35 -2
  22. data/lib/chef-dk/policyfile_lock.rb +43 -0
  23. data/lib/chef-dk/policyfile_services/clean_policies.rb +94 -0
  24. data/lib/chef-dk/policyfile_services/export_repo.rb +103 -16
  25. data/lib/chef-dk/policyfile_services/push_archive.rb +173 -0
  26. data/lib/chef-dk/policyfile_services/show_policy.rb +237 -0
  27. data/lib/chef-dk/service_exceptions.rb +21 -0
  28. data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +1 -0
  29. data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +2 -40
  30. data/lib/chef-dk/skeletons/code_generator/recipes/app.rb +0 -2
  31. data/lib/chef-dk/skeletons/code_generator/templates/default/kitchen.yml.erb +2 -2
  32. data/lib/chef-dk/skeletons/code_generator/templates/default/recipe_spec.rb.erb +1 -1
  33. data/lib/chef-dk/version.rb +1 -1
  34. data/spec/unit/command/env_spec.rb +52 -0
  35. data/spec/unit/command/exec_spec.rb +2 -2
  36. data/spec/unit/command/export_spec.rb +13 -0
  37. data/spec/unit/command/provision_spec.rb +56 -0
  38. data/spec/unit/command/push_archive_spec.rb +153 -0
  39. data/spec/unit/command/show_policy_spec.rb +235 -0
  40. data/spec/unit/command/verify_spec.rb +1 -0
  41. data/spec/unit/helpers_spec.rb +68 -0
  42. data/spec/unit/policyfile/cookbook_locks_spec.rb +107 -1
  43. data/spec/unit/policyfile/lister_spec.rb +256 -0
  44. data/spec/unit/policyfile_demands_spec.rb +202 -10
  45. data/spec/unit/policyfile_evaluation_spec.rb +30 -4
  46. data/spec/unit/policyfile_lock_serialization_spec.rb +45 -0
  47. data/spec/unit/policyfile_services/clean_policies_spec.rb +236 -0
  48. data/spec/unit/policyfile_services/export_repo_spec.rb +99 -6
  49. data/spec/unit/policyfile_services/push_archive_spec.rb +345 -0
  50. data/spec/unit/policyfile_services/show_policy_spec.rb +839 -0
  51. metadata +139 -8
@@ -0,0 +1,839 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2015 Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'spec_helper'
19
+ require 'chef-dk/policyfile_services/show_policy'
20
+
21
+ describe ChefDK::PolicyfileServices::ShowPolicy do
22
+
23
+ let(:chef_config) { double("Chef::Config") }
24
+
25
+ let(:ui) { TestHelpers::TestUI.new }
26
+
27
+ let(:policy_name) { nil }
28
+
29
+ let(:policy_group) { nil }
30
+
31
+ let(:show_orphans) { false }
32
+
33
+ let(:summary_diff) { false }
34
+
35
+ subject(:show_policy_service) do
36
+ described_class.new(config: chef_config,
37
+ ui: ui,
38
+ policy_name: policy_name,
39
+ policy_group: policy_group,
40
+ show_orphans: show_orphans,
41
+ summary_diff: summary_diff)
42
+ end
43
+
44
+ let(:policy_lister) do
45
+ show_policy_service.policy_lister
46
+ end
47
+
48
+ let(:policyfile_locks_content) {}
49
+
50
+ describe "show all" do
51
+
52
+ let(:params) { [] }
53
+
54
+ let(:policies_by_name) { {} }
55
+ let(:policies_by_group) { {} }
56
+
57
+ describe "when an error occurs fetching data from the server" do
58
+
59
+ let(:http_client) { instance_double(ChefDK::AuthenticatedHTTP) }
60
+
61
+ let(:response) do
62
+ Net::HTTPResponse.send(:response_class, "500").new("1.0", "500", "Internal Server Error").tap do |r|
63
+ r.instance_variable_set(:@body, "oops")
64
+ end
65
+ end
66
+
67
+ let(:http_exception) do
68
+ begin
69
+ response.error!
70
+ rescue => e
71
+ e
72
+ end
73
+ end
74
+
75
+ let(:policies_url) { "/policies" }
76
+
77
+ let(:policy_groups_url) { "/policy_groups" }
78
+
79
+ before do
80
+ allow(policy_lister).to receive(:http_client).and_return(http_client)
81
+ end
82
+
83
+ describe "when fetching policy revisions by policy group" do
84
+
85
+ before do
86
+ expect(http_client).to receive(:get).and_raise(http_exception)
87
+ end
88
+
89
+ it "raises an error" do
90
+ expect { show_policy_service.run }.to raise_error(ChefDK::PolicyfileListError)
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ context "when the server returns the data successfully" do
97
+
98
+ before do
99
+ policy_lister.set!(policies_by_name, policies_by_group)
100
+ policy_lister.policy_lock_content = policyfile_locks_content
101
+
102
+ show_policy_service.run
103
+ end
104
+
105
+ context "when there are no policies or groups on the server" do
106
+
107
+ it "prints a message to stderr that there aren't any policies or groups" do
108
+ expect(ui.output).to eq("No policies or policy groups exist on the server\n")
109
+ end
110
+
111
+ end
112
+
113
+ context "when there are policies but no groups" do
114
+
115
+ let(:policies_by_name) do
116
+ {
117
+ "appserver" => {
118
+ "1111111111111111111111111111111111111111111111111111111111111111" => {},
119
+ "2222222222222222222222222222222222222222222222222222222222222222" => {}
120
+ },
121
+ "load-balancer" => {
122
+ "5555555555555555555555555555555555555555555555555555555555555555" => {},
123
+ "6666666666666666666666666666666666666666666666666666666666666666" => {},
124
+ },
125
+ "db" => {
126
+ "9999999999999999999999999999999999999999999999999999999999999999" => {},
127
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" => {}
128
+ }
129
+ }
130
+ end
131
+
132
+ it "prints a message to stderr that there are no active policies" do
133
+ expected_output = <<-OUTPUT
134
+ appserver
135
+ =========
136
+
137
+ Policy appserver is not assigned to any groups
138
+
139
+ load-balancer
140
+ =============
141
+
142
+ Policy load-balancer is not assigned to any groups
143
+
144
+ db
145
+ ==
146
+
147
+ Policy db is not assigned to any groups
148
+
149
+ OUTPUT
150
+ expect(ui.output).to eq(expected_output)
151
+ end
152
+
153
+ context "with orphans shown" do
154
+
155
+ let(:show_orphans) { true }
156
+
157
+ it "shows all policies as orphaned" do
158
+ expected_output = <<-OUTPUT
159
+ appserver
160
+ =========
161
+
162
+ Policy appserver is not assigned to any groups
163
+
164
+ Orphaned:
165
+ ---------
166
+
167
+ * 1111111111
168
+ * 2222222222
169
+
170
+ load-balancer
171
+ =============
172
+
173
+ Policy load-balancer is not assigned to any groups
174
+
175
+ Orphaned:
176
+ ---------
177
+
178
+ * 5555555555
179
+ * 6666666666
180
+
181
+ db
182
+ ==
183
+
184
+ Policy db is not assigned to any groups
185
+
186
+ Orphaned:
187
+ ---------
188
+
189
+ * 9999999999
190
+ * aaaaaaaaaa
191
+
192
+ OUTPUT
193
+ expect(ui.output).to eq(expected_output)
194
+ end
195
+ end
196
+
197
+ end
198
+
199
+ context "when there are groups but no policies" do
200
+
201
+ let(:policies_by_group) do
202
+ {
203
+ "dev" => {},
204
+ "staging" => {},
205
+ "prod" => {}
206
+ }
207
+ end
208
+
209
+ it "prints a message to stderr and exits" do
210
+ expect(ui.output).to eq("No policies exist on the server\n")
211
+ end
212
+
213
+ end
214
+
215
+ context "when there is a revision of each kind of policy assigned to every policy group" do
216
+
217
+ let(:policies_by_name) do
218
+ {
219
+ "appserver" => {
220
+ "1111111111111111111111111111111111111111111111111111111111111111" => {},
221
+ "2222222222222222222222222222222222222222222222222222222222222222" => {}
222
+ },
223
+ "load-balancer" => {
224
+ "5555555555555555555555555555555555555555555555555555555555555555" => {},
225
+ "6666666666666666666666666666666666666666666666666666666666666666" => {},
226
+ },
227
+ "db" => {
228
+ "9999999999999999999999999999999999999999999999999999999999999999" => {},
229
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" => {}
230
+ }
231
+ }
232
+ end
233
+
234
+ let(:policies_by_group) do
235
+ {
236
+ "dev" => {
237
+ "appserver" => "1111111111111111111111111111111111111111111111111111111111111111",
238
+ "load-balancer" => "5555555555555555555555555555555555555555555555555555555555555555",
239
+ "db" => "9999999999999999999999999999999999999999999999999999999999999999"
240
+ },
241
+ "staging" => {
242
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222",
243
+ "load-balancer" => "5555555555555555555555555555555555555555555555555555555555555555",
244
+ "db" => "9999999999999999999999999999999999999999999999999999999999999999"
245
+ },
246
+ "prod" => {
247
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222",
248
+ "load-balancer" => "6666666666666666666666666666666666666666666666666666666666666666",
249
+ "db" => "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
250
+ }
251
+ }
252
+ end
253
+
254
+ it "shows each policy name, followed by a list of group_name -> revision" do
255
+ expected_output = <<-OUTPUT
256
+ appserver
257
+ =========
258
+
259
+ * dev: 1111111111
260
+ * staging: 2222222222
261
+ * prod: 2222222222
262
+
263
+ load-balancer
264
+ =============
265
+
266
+ * dev: 5555555555
267
+ * staging: 5555555555
268
+ * prod: 6666666666
269
+
270
+ db
271
+ ==
272
+
273
+ * dev: 9999999999
274
+ * staging: 9999999999
275
+ * prod: aaaaaaaaaa
276
+
277
+ OUTPUT
278
+ expect(ui.output).to eq(expected_output)
279
+ end
280
+
281
+ end
282
+
283
+ context "when there is a revision of each kind of policy assigned to every policy group, plus orphaned policies" do
284
+ let(:policies_by_name) do
285
+ {
286
+ "appserver" => {
287
+ "1111111111111111111111111111111111111111111111111111111111111111" => {},
288
+ "2222222222222222222222222222222222222222222222222222222222222222" => {},
289
+ "3333333333333333333333333333333333333333333333333333333333333333" => {}
290
+ },
291
+ "load-balancer" => {
292
+ "5555555555555555555555555555555555555555555555555555555555555555" => {},
293
+ "6666666666666666666666666666666666666666666666666666666666666666" => {},
294
+ "7777777777777777777777777777777777777777777777777777777777777777" => {}
295
+ },
296
+ "db" => {
297
+ "9999999999999999999999999999999999999999999999999999999999999999" => {},
298
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" => {},
299
+ "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" => {}
300
+ }
301
+ }
302
+ end
303
+
304
+ let(:policies_by_group) do
305
+ {
306
+ "dev" => {
307
+ "appserver" => "1111111111111111111111111111111111111111111111111111111111111111",
308
+ "load-balancer" => "5555555555555555555555555555555555555555555555555555555555555555",
309
+ "db" => "9999999999999999999999999999999999999999999999999999999999999999"
310
+ },
311
+ "staging" => {
312
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222",
313
+ "load-balancer" => "5555555555555555555555555555555555555555555555555555555555555555",
314
+ "db" => "9999999999999999999999999999999999999999999999999999999999999999"
315
+ },
316
+ "prod" => {
317
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222",
318
+ "load-balancer" => "6666666666666666666666666666666666666666666666666666666666666666",
319
+ "db" => "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
320
+ }
321
+ }
322
+ end
323
+
324
+ it "shows each policy name, followed by a list of group_name -> revision, followed by a list of orphaned policies" do
325
+ expected_output = <<-OUTPUT
326
+ appserver
327
+ =========
328
+
329
+ * dev: 1111111111
330
+ * staging: 2222222222
331
+ * prod: 2222222222
332
+
333
+ load-balancer
334
+ =============
335
+
336
+ * dev: 5555555555
337
+ * staging: 5555555555
338
+ * prod: 6666666666
339
+
340
+ db
341
+ ==
342
+
343
+ * dev: 9999999999
344
+ * staging: 9999999999
345
+ * prod: aaaaaaaaaa
346
+
347
+ OUTPUT
348
+ expect(ui.output).to eq(expected_output)
349
+ end
350
+
351
+ context "with orphans shown" do
352
+
353
+ let(:show_orphans) { true }
354
+
355
+ it "shows each policy name, followed by a list of group_name -> revision, followed by a list of orphaned policies" do
356
+ expected_output = <<-OUTPUT
357
+ appserver
358
+ =========
359
+
360
+ * dev: 1111111111
361
+ * staging: 2222222222
362
+ * prod: 2222222222
363
+
364
+ Orphaned:
365
+ ---------
366
+
367
+ * 3333333333
368
+
369
+ load-balancer
370
+ =============
371
+
372
+ * dev: 5555555555
373
+ * staging: 5555555555
374
+ * prod: 6666666666
375
+
376
+ Orphaned:
377
+ ---------
378
+
379
+ * 7777777777
380
+
381
+ db
382
+ ==
383
+
384
+ * dev: 9999999999
385
+ * staging: 9999999999
386
+ * prod: aaaaaaaaaa
387
+
388
+ Orphaned:
389
+ ---------
390
+
391
+ * bbbbbbbbbb
392
+
393
+ OUTPUT
394
+ expect(ui.output).to eq(expected_output)
395
+ end
396
+
397
+ end
398
+ end
399
+
400
+ context "when some groups do not have a revision of every policy" do
401
+ let(:policies_by_name) do
402
+ {
403
+ "appserver" => {
404
+ "1111111111111111111111111111111111111111111111111111111111111111" => {},
405
+ "2222222222222222222222222222222222222222222222222222222222222222" => {}
406
+ },
407
+ "load-balancer" => {
408
+ "5555555555555555555555555555555555555555555555555555555555555555" => {},
409
+ "6666666666666666666666666666666666666666666666666666666666666666" => {},
410
+ },
411
+ "db" => {
412
+ "9999999999999999999999999999999999999999999999999999999999999999" => {},
413
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" => {}
414
+ },
415
+ "memcache" => {
416
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" => {}
417
+ }
418
+ }
419
+ end
420
+
421
+ let(:policies_by_group) do
422
+ {
423
+ "dev" => {
424
+ "appserver" => "1111111111111111111111111111111111111111111111111111111111111111",
425
+ "load-balancer" => "5555555555555555555555555555555555555555555555555555555555555555",
426
+ "db" => "9999999999999999999999999999999999999999999999999999999999999999",
427
+ "memcache" => "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
428
+ },
429
+ "staging" => {
430
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222",
431
+ "load-balancer" => "5555555555555555555555555555555555555555555555555555555555555555",
432
+ "db" => "9999999999999999999999999999999999999999999999999999999999999999",
433
+ "memcache" => "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
434
+ },
435
+ "prod" => {
436
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222",
437
+ "load-balancer" => "6666666666666666666666666666666666666666666666666666666666666666",
438
+ "db" => "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
439
+ }
440
+ }
441
+ end
442
+
443
+
444
+ it "shows each policy name, followed by a list of group_name -> revision, omitting groups that don't have that policy" do
445
+ expected_output = <<-OUTPUT
446
+ appserver
447
+ =========
448
+
449
+ * dev: 1111111111
450
+ * staging: 2222222222
451
+ * prod: 2222222222
452
+
453
+ load-balancer
454
+ =============
455
+
456
+ * dev: 5555555555
457
+ * staging: 5555555555
458
+ * prod: 6666666666
459
+
460
+ db
461
+ ==
462
+
463
+ * dev: 9999999999
464
+ * staging: 9999999999
465
+ * prod: aaaaaaaaaa
466
+
467
+ memcache
468
+ ========
469
+
470
+ * dev: dddddddddd
471
+ * staging: dddddddddd
472
+ * prod: *NOT APPLIED*
473
+
474
+ OUTPUT
475
+ expect(ui.output).to eq(expected_output)
476
+ end
477
+
478
+ end
479
+ end
480
+ end
481
+
482
+ describe "showing a single policy" do
483
+
484
+ let(:policy_name) { "appserver" }
485
+
486
+ let(:policies_by_name) { {} }
487
+ let(:policies_by_group) { {} }
488
+
489
+ before do
490
+ policy_lister.set!(policies_by_name, policies_by_group)
491
+ end
492
+
493
+ context "when the server returns the data successfully" do
494
+
495
+ before do
496
+ policy_lister.set!(policies_by_name, policies_by_group)
497
+ policy_lister.policy_lock_content = policyfile_locks_content
498
+
499
+ show_policy_service.run
500
+ end
501
+
502
+ context "when there are no revisions of the policy on the server" do
503
+
504
+ let(:policies_by_name) do
505
+ {}
506
+ end
507
+
508
+ let(:policies_by_group) do
509
+ {}
510
+ end
511
+
512
+ it "prints a message to stderr that there are no copies of the policy on the server" do
513
+ expected_output = <<-OUTPUT
514
+ appserver
515
+ =========
516
+
517
+ No policies named 'appserver' are associated with a policy group
518
+
519
+ OUTPUT
520
+
521
+ expect(ui.output).to eq(expected_output)
522
+ end
523
+
524
+ end
525
+
526
+ context "when all policies are orphaned and orphans are not shown" do
527
+ let(:policies_by_name) do
528
+ {
529
+ "appserver" => {
530
+ "1111111111111111111111111111111111111111111111111111111111111111" => {},
531
+ "2222222222222222222222222222222222222222222222222222222222222222" => {},
532
+ "3333333333333333333333333333333333333333333333333333333333333333" => {}
533
+ }
534
+ }
535
+
536
+ end
537
+
538
+ let(:policies_by_group) do
539
+ {}
540
+ end
541
+
542
+ it "explains that no policies are assigned to a group" do
543
+ expected_output = <<-OUTPUT
544
+ appserver
545
+ =========
546
+
547
+ No policies named 'appserver' are associated with a policy group
548
+
549
+ OUTPUT
550
+
551
+ expect(ui.output).to eq(expected_output)
552
+ end
553
+ end
554
+
555
+ context "when all policy groups have the same revision of the policy" do
556
+
557
+ let(:policies_by_name) do
558
+ {
559
+ "appserver" => {
560
+ "1111111111111111111111111111111111111111111111111111111111111111" => {},
561
+ "2222222222222222222222222222222222222222222222222222222222222222" => {},
562
+ "3333333333333333333333333333333333333333333333333333333333333333" => {}
563
+ }
564
+ }
565
+
566
+ end
567
+
568
+ let(:policies_by_group) do
569
+ {
570
+ "dev" => {
571
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222"
572
+ },
573
+ "staging" => {
574
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222"
575
+ },
576
+ "prod" => {
577
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222"
578
+ }
579
+ }
580
+ end
581
+ it "lists each of the groups with the associated revision" do
582
+ expected_output = <<-OUTPUT
583
+ appserver
584
+ =========
585
+
586
+ * dev: 2222222222
587
+ * staging: 2222222222
588
+ * prod: 2222222222
589
+
590
+ OUTPUT
591
+ expect(ui.output).to eq(expected_output)
592
+ end
593
+
594
+ end
595
+
596
+ context "when policy groups have revisions with differing cookbooks" do
597
+
598
+ let(:policies_by_name) do
599
+ {
600
+ "appserver" => {
601
+ "1111111111111111111111111111111111111111111111111111111111111111" => {},
602
+ "2222222222222222222222222222222222222222222222222222222222222222" => {},
603
+ "3333333333333333333333333333333333333333333333333333333333333333" => {}
604
+ }
605
+ }
606
+
607
+ end
608
+
609
+ let(:policies_by_group) do
610
+ {
611
+ "dev" => {
612
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222"
613
+ },
614
+ "staging" => {
615
+ "appserver" => "2222222222222222222222222222222222222222222222222222222222222222"
616
+ },
617
+ "prod" => {
618
+ "appserver" => "1111111111111111111111111111111111111111111111111111111111111111"
619
+ }
620
+ }
621
+ end
622
+
623
+ it "lists each of the groups with the associated revision" do
624
+ expected_output = <<-OUTPUT
625
+ appserver
626
+ =========
627
+
628
+ * dev: 2222222222
629
+ * staging: 2222222222
630
+ * prod: 1111111111
631
+
632
+ OUTPUT
633
+ expect(ui.output).to eq(expected_output)
634
+ end
635
+
636
+ context "when the diff summary option is given" do
637
+
638
+ let(:appserver_lock_contents_111) do
639
+ {
640
+ "cookbook_locks" => {
641
+ "apache2" => {
642
+ "version" => "2.1.3",
643
+ "identifier" => "abcdef" + ("0" * 34)
644
+ },
645
+ "yum" => {
646
+ "version" => "4.5.6",
647
+ "identifier" => "123abc" + ("0" * 34)
648
+ },
649
+ "apt" => {
650
+ "version" => "10.0.0",
651
+ "identifier" => "ffffff" + ("0" * 34)
652
+ }
653
+
654
+ }
655
+ }
656
+ end
657
+
658
+ let(:appserver_lock_contents_222) do
659
+ {
660
+ "cookbook_locks" => {
661
+ "apache2" => {
662
+ "version" => "2.0.5",
663
+ "identifier" => "aaa123" + ("0" * 34)
664
+ },
665
+ "yum" => {
666
+ "version" => "4.5.2",
667
+ "identifier" => "867530" + ("9" * 34)
668
+ },
669
+ "apt" => {
670
+ "version" => "10.0.0",
671
+ "identifier" => "ffffff" + ("0" * 34)
672
+ },
673
+ "other_cookbook" => {
674
+ "version" => "9.8.7",
675
+ "identifier" => "113113" + ("0" * 34)
676
+ }
677
+ }
678
+ }
679
+ end
680
+
681
+ let(:policyfile_locks_content) do
682
+ {
683
+ "appserver" => {
684
+ "1111111111111111111111111111111111111111111111111111111111111111" => appserver_lock_contents_111,
685
+ "2222222222222222222222222222222222222222222222222222222222222222" => appserver_lock_contents_222,
686
+ }
687
+ }
688
+ end
689
+
690
+ let(:summary_diff) { true }
691
+
692
+ it "lists each of the groups and displays the version and identifier of the differing cookbooks" do
693
+ expected_output = <<-OUTPUT
694
+ appserver
695
+ =========
696
+
697
+ dev: 2222222222
698
+ -------------------
699
+
700
+ * apache2: 2.0.5 (aaa1230000)
701
+ * yum: 4.5.2 (8675309999)
702
+ * other_cookbook: 9.8.7 (1131130000)
703
+
704
+ staging: 2222222222
705
+ -------------------
706
+
707
+ * apache2: 2.0.5 (aaa1230000)
708
+ * yum: 4.5.2 (8675309999)
709
+ * other_cookbook: 9.8.7 (1131130000)
710
+
711
+ prod: 1111111111
712
+ -------------------
713
+
714
+ * apache2: 2.1.3 (abcdef0000)
715
+ * yum: 4.5.6 (123abc0000)
716
+ * other_cookbook: *NONE*
717
+
718
+ OUTPUT
719
+ expect(ui.output).to eq(expected_output)
720
+ end
721
+ end
722
+
723
+ context "when orphans are displayed" do
724
+
725
+ let(:show_orphans) { true }
726
+
727
+ it "lists each of the groups, then lists the orphaned revisions" do
728
+ expected_output = <<-OUTPUT
729
+ appserver
730
+ =========
731
+
732
+ * dev: 2222222222
733
+ * staging: 2222222222
734
+ * prod: 1111111111
735
+
736
+ Orphaned:
737
+ ---------
738
+
739
+ * 3333333333
740
+
741
+ OUTPUT
742
+
743
+ expect(ui.output).to eq(expected_output)
744
+ end
745
+
746
+ end
747
+ end
748
+
749
+ end
750
+ end # showing a single policy
751
+
752
+ describe "show policy in a specific policy group" do
753
+
754
+ let(:policy_name) { "appserver" }
755
+
756
+ let(:policy_group) { "dev" }
757
+
758
+ let(:http_client) { instance_double("ChefDK::AuthenticatedHTTP", url: "https://chef.example/organizations/monkeynews") }
759
+
760
+ before do
761
+ allow(show_policy_service).to receive(:http_client).and_return(http_client)
762
+ end
763
+
764
+ it "enables show_policy_revision" do
765
+ expect(show_policy_service.show_policy_revision?).to be(true)
766
+ end
767
+
768
+ context "when there is no policy assigned for the given name and group" do
769
+
770
+ let(:response) do
771
+ Net::HTTPResponse.send(:response_class, "404").new("1.0", "404", "Not Found").tap do |r|
772
+ r.instance_variable_set(:@body, "nope")
773
+ end
774
+ end
775
+
776
+ let(:http_exception) do
777
+ begin
778
+ response.error!
779
+ rescue => e
780
+ e
781
+ end
782
+ end
783
+
784
+ before do
785
+ allow(http_client).to receive(:get).with("policy_groups/dev/policies/appserver").and_raise(http_exception)
786
+ end
787
+
788
+ it "prints a message saying there is no policy assigned" do
789
+ message = "No policyfile lock named 'appserver' found in policy_group 'dev' at https://chef.example/organizations/monkeynews"
790
+ expect { show_policy_service.run }.to raise_error(ChefDK::PolicyfileDownloadError, message)
791
+ end
792
+
793
+ end
794
+
795
+ context "when the policy exists" do
796
+
797
+ let(:policyfile_lock_data) do
798
+ {
799
+ "revision_id" => "cf5b8a020bdc1ba6914093a8a07a5514cce8a3a2979a967b1f32ea704a61785b",
800
+ "name"=> "example",
801
+ "run_list"=> [ "recipe[omnibus::default]" ],
802
+ "cookbook_locks"=> {
803
+ "omnibus"=> {
804
+ "version"=> "2.2.0",
805
+ "identifier"=> "64b3e64306cff223206348e46af545b19032b170",
806
+ "dotted_decimal_identifier"=> "28345299219435506.9887234981653237.76628930769264",
807
+ "cache_key"=> "omnibus-2cf98f9797cacce9c8688fc4e74858b858e2bc14",
808
+ "origin"=> "git@github.com:opscode-cookbooks/omnibus.git",
809
+ "source_options"=> {
810
+ "git"=> "git@github.com:opscode-cookbooks/omnibus.git",
811
+ "revision"=> "2cf98f9797cacce9c8688fc4e74858b858e2bc14",
812
+ "branch"=> "master"
813
+ }
814
+ }
815
+ }
816
+ }
817
+ end
818
+
819
+ let(:policyfile_lock_json) { FFI_Yajl::Encoder.encode(policyfile_lock_data, pretty: true) }
820
+
821
+ let(:pager) { instance_double("ChefDK::Pager", ui: ui) }
822
+
823
+ before do
824
+ allow(ChefDK::Pager).to receive(:new).and_return(pager)
825
+ allow(pager).to receive(:with_pager).and_yield(pager)
826
+ allow(http_client).to receive(:get).with("policy_groups/dev/policies/appserver").and_return(policyfile_lock_data)
827
+ end
828
+
829
+ it "displays the policy" do
830
+ show_policy_service.run
831
+ expect(ui.output).to include(policyfile_lock_json)
832
+ end
833
+
834
+ end
835
+
836
+ end
837
+
838
+ end
839
+