chef-dk 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/chef-dk/builtin_commands.rb +10 -0
  4. data/lib/chef-dk/command/base.rb +2 -2
  5. data/lib/chef-dk/command/clean_policy_cookbooks.rb +116 -0
  6. data/lib/chef-dk/command/clean_policy_revisions.rb +113 -0
  7. data/lib/chef-dk/command/delete_policy.rb +122 -0
  8. data/lib/chef-dk/command/delete_policy_group.rb +122 -0
  9. data/lib/chef-dk/command/export.rb +3 -3
  10. data/lib/chef-dk/command/generate.rb +8 -0
  11. data/lib/chef-dk/command/generator_commands/app.rb +1 -1
  12. data/lib/chef-dk/command/generator_commands/cookbook.rb +1 -1
  13. data/lib/chef-dk/command/generator_commands/policyfile.rb +1 -1
  14. data/lib/chef-dk/command/generator_commands/repo.rb +1 -1
  15. data/lib/chef-dk/command/install.rb +22 -5
  16. data/lib/chef-dk/command/provision.rb +0 -4
  17. data/lib/chef-dk/command/push.rb +1 -2
  18. data/lib/chef-dk/command/shell_init.rb +65 -6
  19. data/lib/chef-dk/command/show_policy.rb +1 -2
  20. data/lib/chef-dk/command/undelete.rb +155 -0
  21. data/lib/chef-dk/command/update.rb +5 -5
  22. data/lib/chef-dk/command/verify.rb +61 -17
  23. data/lib/chef-dk/completions/bash.sh.erb +5 -0
  24. data/lib/chef-dk/completions/chef.fish.erb +10 -0
  25. data/lib/chef-dk/completions/zsh.zsh.erb +21 -0
  26. data/lib/chef-dk/exceptions.rb +12 -0
  27. data/lib/chef-dk/helpers.rb +17 -0
  28. data/lib/chef-dk/policyfile/community_cookbook_source.rb +0 -3
  29. data/lib/chef-dk/policyfile/lister.rb +3 -1
  30. data/lib/chef-dk/policyfile/undo_record.rb +142 -0
  31. data/lib/chef-dk/policyfile/undo_stack.rb +130 -0
  32. data/lib/chef-dk/policyfile_lock.rb +30 -0
  33. data/lib/chef-dk/policyfile_services/clean_policies.rb +5 -4
  34. data/lib/chef-dk/policyfile_services/clean_policy_cookbooks.rb +125 -0
  35. data/lib/chef-dk/policyfile_services/rm_policy.rb +142 -0
  36. data/lib/chef-dk/policyfile_services/rm_policy_group.rb +86 -0
  37. data/lib/chef-dk/policyfile_services/show_policy.rb +1 -1
  38. data/lib/chef-dk/policyfile_services/undelete.rb +108 -0
  39. data/lib/chef-dk/service_exceptions.rb +11 -0
  40. data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +6 -2
  41. data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +1 -1
  42. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +1 -1
  43. data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +1 -1
  44. data/lib/chef-dk/version.rb +1 -1
  45. data/lib/kitchen/provisioner/policyfile_zero.rb +4 -1
  46. data/spec/unit/command/base_spec.rb +26 -1
  47. data/spec/unit/command/clean_policy_cookbooks_spec.rb +181 -0
  48. data/spec/unit/command/clean_policy_revisions_spec.rb +181 -0
  49. data/spec/unit/command/delete_policy_group_spec.rb +207 -0
  50. data/spec/unit/command/delete_policy_spec.rb +207 -0
  51. data/spec/unit/command/generate_spec.rb +41 -1
  52. data/spec/unit/command/generator_commands/cookbook_spec.rb +1 -1
  53. data/spec/unit/command/generator_commands/policyfile_spec.rb +1 -1
  54. data/spec/unit/command/install_spec.rb +24 -0
  55. data/spec/unit/command/shell_init_spec.rb +176 -5
  56. data/spec/unit/command/undelete_spec.rb +246 -0
  57. data/spec/unit/helpers_spec.rb +24 -0
  58. data/spec/unit/policyfile/lister_spec.rb +16 -0
  59. data/spec/unit/policyfile/undo_record_spec.rb +260 -0
  60. data/spec/unit/policyfile/undo_stack_spec.rb +266 -0
  61. data/spec/unit/policyfile_lock_serialization_spec.rb +41 -0
  62. data/spec/unit/policyfile_services/clean_policy_cookbooks_spec.rb +275 -0
  63. data/spec/unit/policyfile_services/rm_policy_group_spec.rb +241 -0
  64. data/spec/unit/policyfile_services/rm_policy_spec.rb +266 -0
  65. data/spec/unit/policyfile_services/show_policy_spec.rb +52 -2
  66. data/spec/unit/policyfile_services/undelete_spec.rb +304 -0
  67. metadata +43 -91
@@ -255,6 +255,7 @@ module ChefDK
255
255
  def build_from_lock_data(lock_data)
256
256
  set_name_from_lock_data(lock_data)
257
257
  set_run_list_from_lock_data(lock_data)
258
+ set_named_run_lists_from_lock_data(lock_data)
258
259
  set_cookbook_locks_from_lock_data(lock_data)
259
260
  set_attributes_from_lock_data(lock_data)
260
261
  set_solution_dependencies_from_lock_data(lock_data)
@@ -264,6 +265,7 @@ module ChefDK
264
265
  def build_from_archive(lock_data)
265
266
  set_name_from_lock_data(lock_data)
266
267
  set_run_list_from_lock_data(lock_data)
268
+ set_named_run_lists_from_lock_data(lock_data)
267
269
  set_cookbook_locks_as_archives_from_lock_data(lock_data)
268
270
  set_attributes_from_lock_data(lock_data)
269
271
  set_solution_dependencies_from_lock_data(lock_data)
@@ -416,6 +418,34 @@ module ChefDK
416
418
  @run_list = run_list_attribute
417
419
  end
418
420
 
421
+ def set_named_run_lists_from_lock_data(lock_data)
422
+ return unless lock_data.key?("named_run_lists")
423
+
424
+ lock_data_named_run_lists = lock_data["named_run_lists"]
425
+
426
+ unless lock_data_named_run_lists.kind_of?(Hash)
427
+ msg = "lockfile's named_run_lists must be a Hash (JSON object). (got: #{lock_data_named_run_lists.inspect})"
428
+ raise InvalidLockfile, msg
429
+ end
430
+
431
+ lock_data_named_run_lists.each do |name, run_list|
432
+ unless name.kind_of?(String)
433
+ msg = "Keys in lockfile's named_run_lists must be Strings. (got: #{name.inspect})"
434
+ raise InvalidLockfile, msg
435
+ end
436
+ unless run_list.kind_of?(Array)
437
+ msg = "Values in lockfile's named_run_lists must be Arrays. (got: #{run_list.inspect})"
438
+ raise InvalidLockfile, msg
439
+ end
440
+ bad_run_list_items = run_list.select { |e| e !~ RUN_LIST_ITEM_FORMAT }
441
+ unless bad_run_list_items.empty?
442
+ msg = "lockfile's run_list items must be formatted like `recipe[$COOKBOOK_NAME::$RECIPE_NAME]'. Invalid items: `#{bad_run_list_items.join("' `")}'"
443
+ raise InvalidLockfile, msg
444
+ end
445
+ end
446
+ @named_run_lists = lock_data_named_run_lists
447
+ end
448
+
419
449
  def set_cookbook_locks_from_lock_data(lock_data)
420
450
  cookbook_lock_data = lock_data["cookbook_locks"]
421
451
 
@@ -15,6 +15,7 @@
15
15
  # limitations under the License.
16
16
  #
17
17
 
18
+ require 'chef-dk/exceptions'
18
19
  require 'chef-dk/service_exceptions'
19
20
  require 'chef-dk/policyfile/lister'
20
21
 
@@ -53,7 +54,7 @@ module ChefDK
53
54
 
54
55
  message = "Failed to delete some policy revisions:\n" + details.join("\n") + "\n"
55
56
 
56
- raise PolicyfileCleanError.new(message, nil)
57
+ raise PolicyfileCleanError.new(message, MultipleErrors.new("multiple errors"))
57
58
  end
58
59
 
59
60
  true
@@ -74,9 +75,9 @@ module ChefDK
74
75
  end
75
76
 
76
77
  def http_client
77
- @http_client ||= ChefDK::AuthenticatedHTTP.new(config.chef_server_url,
78
- signing_key_filename: config.client_key,
79
- client_name: config.node_name)
78
+ @http_client ||= ChefDK::AuthenticatedHTTP.new(chef_config.chef_server_url,
79
+ signing_key_filename: chef_config.client_key,
80
+ client_name: chef_config.node_name)
80
81
  end
81
82
 
82
83
  private
@@ -0,0 +1,125 @@
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 'set'
19
+
20
+ require 'chef-dk/authenticated_http'
21
+ require 'chef-dk/service_exceptions'
22
+
23
+ module ChefDK
24
+ module PolicyfileServices
25
+
26
+ class CleanPolicyCookbooks
27
+
28
+ attr_reader :chef_config
29
+
30
+ attr_reader :ui
31
+
32
+ def initialize(config: nil, ui: nil)
33
+ @chef_config = config
34
+ @ui = ui
35
+
36
+ @all_cookbooks = nil
37
+ @active_cookbooks = nil
38
+ @all_policies = nil
39
+ end
40
+
41
+ def run
42
+ gc_cookbooks
43
+ rescue => e
44
+ raise PolicyCookbookCleanError.new("Failed to cleanup policy cookbooks", e)
45
+ end
46
+
47
+ def gc_cookbooks
48
+ cookbooks = cookbooks_to_clean
49
+
50
+ if cookbooks.empty?
51
+ ui.msg("No cookbooks deleted.")
52
+ end
53
+
54
+ cookbooks.each do |name, identifiers|
55
+ identifiers.each do |identifier|
56
+ http_client.delete("/cookbook_artifacts/#{name}/#{identifier}")
57
+ ui.msg("DELETE #{name} #{identifier}")
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ def all_cookbooks
64
+ cookbook_list = http_client.get("/cookbook_artifacts")
65
+ cookbook_list.inject({}) do |cb_map, (name, cb_info)|
66
+ cb_map[name] = cb_info["versions"].map { |v| v["identifier"] }
67
+ cb_map
68
+ end
69
+ end
70
+
71
+ def active_cookbooks
72
+ policy_revisions_by_name.inject({}) do |cb_map, (policy_name, revision_ids)|
73
+ revision_ids.each do |revision_id|
74
+ cookbook_revisions_in_policy(policy_name, revision_id).each do |cb_name, identifier|
75
+ cb_map[cb_name] ||= Set.new
76
+ cb_map[cb_name] << identifier
77
+ end
78
+ end
79
+ cb_map
80
+ end
81
+ end
82
+
83
+ def cookbooks_to_clean
84
+ active_cbs = active_cookbooks
85
+
86
+ all_cookbooks.inject({}) do |cb_map, (cb_name, revisions)|
87
+ active_revs = active_cbs[cb_name] || Set.new
88
+ inactive_revs = Set.new(revisions) - active_revs
89
+ cb_map[cb_name] = inactive_revs unless inactive_revs.empty?
90
+
91
+ cb_map
92
+ end
93
+ end
94
+
95
+ # @api private
96
+ def policy_revisions_by_name
97
+ policies_list = http_client.get("/policies")
98
+ policies_list.inject({}) do |policies_map, (name, policy_info)|
99
+ policies_map[name] = policy_info["revisions"].keys
100
+ policies_map
101
+ end
102
+ end
103
+
104
+ # @api private
105
+ def cookbook_revisions_in_policy(name, revision_id)
106
+ policy_revision_data = http_client.get("/policies/#{name}/revisions/#{revision_id}")
107
+
108
+ policy_revision_data["cookbook_locks"].inject({}) do |cb_map, (cb_name, lock_info)|
109
+ cb_map[cb_name] = lock_info["identifier"]
110
+ cb_map
111
+ end
112
+ end
113
+
114
+ # @api private
115
+ # An instance of ChefDK::AuthenticatedHTTP configured with the user's
116
+ # server URL and credentials.
117
+ def http_client
118
+ @http_client ||= ChefDK::AuthenticatedHTTP.new(chef_config.chef_server_url,
119
+ signing_key_filename: chef_config.client_key,
120
+ client_name: chef_config.node_name)
121
+ end
122
+ end
123
+ end
124
+ end
125
+
@@ -0,0 +1,142 @@
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 'chef-dk/service_exceptions'
19
+ require 'chef-dk/authenticated_http'
20
+ require 'chef-dk/policyfile/undo_stack'
21
+ require 'chef-dk/policyfile/undo_record'
22
+
23
+ module ChefDK
24
+ module PolicyfileServices
25
+
26
+ class RmPolicy
27
+
28
+ attr_reader :policy_name
29
+
30
+ # @api private
31
+ attr_reader :chef_config
32
+
33
+ # @api private
34
+ attr_reader :ui
35
+
36
+ # @api private
37
+ attr_reader :undo_record
38
+
39
+ # @api private
40
+ attr_reader :undo_stack
41
+
42
+ def initialize(config: nil, ui: nil, policy_name: nil)
43
+ @chef_config = config
44
+ @ui = ui
45
+ @policy_name = policy_name
46
+
47
+ @policy_revision_data = nil
48
+ @policy_exists = false
49
+ @policy_group_data = nil
50
+
51
+ @undo_record = Policyfile::UndoRecord.new
52
+ @undo_stack = Policyfile::UndoStack.new
53
+ end
54
+
55
+ def run
56
+ unless policy_exists?
57
+ ui.err("Policy '#{policy_name}' does not exist on the server")
58
+ return false
59
+ end
60
+
61
+ undo_record.description = "delete-policy #{policy_name}"
62
+
63
+ unless policy_has_no_revisions?
64
+ gather_policy_data_for_undo
65
+ end
66
+
67
+ http_client.delete("/policies/#{policy_name}")
68
+ undo_stack.push(undo_record)
69
+ ui.err("Removed policy '#{policy_name}'.")
70
+ rescue => e
71
+ raise DeletePolicyError.new("Failed to delete policy '#{policy_name}'", e)
72
+ end
73
+
74
+ # @api private
75
+ # An instance of ChefDK::AuthenticatedHTTP configured with the user's
76
+ # server URL and credentials.
77
+ def http_client
78
+ @http_client ||= ChefDK::AuthenticatedHTTP.new(chef_config.chef_server_url,
79
+ signing_key_filename: chef_config.client_key,
80
+ client_name: chef_config.node_name)
81
+ end
82
+
83
+ private
84
+
85
+ def policy_has_no_revisions?
86
+ policy_revision_data.empty? || policy_revision_data["revisions"].empty?
87
+ end
88
+
89
+ def gather_policy_data_for_undo
90
+ revisions = policy_revision_data["revisions"].keys
91
+
92
+ revisions.each do |revision_id|
93
+ policy_revision_data = http_client.get("/policies/#{policy_name}/revisions/#{revision_id}")
94
+ policy_groups = policy_groups_using_revision(revision_id)
95
+ if policy_groups.empty?
96
+ undo_record.add_policy_revision(policy_name, nil, policy_revision_data)
97
+ else
98
+ policy_groups.each do |policy_group|
99
+ undo_record.add_policy_revision(policy_name, policy_group, policy_revision_data)
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ def policy_groups_using_revision(revision_id)
106
+ groups = []
107
+ policy_group_data.each do |group_name, group_info|
108
+ next unless group_info.key?("policies") && !group_info["policies"].empty?
109
+ next unless group_info["policies"].key?(policy_name)
110
+ next unless group_info["policies"][policy_name]["revision_id"] == revision_id
111
+ groups << group_name if group_info
112
+ end
113
+ groups
114
+ end
115
+
116
+ def policy_group_data
117
+ @policy_group_data ||= http_client.get("/policy_groups")
118
+ end
119
+
120
+ def policy_exists?
121
+ return true if @policy_exists
122
+ fetch_policy_revision_data
123
+ @policy_exists
124
+ end
125
+
126
+ def policy_revision_data
127
+ return @policy_revision_data if @policy_exists
128
+ fetch_policy_revision_data
129
+ end
130
+
131
+ def fetch_policy_revision_data
132
+ @policy_revision_data = http_client.get("/policies/#{policy_name}")
133
+ @policy_exists = true
134
+ rescue Net::HTTPServerException => e
135
+ raise unless e.response.code == "404"
136
+ @policy_exists = false
137
+ end
138
+
139
+ end
140
+ end
141
+ end
142
+
@@ -0,0 +1,86 @@
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 'chef-dk/service_exceptions'
19
+ require 'chef-dk/authenticated_http'
20
+ require 'chef-dk/policyfile/undo_stack'
21
+ require 'chef-dk/policyfile/undo_record'
22
+
23
+ module ChefDK
24
+ module PolicyfileServices
25
+
26
+ class RmPolicyGroup
27
+
28
+ attr_reader :policy_group
29
+
30
+ # @api private
31
+ attr_reader :chef_config
32
+
33
+ # @api private
34
+ attr_reader :ui
35
+
36
+ # @api private
37
+ attr_reader :undo_record
38
+
39
+ # @api private
40
+ attr_reader :undo_stack
41
+
42
+ def initialize(config: nil, ui: nil, policy_group: nil)
43
+ @chef_config = config
44
+ @ui = ui
45
+ @policy_group = policy_group
46
+
47
+ @undo_record = Policyfile::UndoRecord.new
48
+ @undo_stack = Policyfile::UndoStack.new
49
+ end
50
+
51
+ def run
52
+ undo_record.description = "delete-policy-group #{policy_group}"
53
+ policy_group_list = http_client.get("/policy_groups")
54
+
55
+ unless policy_group_list.has_key?(policy_group)
56
+ ui.err("Policy group '#{policy_group}' does not exist on the server")
57
+ return false
58
+ end
59
+ policy_group_info = policy_group_list[policy_group]
60
+
61
+ policies_in_group = policy_group_info["policies"] || []
62
+ policies_in_group.each do |name, revision_info|
63
+ rev_id = revision_info["revision_id"]
64
+ policy_revision_data = http_client.get("/policies/#{name}/revisions/#{rev_id}")
65
+ undo_record.add_policy_revision(name, policy_group, policy_revision_data)
66
+ end
67
+ http_client.delete("/policy_groups/#{policy_group}")
68
+ undo_record.add_policy_group(policy_group)
69
+ ui.err("Removed policy group '#{policy_group}'.")
70
+ undo_stack.push(undo_record)
71
+ rescue => e
72
+ raise DeletePolicyGroupError.new("Failed to delete policy group '#{policy_group}'", e)
73
+ end
74
+
75
+ # @api private
76
+ # An instance of ChefDK::AuthenticatedHTTP configured with the user's
77
+ # server URL and credentials.
78
+ def http_client
79
+ @http_client ||= ChefDK::AuthenticatedHTTP.new(chef_config.chef_server_url,
80
+ signing_key_filename: chef_config.client_key,
81
+ client_name: chef_config.node_name)
82
+ end
83
+ end
84
+ end
85
+ end
86
+
@@ -163,7 +163,7 @@ module ChefDK
163
163
  report.h1(policy_name)
164
164
  rev_id_by_group = policy_lister.revision_ids_by_group_for(policy_name)
165
165
 
166
- if rev_id_by_group.empty?
166
+ if rev_id_by_group.empty? || rev_id_by_group.all? { |_k, rev| rev.nil? }
167
167
  ui.err("No policies named '#{policy_name}' are associated with a policy group")
168
168
  ui.err("")
169
169
  elsif show_summary_diff?
@@ -0,0 +1,108 @@
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 'chef-dk/authenticated_http'
19
+ require 'chef-dk/service_exceptions'
20
+ require 'chef-dk/policyfile/undo_stack'
21
+
22
+ module ChefDK
23
+ module PolicyfileServices
24
+ class Undelete
25
+
26
+ attr_reader :ui
27
+
28
+ attr_reader :chef_config
29
+
30
+ attr_reader :undo_record_id
31
+
32
+ def initialize(undo_record_id: nil, config: nil, ui: nil)
33
+ @chef_config = config
34
+ @ui = ui
35
+ @undo_record_id = undo_record_id
36
+
37
+ @http_client = nil
38
+ @undo_stack = nil
39
+ end
40
+
41
+ # In addition to the #run method, this class also has #list as a public
42
+ # entry point. This prints the list of undoable items, with descriptions.
43
+ def list
44
+ if undo_stack.empty?
45
+ ui.err("Nothing to undo.")
46
+ else
47
+ messages = []
48
+ undo_stack.each_with_id do |timestamp, undo_record|
49
+ messages.unshift("#{timestamp}: #{undo_record.description}")
50
+ end
51
+ messages.each { |m| ui.msg(m) }
52
+ end
53
+ end
54
+
55
+ def run
56
+ if undo_record_id
57
+ if undo_stack.has_id?(undo_record_id)
58
+ undo_stack.delete(undo_record_id) { |undo_record| restore(undo_record) }
59
+ else
60
+ ui.err("No undo record with id '#{undo_record_id}' exists")
61
+ end
62
+ else
63
+ undo_stack.pop { |undo_record| restore(undo_record) }
64
+ end
65
+ rescue => e
66
+ raise UndeleteError.new("Failed to undelete.", e)
67
+ end
68
+
69
+ def undo_stack
70
+ @undo_stack ||= Policyfile::UndoStack.new
71
+ end
72
+
73
+ def http_client
74
+ @http_client ||= ChefDK::AuthenticatedHTTP.new(chef_config.chef_server_url,
75
+ signing_key_filename: chef_config.client_key,
76
+ client_name: chef_config.node_name)
77
+ end
78
+
79
+ private
80
+
81
+ def restore(undo_record)
82
+ undo_record.policy_revisions.each do |policy_info|
83
+ if policy_info.policy_group.nil?
84
+ recreate_as_orphan(policy_info)
85
+ else
86
+ recreate_and_associate_to_group(policy_info)
87
+ end
88
+ end
89
+ if ( restored_policy_group = undo_record.policy_groups.first )
90
+ ui.msg("Restored policy group '#{restored_policy_group}'")
91
+ end
92
+ end
93
+
94
+ def recreate_as_orphan(policy_info)
95
+ rel_uri = "/policies/#{policy_info.policy_name}/revisions"
96
+ http_client.post(rel_uri, policy_info.data)
97
+ ui.msg("Restored policy '#{policy_info.policy_name}'")
98
+ end
99
+
100
+ def recreate_and_associate_to_group(policy_info)
101
+ rel_uri = "/policy_groups/#{policy_info.policy_group}/policies/#{policy_info.policy_name}"
102
+ http_client.put(rel_uri, policy_info.data)
103
+ ui.msg("Restored policy '#{policy_info.policy_name}'")
104
+ end
105
+
106
+ end
107
+ end
108
+ end