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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/chef-dk/builtin_commands.rb +10 -0
- data/lib/chef-dk/command/base.rb +2 -2
- data/lib/chef-dk/command/clean_policy_cookbooks.rb +116 -0
- data/lib/chef-dk/command/clean_policy_revisions.rb +113 -0
- data/lib/chef-dk/command/delete_policy.rb +122 -0
- data/lib/chef-dk/command/delete_policy_group.rb +122 -0
- data/lib/chef-dk/command/export.rb +3 -3
- data/lib/chef-dk/command/generate.rb +8 -0
- data/lib/chef-dk/command/generator_commands/app.rb +1 -1
- data/lib/chef-dk/command/generator_commands/cookbook.rb +1 -1
- data/lib/chef-dk/command/generator_commands/policyfile.rb +1 -1
- data/lib/chef-dk/command/generator_commands/repo.rb +1 -1
- data/lib/chef-dk/command/install.rb +22 -5
- data/lib/chef-dk/command/provision.rb +0 -4
- data/lib/chef-dk/command/push.rb +1 -2
- data/lib/chef-dk/command/shell_init.rb +65 -6
- data/lib/chef-dk/command/show_policy.rb +1 -2
- data/lib/chef-dk/command/undelete.rb +155 -0
- data/lib/chef-dk/command/update.rb +5 -5
- data/lib/chef-dk/command/verify.rb +61 -17
- data/lib/chef-dk/completions/bash.sh.erb +5 -0
- data/lib/chef-dk/completions/chef.fish.erb +10 -0
- data/lib/chef-dk/completions/zsh.zsh.erb +21 -0
- data/lib/chef-dk/exceptions.rb +12 -0
- data/lib/chef-dk/helpers.rb +17 -0
- data/lib/chef-dk/policyfile/community_cookbook_source.rb +0 -3
- data/lib/chef-dk/policyfile/lister.rb +3 -1
- data/lib/chef-dk/policyfile/undo_record.rb +142 -0
- data/lib/chef-dk/policyfile/undo_stack.rb +130 -0
- data/lib/chef-dk/policyfile_lock.rb +30 -0
- data/lib/chef-dk/policyfile_services/clean_policies.rb +5 -4
- data/lib/chef-dk/policyfile_services/clean_policy_cookbooks.rb +125 -0
- data/lib/chef-dk/policyfile_services/rm_policy.rb +142 -0
- data/lib/chef-dk/policyfile_services/rm_policy_group.rb +86 -0
- data/lib/chef-dk/policyfile_services/show_policy.rb +1 -1
- data/lib/chef-dk/policyfile_services/undelete.rb +108 -0
- data/lib/chef-dk/service_exceptions.rb +11 -0
- data/lib/chef-dk/skeletons/code_generator/files/default/chefignore +6 -2
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/README.md +1 -1
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +1 -1
- data/lib/chef-dk/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +1 -1
- data/lib/chef-dk/version.rb +1 -1
- data/lib/kitchen/provisioner/policyfile_zero.rb +4 -1
- data/spec/unit/command/base_spec.rb +26 -1
- data/spec/unit/command/clean_policy_cookbooks_spec.rb +181 -0
- data/spec/unit/command/clean_policy_revisions_spec.rb +181 -0
- data/spec/unit/command/delete_policy_group_spec.rb +207 -0
- data/spec/unit/command/delete_policy_spec.rb +207 -0
- data/spec/unit/command/generate_spec.rb +41 -1
- data/spec/unit/command/generator_commands/cookbook_spec.rb +1 -1
- data/spec/unit/command/generator_commands/policyfile_spec.rb +1 -1
- data/spec/unit/command/install_spec.rb +24 -0
- data/spec/unit/command/shell_init_spec.rb +176 -5
- data/spec/unit/command/undelete_spec.rb +246 -0
- data/spec/unit/helpers_spec.rb +24 -0
- data/spec/unit/policyfile/lister_spec.rb +16 -0
- data/spec/unit/policyfile/undo_record_spec.rb +260 -0
- data/spec/unit/policyfile/undo_stack_spec.rb +266 -0
- data/spec/unit/policyfile_lock_serialization_spec.rb +41 -0
- data/spec/unit/policyfile_services/clean_policy_cookbooks_spec.rb +275 -0
- data/spec/unit/policyfile_services/rm_policy_group_spec.rb +241 -0
- data/spec/unit/policyfile_services/rm_policy_spec.rb +266 -0
- data/spec/unit/policyfile_services/show_policy_spec.rb +52 -2
- data/spec/unit/policyfile_services/undelete_spec.rb +304 -0
- 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,
|
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(
|
78
|
-
signing_key_filename:
|
79
|
-
client_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
|