knife-tidy 2.0.9 → 2.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|