knife-tidy 2.0.9 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/conf/substitutions.json.example +10 -0
- data/lib/chef/knife/tidy_backup_clean.rb +24 -25
- data/lib/chef/knife/tidy_notify.rb +9 -9
- data/lib/chef/knife/tidy_server_clean.rb +3 -3
- data/lib/chef/knife/tidy_server_report.rb +20 -2
- data/lib/chef/tidy_acls.rb +15 -15
- data/lib/chef/tidy_common.rb +19 -2
- data/lib/chef/tidy_substitutions.rb +4 -4
- data/lib/knife-tidy/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebbadbfe49e6402c189f63e8e0290eeb93d409f89f4220ef9ad6bdc96b0b455f
|
4
|
+
data.tar.gz: ee7f3392eac804aeec3490c33c1e02d9d22d1bd038f3a1eb8222fd9d9c660dd9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e78b266e0482121cd3d551a9d683cd79b85aae16bb31d53260c2c73a7ceae1080052cd582957b55a23099c7799ed8312e0a5fcde1b920640497af04872894ab7
|
7
|
+
data.tar.gz: b1e97749b9ed73fe512b76a45291541b070eb730ded2f86dc4de1f355258e319017338e183c53a0dd2b4671f98a513ba4a5ca69053e6dc834359f396e15257ee
|
@@ -4,15 +4,15 @@ class Chef
|
|
4
4
|
class Knife
|
5
5
|
class TidyBackupClean < Knife
|
6
6
|
deps do
|
7
|
-
require "chef/
|
7
|
+
require "chef/cookbook/cookbook_version_loader"
|
8
8
|
require "chef/cookbook/metadata"
|
9
9
|
require "chef/role"
|
10
10
|
require "chef/run_list"
|
11
11
|
require_relative "../tidy_substitutions"
|
12
12
|
require_relative "../tidy_acls"
|
13
|
-
require "ffi_yajl"
|
14
|
-
require "fileutils"
|
15
|
-
require "securerandom"
|
13
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
14
|
+
require "fileutils" unless defined?(FileUtils)
|
15
|
+
require "securerandom" unless defined?(SecureRandom)
|
16
16
|
end
|
17
17
|
|
18
18
|
banner "knife tidy backup clean (options)"
|
@@ -25,7 +25,7 @@ class Chef
|
|
25
25
|
|
26
26
|
option :gsub_file,
|
27
27
|
long: "--gsub-file path/to/gsub/file",
|
28
|
-
description: "The path to the file used for substitutions. If non-
|
28
|
+
description: "The path to the file used for substitutions. If non-existent, a boiler plate one will be created."
|
29
29
|
|
30
30
|
option :gen_gsub,
|
31
31
|
long: "--gen-gsub",
|
@@ -75,7 +75,7 @@ class Chef
|
|
75
75
|
tidy.global_user_names.each do |user|
|
76
76
|
email = ""
|
77
77
|
ui.stdout.puts "INFO: Validating #{user}"
|
78
|
-
the_user =
|
78
|
+
the_user = tidy.json_file_to_hash(File.join(tidy.users_path, "#{user}.json"), symbolize_names: false)
|
79
79
|
if the_user.key?("email") && the_user["email"].match(/\A[^@\s]+@[^@\s]+\z/)
|
80
80
|
if emails_seen.include?(the_user["email"])
|
81
81
|
ui.stdout.puts "REPAIRING: Already saw #{user}'s email, creating a unique one."
|
@@ -147,7 +147,7 @@ class Chef
|
|
147
147
|
add_cookbook_name_to_metadata(cookbook_name, rb_path) if lines.empty?
|
148
148
|
else
|
149
149
|
if ::File.exist?(json_path)
|
150
|
-
metadata =
|
150
|
+
metadata = tidy.json_file_to_hash(json_path, symbolize_names: false)
|
151
151
|
if metadata["name"] != cookbook_name
|
152
152
|
metadata["name"] = cookbook_name
|
153
153
|
ui.stdout.puts "REPAIRING: Correcting `name` in #{json_path}`"
|
@@ -161,26 +161,24 @@ class Chef
|
|
161
161
|
end
|
162
162
|
|
163
163
|
def load_cookbooks(org)
|
164
|
-
|
165
|
-
|
164
|
+
for_each_cookbook_path(org) do |cookbook|
|
165
|
+
cl = Chef::Cookbook::CookbookVersionLoader.new(cookbook)
|
166
166
|
ui.stdout.puts "INFO: Loading #{cookbook}"
|
167
|
-
ret = cl.
|
167
|
+
ret = cl.load!
|
168
168
|
if ret.nil?
|
169
169
|
action_needed("ACTION NEEDED: Something's wrong with the #{cookbook} cookbook in org #{org} - cannot load it! Moving to cookbooks.broken folder.")
|
170
|
-
|
170
|
+
broken_cookbooks_add(org, cookbook)
|
171
171
|
end
|
172
172
|
end
|
173
|
-
rescue LoadError => e
|
173
|
+
rescue LoadError, Exceptions::MetadataNotValid => e
|
174
174
|
ui.error e
|
175
175
|
exit 1
|
176
176
|
end
|
177
177
|
|
178
|
-
def
|
178
|
+
def broken_cookbooks_add(org, cookbook_path)
|
179
179
|
broken_path = ::File.join(tidy.org_path(org), "cookbooks.broken")
|
180
180
|
FileUtils.mkdir(broken_path) unless ::File.directory?(broken_path)
|
181
|
-
|
182
|
-
FileUtils.mv(cb, broken_path, verbose: true, force: true)
|
183
|
-
end
|
181
|
+
FileUtils.mv(cookbook_path, broken_path, verbose: true, force: true)
|
184
182
|
end
|
185
183
|
|
186
184
|
def generate_new_metadata(org)
|
@@ -229,7 +227,7 @@ class Chef
|
|
229
227
|
|
230
228
|
def fix_metadata_fields(cookbook_path)
|
231
229
|
json_path = ::File.join(cookbook_path, "metadata.json")
|
232
|
-
metadata =
|
230
|
+
metadata = tidy.json_file_to_hash(json_path, symbolize_names: false)
|
233
231
|
md = metadata.dup
|
234
232
|
metadata.each_pair do |key, value|
|
235
233
|
if value.nil?
|
@@ -299,7 +297,7 @@ class Chef
|
|
299
297
|
|
300
298
|
def substitutions_file
|
301
299
|
sub_file_path = ::File.expand_path(config[:gsub_file])
|
302
|
-
ui.error "
|
300
|
+
ui.error "Substitutions file #{sub_file_path} does not exist!" unless ::File.exist?(sub_file_path)
|
303
301
|
@substitutions_file ||= sub_file_path
|
304
302
|
end
|
305
303
|
|
@@ -351,7 +349,7 @@ class Chef
|
|
351
349
|
end
|
352
350
|
|
353
351
|
def repair_role_run_lists(role_path)
|
354
|
-
the_role =
|
352
|
+
the_role = tidy.json_file_to_hash(role_path, symbolize_names: false)
|
355
353
|
new_role = the_role.clone
|
356
354
|
rl = Chef::RunList.new
|
357
355
|
new_role["run_list"] = []
|
@@ -384,7 +382,7 @@ class Chef
|
|
384
382
|
for_each_role(org) do |role_path|
|
385
383
|
ui.stdout.puts "INFO: Validating Role at #{role_path}"
|
386
384
|
begin
|
387
|
-
Chef::Role.from_hash(
|
385
|
+
Chef::Role.from_hash(tidy.json_file_to_hash(role_path, symbolize_names: false))
|
388
386
|
rescue ArgumentError
|
389
387
|
repair_role_run_lists(role_path)
|
390
388
|
end
|
@@ -394,21 +392,22 @@ class Chef
|
|
394
392
|
def validate_clients_group(org)
|
395
393
|
ui.stdout.puts "INFO: validating all clients for org #{org} exist in clients group"
|
396
394
|
clients_group_path = ::File.join(tidy.groups_path(org), "clients.json")
|
397
|
-
existing_group_data =
|
395
|
+
existing_group_data = tidy.json_file_to_hash(clients_group_path, symbolize_names: false)
|
398
396
|
existing_group_data["clients"] = [] unless existing_group_data.key?("clients")
|
399
397
|
if existing_group_data["clients"].length != tidy.client_names(org).length
|
400
398
|
ui.stdout.puts "REPAIRING: Adding #{(existing_group_data["clients"].length - tidy.client_names(org).length).abs} missing clients into #{org}'s client group file #{clients_group_path}"
|
401
399
|
existing_group_data["clients"] = (existing_group_data["clients"] + tidy.client_names(org)).uniq
|
402
|
-
|
403
|
-
|
404
|
-
|
400
|
+
end
|
401
|
+
existing_group_data["clients"] = existing_group_data["clients"].sort
|
402
|
+
::File.open(clients_group_path, "w") do |f|
|
403
|
+
f.write(Chef::JSONCompat.to_json_pretty(existing_group_data))
|
405
404
|
end
|
406
405
|
end
|
407
406
|
|
408
407
|
def validate_invitations(org)
|
409
408
|
invite_file = tidy.invitations_path(org)
|
410
409
|
ui.stdout.puts "INFO: validating org #{org} invites in #{invite_file}"
|
411
|
-
invitations =
|
410
|
+
invitations = tidy.json_file_to_hash(invite_file, symbolize_names: false)
|
412
411
|
invitations_new = []
|
413
412
|
invitations.each do |invite|
|
414
413
|
if invite["username"].nil?
|
@@ -4,7 +4,7 @@ class Chef
|
|
4
4
|
class Knife
|
5
5
|
class TidyNotify < Knife
|
6
6
|
deps do
|
7
|
-
require "ffi_yajl"
|
7
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
8
8
|
require "net/smtp"
|
9
9
|
end
|
10
10
|
|
@@ -14,39 +14,39 @@ class Chef
|
|
14
14
|
short: "-s SERVER_NAME",
|
15
15
|
long: "--smtp_server SERVER_NAME",
|
16
16
|
default: "localhost",
|
17
|
-
description: "SMTP Server to be used for
|
17
|
+
description: "SMTP Server to be used for emailing reports to organization admins (defaults to localhost)"
|
18
18
|
|
19
19
|
option :smtp_port,
|
20
20
|
short: "-p SMTP_PORT",
|
21
21
|
long: "--smtp_port SMTP_PORT",
|
22
22
|
default: 25,
|
23
|
-
description: "SMTP port to be used for
|
23
|
+
description: "SMTP port to be used for emailing reports to organization admins (defaults to 25)"
|
24
24
|
|
25
25
|
option :smtp_helo,
|
26
26
|
short: "-h SMTP_HELO",
|
27
27
|
long: "--smtp_helo SMTP_HELO",
|
28
28
|
default: "localhost",
|
29
|
-
description: "SMTP HELO to be used for
|
29
|
+
description: "SMTP HELO to be used for emailing reports to organization admins (defaults to localhost)"
|
30
30
|
|
31
31
|
option :smtp_username,
|
32
32
|
short: "-u SMTP_USERNAME",
|
33
33
|
long: "--smtp_username SMTP_USERNAME",
|
34
|
-
description: "SMTP Username to be used for
|
34
|
+
description: "SMTP Username to be used for emailing reports to organization admins"
|
35
35
|
|
36
36
|
option :smtp_password,
|
37
37
|
long: "--smtp_password SMTP_PASSWORD",
|
38
|
-
description: "SMTP Password to be used for
|
38
|
+
description: "SMTP Password to be used for emailing reports to organization admins"
|
39
39
|
|
40
40
|
option :smtp_from,
|
41
41
|
long: "--smtp_from SMTP_FROM",
|
42
|
-
description: "SMTP From address to be used for
|
42
|
+
description: "SMTP From address to be used for emailing reports to organization admins"
|
43
43
|
|
44
44
|
option :smtp_use_tls,
|
45
45
|
long: "--smtp_use_tls",
|
46
46
|
short: "-t",
|
47
47
|
default: false,
|
48
48
|
boolean: true | false,
|
49
|
-
description: "Whether TLS should be used for
|
49
|
+
description: "Whether TLS should be used for emailing reports to organization admins (defaults to false if omitted)"
|
50
50
|
|
51
51
|
include Knife::TidyBase
|
52
52
|
|
@@ -88,7 +88,7 @@ class Chef
|
|
88
88
|
file_name = "#{reports_dir}/#{org}#{report}"
|
89
89
|
ui.info(" Parsing file #{file_name}")
|
90
90
|
json_string = File.read(file_name)
|
91
|
-
reports[org][report] =
|
91
|
+
reports[org][report] = tidy.json_file_to_hash(json_string, symbolize_names: false)
|
92
92
|
rescue Errno::ENOENT
|
93
93
|
ui.info(" Skipping file #{file_name} - not found for organization #{org}")
|
94
94
|
reports[org][report] = {}
|
@@ -6,7 +6,7 @@ class Chef
|
|
6
6
|
include Knife::TidyBase
|
7
7
|
|
8
8
|
deps do
|
9
|
-
require "ffi_yajl"
|
9
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
10
10
|
require "chef/util/threaded_job_queue"
|
11
11
|
end
|
12
12
|
|
@@ -91,7 +91,7 @@ class Chef
|
|
91
91
|
return unless ::File.exist?(unused_cookbooks_file)
|
92
92
|
|
93
93
|
ui.stdout.puts "INFO: Cleaning cookbooks for Org: #{org}, using #{unused_cookbooks_file}"
|
94
|
-
unused_cookbooks =
|
94
|
+
unused_cookbooks = tidy.json_file_to_hash(unused_cookbooks_file, symbolize_names: true)
|
95
95
|
unused_cookbooks.keys.each do |cookbook|
|
96
96
|
versions = unused_cookbooks[cookbook]
|
97
97
|
versions.each do |version|
|
@@ -118,7 +118,7 @@ class Chef
|
|
118
118
|
return unless ::File.exist?(stale_nodes_file)
|
119
119
|
|
120
120
|
ui.stdout.puts "INFO: Cleaning stale nodes for Org: #{org}, using #{stale_nodes_file}"
|
121
|
-
stale_nodes =
|
121
|
+
stale_nodes = tidy.json_file_to_hash(stale_nodes_file, symbolize_names: true)
|
122
122
|
stale_nodes[:list].each do |node|
|
123
123
|
queue << -> { delete_node_job(org, node) }
|
124
124
|
end
|
@@ -7,7 +7,7 @@ class Chef
|
|
7
7
|
include Knife::TidyBase
|
8
8
|
|
9
9
|
deps do
|
10
|
-
require "ffi_yajl"
|
10
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
11
11
|
end
|
12
12
|
|
13
13
|
banner "knife tidy server report (options)"
|
@@ -17,6 +17,11 @@ class Chef
|
|
17
17
|
default: 30,
|
18
18
|
description: "Maximum number of days since last checkin before node is considered stale (default: 30)"
|
19
19
|
|
20
|
+
option :keep_versions,
|
21
|
+
long: "--keep-versions MIN",
|
22
|
+
default: 0,
|
23
|
+
description: "Keep a minimum of this many versions of each cookbook (default: 0)"
|
24
|
+
|
20
25
|
def run
|
21
26
|
ensure_reports_dir!
|
22
27
|
FileUtils.rm_f(server_warnings_file_path)
|
@@ -32,6 +37,7 @@ class Chef
|
|
32
37
|
|
33
38
|
stale_orgs = []
|
34
39
|
node_threshold = config[:node_threshold].to_i
|
40
|
+
keep_versions = config[:keep_versions].to_i
|
35
41
|
|
36
42
|
orgs.each do |org|
|
37
43
|
pre_12_3_nodes = []
|
@@ -76,6 +82,9 @@ class Chef
|
|
76
82
|
end
|
77
83
|
end
|
78
84
|
|
85
|
+
used_cookbooks = keep_cookbook_versions(cb_list, keep_versions)
|
86
|
+
|
87
|
+
Chef::Log.debug("Used cookbook list before checking environments: #{used_cookbooks}")
|
79
88
|
pins = environment_constraints(org)
|
80
89
|
used_cookbooks = check_environment_pins(used_cookbooks, pins, cb_list)
|
81
90
|
|
@@ -99,7 +108,7 @@ class Chef
|
|
99
108
|
action_needed(pre_12_3_message, server_warnings_file_path)
|
100
109
|
end
|
101
110
|
if unconverged_recent_nodes.length > 0
|
102
|
-
unconverged_recent_message = "#{unconverged_recent_nodes.length} nodes have been created in the last hour that have yet to converge in organization #{org}. These nodes WILL NOT be factored in the stale cookbook
|
111
|
+
unconverged_recent_message = "#{unconverged_recent_nodes.length} nodes have been created in the last hour that have yet to converge in organization #{org}. These nodes WILL NOT be factored in the stale cookbook versions report. Continuing with the server cleanup will delete cookbooks in-use by these nodes."
|
103
112
|
ui.warn(unconverged_recent_message)
|
104
113
|
action_needed(unconverged_recent_message, server_warnings_file_path)
|
105
114
|
end
|
@@ -153,6 +162,15 @@ class Chef
|
|
153
162
|
cb_list
|
154
163
|
end
|
155
164
|
|
165
|
+
def keep_cookbook_versions(cb_list, min)
|
166
|
+
retain = {}
|
167
|
+
cb_list.each do |name, versions|
|
168
|
+
keep = versions.sort { |a, b| Gem::Version.new(a) <=> Gem::Version.new(b) }.last(min)
|
169
|
+
retain[name] = keep
|
170
|
+
end
|
171
|
+
retain
|
172
|
+
end
|
173
|
+
|
156
174
|
def cookbook_count(cb_list)
|
157
175
|
cb_count_list = {}
|
158
176
|
cb_list.each do |name, versions|
|
data/lib/chef/tidy_acls.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require "ffi_yajl"
|
2
|
-
require "fileutils"
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require "fileutils" unless defined?(FileUtils)
|
3
3
|
require "chef/log"
|
4
4
|
|
5
5
|
class Chef
|
@@ -20,26 +20,26 @@ class Chef
|
|
20
20
|
def load_users
|
21
21
|
@tidy.ui.stdout.puts "INFO: Loading users"
|
22
22
|
Dir[::File.join(@tidy.users_path, "*.json")].each do |user|
|
23
|
-
@users.push(
|
23
|
+
@users.push(@tidy.json_file_to_hash(user, symbolize_names: true))
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
def load_members
|
28
28
|
@tidy.ui.stdout.puts "INFO: Loading members for #{@org}"
|
29
|
-
@members =
|
29
|
+
@members = @tidy.json_file_to_hash(@tidy.members_path(@org), symbolize_names: true)
|
30
30
|
end
|
31
31
|
|
32
32
|
def load_clients
|
33
33
|
@tidy.ui.stdout.puts "INFO: Loading clients for #{@org}"
|
34
34
|
Dir[::File.join(@tidy.clients_path(@org), "*.json")].each do |client|
|
35
|
-
@clients.push(
|
35
|
+
@clients.push(@tidy.json_file_to_hash(client, symbolize_names: true))
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
def load_groups
|
40
40
|
@tidy.ui.stdout.puts "INFO: Loading groups for #{@org}"
|
41
41
|
Dir[::File.join(@tidy.groups_path(@org), "*.json")].each do |group|
|
42
|
-
@groups.push(
|
42
|
+
@groups.push(@tidy.json_file_to_hash(group, symbolize_names: true))
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -111,7 +111,7 @@ class Chef
|
|
111
111
|
|
112
112
|
def add_client_to_org(actor)
|
113
113
|
# TODO
|
114
|
-
@tidy.ui.stdout.puts "ACTION NEEDED: Client referenced in acl non-
|
114
|
+
@tidy.ui.stdout.puts "ACTION NEEDED: Client referenced in acl non-existent: #{actor}"
|
115
115
|
end
|
116
116
|
|
117
117
|
def add_actor_to_members(actor)
|
@@ -128,7 +128,7 @@ class Chef
|
|
128
128
|
|
129
129
|
def remove_group_from_acl(group, acl_file)
|
130
130
|
@tidy.ui.stdout.puts "REPAIRING: Removing invalid group: #{group} from #{acl_file}"
|
131
|
-
acl =
|
131
|
+
acl = @tidy.json_file_to_hash(acl_file, symbolize_names: false)
|
132
132
|
acl_ops.each do |op|
|
133
133
|
acl[op]["groups"].reject! { |the_group| the_group == group }
|
134
134
|
end
|
@@ -137,7 +137,7 @@ class Chef
|
|
137
137
|
|
138
138
|
# Appends the proper acls for ::server-admins and the org's read access group if they are missing.
|
139
139
|
def ensure_global_group_acls(acl_file)
|
140
|
-
acl =
|
140
|
+
acl = @tidy.json_file_to_hash(acl_file, symbolize_names: false)
|
141
141
|
acl_ops.each do |op|
|
142
142
|
unless acl[op]["groups"].include? "::server-admins"
|
143
143
|
@tidy.ui.stdout.puts "REPAIRING: Adding #{op} acl for ::server-admins in #{acl_file}"
|
@@ -152,7 +152,7 @@ class Chef
|
|
152
152
|
end
|
153
153
|
|
154
154
|
def ensure_client_read_acls(acl_file)
|
155
|
-
acl =
|
155
|
+
acl = @tidy.json_file_to_hash(acl_file, symbolize_names: false)
|
156
156
|
%w{users admins}.each do |group|
|
157
157
|
unless acl["read"]["groups"].include? group
|
158
158
|
@tidy.ui.stdout.puts "REPAIRING: Adding read acl for #{group} in #{acl_file}"
|
@@ -164,7 +164,7 @@ class Chef
|
|
164
164
|
|
165
165
|
def validate_acls
|
166
166
|
org_acls.each do |acl_file|
|
167
|
-
acl =
|
167
|
+
acl = @tidy.json_file_to_hash(acl_file, symbolize_names: false)
|
168
168
|
actors_groups = acl_actors_groups(acl)
|
169
169
|
actors_groups[:actors].each do |actor|
|
170
170
|
next if actor == "pivotal"
|
@@ -203,11 +203,11 @@ class Chef
|
|
203
203
|
@members.each do |member|
|
204
204
|
user_acl_path = ::File.join(@tidy.user_acls_path, "#{member[:user][:username]}.json")
|
205
205
|
begin
|
206
|
-
user_acl =
|
206
|
+
user_acl = @tidy.json_file_to_hash(user_acl_path, symbolize_names: false)
|
207
207
|
rescue Errno::ENOENT
|
208
208
|
@tidy.ui.stdout.puts "REPAIRING: Replacing missing user acl for #{member[:user][:username]}."
|
209
209
|
@tidy.write_new_file(default_user_acl(member), user_acl_path, backup = false)
|
210
|
-
user_acl =
|
210
|
+
user_acl = @tidy.json_file_to_hash(user_acl_path, symbolize_names: false)
|
211
211
|
end
|
212
212
|
ensure_global_group_acls(user_acl_path)
|
213
213
|
actors_groups = acl_actors_groups(user_acl)
|
@@ -221,11 +221,11 @@ class Chef
|
|
221
221
|
@clients.each do |client|
|
222
222
|
client_acl_path = ::File.join(@tidy.org_acls_path(@org), "clients", "#{client[:name]}.json")
|
223
223
|
begin
|
224
|
-
client_acl =
|
224
|
+
client_acl = @tidy.json_file_to_hash(client_acl_path, symbolize_names: false)
|
225
225
|
rescue Errno::ENOENT
|
226
226
|
@tidy.ui.stdout.puts "REPAIRING: Replacing missing client acl for #{client[:name]} in #{client_acl_path}."
|
227
227
|
@tidy.write_new_file(default_client_acl(client[:name]), client_acl_path, backup = false)
|
228
|
-
client_acl =
|
228
|
+
client_acl = @tidy.json_file_to_hash(client_acl_path, symbolize_names: false)
|
229
229
|
end
|
230
230
|
ensure_client_read_acls(client_acl_path)
|
231
231
|
end
|
data/lib/chef/tidy_common.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require "ffi_yajl"
|
2
|
-
require "fileutils"
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require "fileutils" unless defined?(FileUtils)
|
3
3
|
require "chef/knife/core/ui"
|
4
4
|
|
5
5
|
class Chef
|
@@ -149,6 +149,23 @@ class Chef
|
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
|
+
# Read a json file and return a hash of parsed content with optional symbolized keys
|
153
|
+
#
|
154
|
+
# @param [String] path to file
|
155
|
+
# @param [double splat] options to pass FFI_Yajl::Parser.parse()
|
156
|
+
#
|
157
|
+
# @return [Hash] original json content as hash
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# json_file_to_hash('/path/to/file.json', symbolize_names: true) => { foo: "bar" }
|
161
|
+
#
|
162
|
+
def json_file_to_hash(file_path, **options)
|
163
|
+
FFI_Yajl::Parser.parse(File.read(file_path), options)
|
164
|
+
rescue Errno::ENOENT, Errno::EACCES, FFI_Yajl::ParseError
|
165
|
+
puts "ERROR: unable to parse file: '#{file_path}'"
|
166
|
+
raise
|
167
|
+
end
|
168
|
+
|
152
169
|
#
|
153
170
|
# Determine the cookbook name from path
|
154
171
|
#
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require "ffi_yajl"
|
2
|
-
require "tempfile"
|
3
|
-
require "fileutils"
|
1
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
2
|
+
require "tempfile" unless defined?(Tempfile)
|
3
|
+
require "fileutils" unless defined?(FileUtils)
|
4
4
|
require "chef/log"
|
5
5
|
|
6
6
|
class Chef
|
@@ -17,7 +17,7 @@ class Chef
|
|
17
17
|
|
18
18
|
def load_data
|
19
19
|
@tidy.ui.stdout.puts "INFO: Loading substitutions from #{file_path}"
|
20
|
-
@data =
|
20
|
+
@data = @tidy.json_file_to_hash(@file_path, symbolize_names: false)
|
21
21
|
rescue Errno::ENOENT
|
22
22
|
raise NoSubstitutionFile, file_path
|
23
23
|
end
|
data/lib/knife-tidy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-tidy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Miller
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Report on stale Chef Server nodes and cookbooks and clean up data integrity
|
14
14
|
issues in a knife-ec-backup object based backup
|
@@ -19,6 +19,7 @@ extensions: []
|
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
21
|
- LICENSE
|
22
|
+
- conf/substitutions.json.example
|
22
23
|
- lib/chef/knife/tidy_backup_clean.rb
|
23
24
|
- lib/chef/knife/tidy_base.rb
|
24
25
|
- lib/chef/knife/tidy_notify.rb
|