knife-tidy 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,58 +1,58 @@
1
- require 'chef/knife/tidy_base'
1
+ require "chef/knife/tidy_base"
2
2
 
3
3
  class Chef
4
4
  class Knife
5
5
  class TidyNotify < Knife
6
6
  deps do
7
- require 'ffi_yajl'
8
- require 'net/smtp'
7
+ require "ffi_yajl"
8
+ require "net/smtp"
9
9
  end
10
10
 
11
- banner 'knife tidy notify (options)'
11
+ banner "knife tidy notify (options)"
12
12
 
13
13
  option :smtp_server,
14
- short: '-s SERVER_NAME',
15
- long: '--smtp_server SERVER_NAME',
16
- default: 'localhost',
17
- description: 'SMTP Server to be used for emailling reports to organization admins (defaults to localhost)'
14
+ short: "-s SERVER_NAME",
15
+ long: "--smtp_server SERVER_NAME",
16
+ default: "localhost",
17
+ description: "SMTP Server to be used for emailling reports to organization admins (defaults to localhost)"
18
18
 
19
19
  option :smtp_port,
20
- short: '-p SMTP_PORT',
21
- long: '--smtp_port SMTP_PORT',
20
+ short: "-p SMTP_PORT",
21
+ long: "--smtp_port SMTP_PORT",
22
22
  default: 25,
23
- description: 'SMTP port to be used for emailling reports to organization admins (defaults to 25)'
23
+ description: "SMTP port to be used for emailling reports to organization admins (defaults to 25)"
24
24
 
25
25
  option :smtp_helo,
26
- short: '-h SMTP_HELO',
27
- long: '--smtp_helo SMTP_HELO',
28
- default: 'localhost',
29
- description: 'SMTP HELO to be used for emailling reports to organization admins (defaults to localhost)'
26
+ short: "-h SMTP_HELO",
27
+ long: "--smtp_helo SMTP_HELO",
28
+ default: "localhost",
29
+ description: "SMTP HELO to be used for emailling reports to organization admins (defaults to localhost)"
30
30
 
31
31
  option :smtp_username,
32
- short: '-u SMTP_USERNAME',
33
- long: '--smtp_username SMTP_USERNAME',
34
- description: 'SMTP Username to be used for emailling reports to organization admins'
32
+ short: "-u SMTP_USERNAME",
33
+ long: "--smtp_username SMTP_USERNAME",
34
+ description: "SMTP Username to be used for emailling reports to organization admins"
35
35
 
36
36
  option :smtp_password,
37
- long: '--smtp_password SMTP_PASSWORD',
38
- description: 'SMTP Password to be used for emailling reports to organization admins'
37
+ long: "--smtp_password SMTP_PASSWORD",
38
+ description: "SMTP Password to be used for emailling reports to organization admins"
39
39
 
40
40
  option :smtp_from,
41
- long: '--smtp_from SMTP_FROM',
42
- description: 'SMTP From address to be used for emailling reports to organization admins'
41
+ long: "--smtp_from SMTP_FROM",
42
+ description: "SMTP From address to be used for emailling reports to organization admins"
43
43
 
44
44
  option :smtp_use_tls,
45
- long: '--smtp_use_tls',
46
- short: '-t',
45
+ long: "--smtp_use_tls",
46
+ short: "-t",
47
47
  default: false,
48
48
  boolean: true | false,
49
- description: 'Whether TLS should be used for emailling reports to organization admins (defaults to false if omitted)'
49
+ description: "Whether TLS should be used for emailling reports to organization admins (defaults to false if omitted)"
50
50
 
51
51
  include Knife::TidyBase
52
52
 
53
53
  def run
54
54
  reports_dir = tidy.reports_dir
55
- report_file_suffixes = ['_unused_cookbooks.json', '_cookbook_count.json', '_stale_nodes.json']
55
+ report_file_suffixes = ["_unused_cookbooks.json", "_cookbook_count.json", "_stale_nodes.json"]
56
56
  # Only grab the files matching the report_file_suffixes
57
57
  report_files = Dir["#{reports_dir}/*{#{report_file_suffixes.join(',')}}"]
58
58
 
@@ -62,11 +62,11 @@ class Chef
62
62
  begin
63
63
  org_names = report_files.map { |r_file| r_file.match("#{reports_dir}\/(.*)(#{report_file_suffixes.join('|')})").captures.first }.uniq
64
64
  rescue NoMethodError
65
- ui.stderr.puts 'Failed to parse json reports files. Please ensure your reports are valid.'
65
+ ui.stderr.puts "Failed to parse json reports files. Please ensure your reports are valid."
66
66
  return
67
67
  end
68
68
  if config[:org_list]
69
- filter_orgs = config[:org_list].split(',')
69
+ filter_orgs = config[:org_list].split(",")
70
70
  # Take the intersection of org_names and filter_orgs
71
71
  org_names &= filter_orgs
72
72
  end
@@ -76,7 +76,7 @@ class Chef
76
76
  # Iterate through list of collected organizations and parse any report files into JSON objects
77
77
 
78
78
  unless org_names
79
- ui.std.puts 'No valid org reports found to send notifications. Exiting.'
79
+ ui.std.puts "No valid org reports found to send notifications. Exiting."
80
80
  return
81
81
  end
82
82
 
@@ -99,13 +99,13 @@ class Chef
99
99
  ui.info("Fetching admins users for organization #{org}")
100
100
  begin
101
101
  admins = org_admins(org)
102
- reports[org]['admins'] = admins.map { |name, _data| org_user(org, name) unless name == 'pivotal' }
102
+ reports[org]["admins"] = admins.map { |name, _data| org_user(org, name) unless name == "pivotal" }
103
103
  rescue Net::HTTPServerException
104
104
  ui.info(" Cannot fetch admin users for organization #{org} as it does not exist on the server")
105
105
  end
106
106
 
107
107
  # Build list of email recipients from the collected admin users (display name and email address of each)
108
- email_recipients = reports[org]['admins'].map { |admin| { name: admin['display_name'], email: admin['email'] } unless admin.nil? }.compact
108
+ email_recipients = reports[org]["admins"].map { |admin| { name: admin["display_name"], email: admin["email"] } unless admin.nil? }.compact
109
109
 
110
110
  # Send a report email to all admin users of the organization
111
111
  ui.info "Sending email reports for organization #{org}"
@@ -118,73 +118,73 @@ class Chef
118
118
 
119
119
  def generate_email(report_data, organization, recipients, report_file_suffixes)
120
120
  mime_boundary = "==Multipart_Boundary_x#{srand}x"
121
- message = <<MESSAGE_END
122
- From: Knife Tidy <#{config[:smtp_from]}>
123
- To: #{recipients.map { |recipient| "#{recipient[:name]} <#{recipient[:email]}>" }.join(', ')}
124
- MIME-Version: 1.0
125
- Subject: Knife Tidy Cleanup Report for Organization "#{organization}"
126
- Content-Type: multipart/mixed; boundary="#{mime_boundary}";
127
- --#{mime_boundary}
128
- Content-type: text/html
129
- Content-Transfer-Encoding: 7bit
130
-
131
- The following reports were generated by <a href="https://github.com/chef-customers/knife-tidy">knife-tidy</a>, and contain a list of unused cookbooks and stale nodes for the Chef server organization "#{organization}"
132
- #{generate_total_cookbooks_table(report_data, organization)}
133
- #{generate_unused_cookbooks_table(report_data, organization)}
134
- #{generate_node_table(report_data, organization)}
135
- MESSAGE_END
121
+ message = <<~MESSAGE_END
122
+ From: Knife Tidy <#{config[:smtp_from]}>
123
+ To: #{recipients.map { |recipient| "#{recipient[:name]} <#{recipient[:email]}>" }.join(', ')}
124
+ MIME-Version: 1.0
125
+ Subject: Knife Tidy Cleanup Report for Organization "#{organization}"
126
+ Content-Type: multipart/mixed; boundary="#{mime_boundary}";
127
+ --#{mime_boundary}
128
+ Content-type: text/html
129
+ Content-Transfer-Encoding: 7bit
130
+
131
+ The following reports were generated by <a href="https://github.com/chef-customers/knife-tidy">knife-tidy</a>, and contain a list of unused cookbooks and stale nodes for the Chef server organization "#{organization}"
132
+ #{generate_total_cookbooks_table(report_data, organization)}
133
+ #{generate_unused_cookbooks_table(report_data, organization)}
134
+ #{generate_node_table(report_data, organization)}
135
+ MESSAGE_END
136
136
 
137
137
  report_file_suffixes.each do |suffix|
138
- message += <<MESSAGE_END
139
- --#{mime_boundary}
140
- Content-Transfer-Encoding:7bit
141
- Content-Type: plain/text;name="#{organization}#{suffix}";charset="UTF-8"
142
- Content-Disposition: attachment;filename="#{organization}#{suffix}"
138
+ message += <<~MESSAGE_END
139
+ --#{mime_boundary}
140
+ Content-Transfer-Encoding:7bit
141
+ Content-Type: plain/text;name="#{organization}#{suffix}";charset="UTF-8"
142
+ Content-Disposition: attachment;filename="#{organization}#{suffix}"
143
143
 
144
- #{report_data[organization][suffix].to_json}
144
+ #{report_data[organization][suffix].to_json}
145
145
 
146
- MESSAGE_END
146
+ MESSAGE_END
147
147
  end
148
148
 
149
- message += <<MESSAGE_END
150
- --#{mime_boundary}--
151
- MESSAGE_END
149
+ message += <<~MESSAGE_END
150
+ --#{mime_boundary}--
151
+ MESSAGE_END
152
152
  puts message
153
153
  message
154
154
  end
155
155
 
156
156
  def generate_total_cookbooks_table(report_data, organization)
157
157
  table_start = "<h2>Total Versions by Cookbook</h2><p>This table contains the count of versions of each cookbook stored on the Chef Server.<p><table border='1' cellpadding='1' cellspacing='0'>"
158
- table_end = '</table><br/>'
159
- header_string = '<tr><th>Cookbook Name</th><th>Total Version Count</th></tr>'
160
- table_body = if report_data[organization]['_cookbook_count.json'].empty?
158
+ table_end = "</table><br/>"
159
+ header_string = "<tr><th>Cookbook Name</th><th>Total Version Count</th></tr>"
160
+ table_body = if report_data[organization]["_cookbook_count.json"].empty?
161
161
  "<tr><td colspan='2'>No cookbook versions</td></tr>"
162
162
  else
163
- report_data[organization]['_cookbook_count.json'].map { |cookbook_name, cookbook_count| "<tr><td>#{cookbook_name}</td><td>#{cookbook_count}</td></tr>" }.join("\n")
163
+ report_data[organization]["_cookbook_count.json"].map { |cookbook_name, cookbook_count| "<tr><td>#{cookbook_name}</td><td>#{cookbook_count}</td></tr>" }.join("\n")
164
164
  end
165
165
  table_start + header_string + table_body + table_end
166
166
  end
167
167
 
168
168
  def generate_unused_cookbooks_table(report_data, organization)
169
169
  table_start = "<h2>Unused Cookbooks</h2><p>This table contains cookbook names and the count of their versions that are not currently in the runlists of any nodes.<p><table border='1' cellpadding='1' cellspacing='0'>"
170
- table_end = '</table><br/>'
171
- header_string = '<tr><th>Cookbook Name</th><th>Unused Versions</th></tr>'
172
- table_body = if report_data[organization]['_unused_cookbooks.json'].empty?
170
+ table_end = "</table><br/>"
171
+ header_string = "<tr><th>Cookbook Name</th><th>Unused Versions</th></tr>"
172
+ table_body = if report_data[organization]["_unused_cookbooks.json"].empty?
173
173
  "<tr><td colspan='2'>No unused cookbook versions</td></tr>"
174
174
  else
175
- report_data[organization]['_unused_cookbooks.json'].map { |cookbook_name, cookbook_versions| "<tr><td>#{cookbook_name}</td><td>#{cookbook_versions.join('<br>')}</td></tr>" }.join("\n")
175
+ report_data[organization]["_unused_cookbooks.json"].map { |cookbook_name, cookbook_versions| "<tr><td>#{cookbook_name}</td><td>#{cookbook_versions.join('<br>')}</td></tr>" }.join("\n")
176
176
  end
177
177
  table_start + header_string + table_body + table_end
178
178
  end
179
179
 
180
180
  def generate_node_table(report_data, organization)
181
181
  table_start = "<h2>Stale Nodes</h2><p>This table contains nodes that have not checked in to the Chef Server in #{report_data[organization]['_stale_nodes.json']['threshold_days']} days.<p><table border='1' cellpadding='1' cellspacing='0'>"
182
- table_end = '</table>'
183
- header_string = '<tr><th>Node Name</th></tr>'
184
- table_body = if report_data[organization]['_stale_nodes.json'].empty? || report_data[organization]['_stale_nodes.json']['count'] == 0
182
+ table_end = "</table>"
183
+ header_string = "<tr><th>Node Name</th></tr>"
184
+ table_body = if report_data[organization]["_stale_nodes.json"].empty? || report_data[organization]["_stale_nodes.json"]["count"] == 0
185
185
  "<tr><td colspan='2'>No stale nodes</td></tr>"
186
186
  else
187
- report_data[organization]['_stale_nodes.json']['list'].map { |node_name| "<tr><td>#{node_name}</td></tr>" }.join("\n")
187
+ report_data[organization]["_stale_nodes.json"]["list"].map { |node_name| "<tr><td>#{node_name}</td></tr>" }.join("\n")
188
188
  end
189
189
  table_start + header_string + table_body + table_end
190
190
  end
@@ -199,7 +199,7 @@ MESSAGE_END
199
199
 
200
200
  def org_admins(org)
201
201
  admins = {}
202
- rest.get("/organizations/#{org}/groups/admins")['users'].each do |name|
202
+ rest.get("/organizations/#{org}/groups/admins")["users"].each do |name|
203
203
  admins[name] = {}
204
204
  end
205
205
  admins
@@ -1,4 +1,4 @@
1
- require 'chef/knife/tidy_base'
1
+ require "chef/knife/tidy_base"
2
2
 
3
3
  class Chef
4
4
  class Knife
@@ -6,32 +6,32 @@ class Chef
6
6
  include Knife::TidyBase
7
7
 
8
8
  deps do
9
- require 'ffi_yajl'
10
- require 'chef/util/threaded_job_queue'
9
+ require "ffi_yajl"
10
+ require "chef/util/threaded_job_queue"
11
11
  end
12
12
 
13
- banner 'knife tidy server clean (options)'
13
+ banner "knife tidy server clean (options)"
14
14
 
15
15
  option :backup_path,
16
- long: '--backup-path path/to/backup',
17
- description: 'The path to the knife-ec-backup backup directory'
16
+ long: "--backup-path path/to/backup",
17
+ description: "The path to the knife-ec-backup backup directory"
18
18
 
19
19
  option :concurrency,
20
- long: '--concurrency THREADS',
20
+ long: "--concurrency THREADS",
21
21
  default: 1,
22
- description: 'Maximum number of simultaneous requests to send (default: 1)'
22
+ description: "Maximum number of simultaneous requests to send (default: 1)"
23
23
 
24
24
  option :only_cookbooks,
25
- long: '--only-cookbooks',
26
- description: 'Only delete unused cookbooks from Chef Server.'
25
+ long: "--only-cookbooks",
26
+ description: "Only delete unused cookbooks from Chef Server."
27
27
 
28
28
  option :only_nodes,
29
- long: '--only-nodes',
30
- description: 'Only delete stale nodes (and associated clients and ACLs) from Chef Server.'
29
+ long: "--only-nodes",
30
+ description: "Only delete stale nodes (and associated clients and ACLs) from Chef Server."
31
31
 
32
32
  option :dry_run,
33
- long: '--dry-run',
34
- description: 'Do not perform any actual deletion, only report on what would have been deleted.'
33
+ long: "--dry-run",
34
+ description: "Do not perform any actual deletion, only report on what would have been deleted."
35
35
 
36
36
  def run
37
37
  STDOUT.sync = true
@@ -41,37 +41,37 @@ class Chef
41
41
  configure_chef
42
42
 
43
43
  if config[:only_cookbooks] && config[:only_nodes]
44
- ui.error 'Cannot use --only-cookbooks AND --only-nodes'
44
+ ui.error "Cannot use --only-cookbooks AND --only-nodes"
45
45
  exit 1
46
46
  end
47
47
 
48
48
  while config[:backup_path].nil?
49
49
  user_value = ui.ask_question("It is not recommended to run this command without specifying a current backup directory.\nPlease specify a backup directory:")
50
- config[:backup_path] = user_value == '' ? nil : user_value
50
+ config[:backup_path] = user_value == "" ? nil : user_value
51
51
  end
52
52
 
53
53
  unless ::File.directory?(config[:backup_path])
54
- ui.error 'Must specify valid --backup-path'
54
+ ui.error "Must specify valid --backup-path"
55
55
  exit 1
56
56
  end
57
57
 
58
58
  deletions = if config[:only_cookbooks]
59
- 'cookbooks'
59
+ "cookbooks"
60
60
  elsif config[:only_nodes]
61
- 'nodes (and associated clients and ACLs)'
61
+ "nodes (and associated clients and ACLs)"
62
62
  else
63
- 'cookbooks and nodes (and associated clients and ACLs)'
63
+ "cookbooks and nodes (and associated clients and ACLs)"
64
64
  end
65
65
 
66
66
  orgs = if config[:org_list]
67
- config[:org_list].split(',')
67
+ config[:org_list].split(",")
68
68
  else
69
69
  all_orgs
70
70
  end
71
71
 
72
72
  ui.warn "This operation will affect the following Orgs on #{server.root_url}: #{orgs}"
73
73
  if ::File.exist?(server_warnings_file_path)
74
- ::File.read(::File.expand_path('reports/knife-tidy-server-warnings.txt')).each_line do |line|
74
+ ::File.read(::File.expand_path("reports/knife-tidy-server-warnings.txt")).each_line do |line|
75
75
  ui.warn(line)
76
76
  end
77
77
  end
@@ -147,7 +147,7 @@ class Chef
147
147
  end
148
148
 
149
149
  def report_files
150
- Dir[::File.join(tidy.reports_dir, '**.json')]
150
+ Dir[::File.join(tidy.reports_dir, "**.json")]
151
151
  end
152
152
 
153
153
  def all_orgs
@@ -1,4 +1,4 @@
1
- require 'chef/knife/tidy_base'
1
+ require "chef/knife/tidy_base"
2
2
 
3
3
  class Chef
4
4
  class Knife
@@ -7,15 +7,15 @@ class Chef
7
7
  include Knife::TidyBase
8
8
 
9
9
  deps do
10
- require 'ffi_yajl'
10
+ require "ffi_yajl"
11
11
  end
12
12
 
13
13
  banner "knife tidy server report (options)"
14
14
 
15
15
  option :node_threshold,
16
- :long => '--node-threshold NUM_DAYS',
17
- :default => 30,
18
- :description => 'Maximum number of days since last checkin before node is considered stale (default: 30)'
16
+ long: "--node-threshold NUM_DAYS",
17
+ default: 30,
18
+ description: "Maximum number of days since last checkin before node is considered stale (default: 30)"
19
19
 
20
20
  def run
21
21
  ensure_reports_dir!
@@ -25,7 +25,7 @@ class Chef
25
25
  delete_existing_reports
26
26
 
27
27
  orgs = if config[:org_list]
28
- config[:org_list].split(',')
28
+ config[:org_list].split(",")
29
29
  else
30
30
  all_orgs
31
31
  end
@@ -51,23 +51,23 @@ class Chef
51
51
 
52
52
  nodes.each do |node|
53
53
  # If the node hasn't checked in.
54
- if !node['chef_packages']
54
+ if !node["chef_packages"]
55
55
  # If the node is under an hour old.
56
- if (Time.now.to_i - node['ohai_time'].to_i) < 3600
57
- unconverged_recent_nodes << node['name']
56
+ if (Time.now.to_i - node["ohai_time"].to_i) < 3600
57
+ unconverged_recent_nodes << node["name"]
58
58
  end
59
59
  next
60
60
  end
61
- chef_version = Gem::Version.new(node['chef_packages']['chef']['version'])
61
+ chef_version = Gem::Version.new(node["chef_packages"]["chef"]["version"])
62
62
  # If the node has checked in within the node_threshold with a client older than 12.3
63
- if chef_version < Gem::Version.new("12.3") && (Time.now.to_i - node['ohai_time'].to_i) <= node_threshold * 86400
64
- pre_12_3_nodes << node['name']
63
+ if chef_version < Gem::Version.new("12.3") && (Time.now.to_i - node["ohai_time"].to_i) <= node_threshold * 86400
64
+ pre_12_3_nodes << node["name"]
65
65
  end
66
66
  end
67
67
 
68
- nodes.select{|node| !node['cookbooks'].nil?}.each do |node|
69
- node['cookbooks'].each do |name, version_hash|
70
- version = Gem::Version.new(version_hash['version']).to_s
68
+ nodes.select { |node| !node["cookbooks"].nil? }.each do |node|
69
+ node["cookbooks"].each do |name, version_hash|
70
+ version = Gem::Version.new(version_hash["version"]).to_s
71
71
  if used_cookbooks[name]
72
72
  used_cookbooks[name].push(version) unless used_cookbooks[name].include?(version)
73
73
  else
@@ -81,17 +81,17 @@ class Chef
81
81
 
82
82
  stale_nodes = []
83
83
  nodes.each do |n|
84
- if (Time.now.to_i - n['ohai_time'].to_i) >= node_threshold * 86400
85
- stale_nodes.push(n['name'])
84
+ if (Time.now.to_i - n["ohai_time"].to_i) >= node_threshold * 86400
85
+ stale_nodes.push(n["name"])
86
86
  end
87
87
  end
88
88
 
89
- stale_nodes_hash = {'threshold_days': node_threshold, 'org_total_node_count': nodes.count, 'count': stale_nodes.count, 'list': stale_nodes}
89
+ stale_nodes_hash = { 'threshold_days': node_threshold, 'org_total_node_count': nodes.count, 'count': stale_nodes.count, 'list': stale_nodes }
90
90
  stale_orgs.push(org) if stale_nodes.count == nodes.count
91
91
 
92
- tidy.write_new_file(unused_cookbooks(used_cookbooks, cb_list), ::File.join(tidy.reports_dir, "#{org}_unused_cookbooks.json"), backup=false)
93
- tidy.write_new_file(version_count, ::File.join(tidy.reports_dir, "#{org}_cookbook_count.json"), backup=false)
94
- tidy.write_new_file(stale_nodes_hash, ::File.join(tidy.reports_dir, "#{org}_stale_nodes.json"), backup=false)
92
+ tidy.write_new_file(unused_cookbooks(used_cookbooks, cb_list), ::File.join(tidy.reports_dir, "#{org}_unused_cookbooks.json"), backup = false)
93
+ tidy.write_new_file(version_count, ::File.join(tidy.reports_dir, "#{org}_cookbook_count.json"), backup = false)
94
+ tidy.write_new_file(stale_nodes_hash, ::File.join(tidy.reports_dir, "#{org}_stale_nodes.json"), backup = false)
95
95
 
96
96
  if pre_12_3_nodes.length > 0
97
97
  pre_12_3_message = "#{pre_12_3_nodes.length} nodes in organization #{org} have converged in the last #{node_threshold} days with a chef-client < 12.3. These nodes' cookbook versions WILL NOT be factored in the stale cookbooks versions report. Continuing with the server cleanup will delete cookbooks in-use by these nodes."
@@ -113,24 +113,24 @@ class Chef
113
113
  end
114
114
 
115
115
  def delete_existing_reports
116
- files = Dir[::File.join(tidy.reports_dir, '*.json')]
116
+ files = Dir[::File.join(tidy.reports_dir, "*.json")]
117
117
  unless files.empty?
118
118
  ui.confirm("You have existing reports in #{tidy.reports_dir}. Remove")
119
- FileUtils.rm(files, :force => true)
119
+ FileUtils.rm(files, force: true)
120
120
  end
121
121
  end
122
122
 
123
- # Need the block here to get the search method to invoke multiple searches and
123
+ # Need the block here to get the search method to invoke multiple searches and
124
124
  # aggregate results for result sets over 1k.
125
125
  def nodes_list(org)
126
126
  node_results = []
127
127
  Chef::Search::Query.new("#{server.root_url}/organizations/#{org}").search(
128
- :node, '*:*',
129
- :filter_result => {
130
- 'name' => ['name'],
131
- 'cookbooks' => ['cookbooks'],
132
- 'ohai_time' => ['ohai_time'],
133
- 'chef_packages' => ['chef_packages']
128
+ :node, "*:*",
129
+ filter_result: {
130
+ "name" => ["name"],
131
+ "cookbooks" => ["cookbooks"],
132
+ "ohai_time" => ["ohai_time"],
133
+ "chef_packages" => ["chef_packages"],
134
134
  }
135
135
  ) do |node|
136
136
  node_results << node
@@ -141,8 +141,8 @@ class Chef
141
141
  def cookbook_list(org)
142
142
  cb_list = {}
143
143
  rest.get("/organizations/#{org}/cookbooks?num_versions=all").each do |name, data|
144
- data['versions'].each do |version_hash|
145
- version = Gem::Version.new(version_hash['version']).to_s
144
+ data["versions"].each do |version_hash|
145
+ version = Gem::Version.new(version_hash["version"]).to_s
146
146
  if cb_list[name] && !cb_list[name].include?(version)
147
147
  cb_list[name].push(version)
148
148
  else
@@ -164,11 +164,11 @@ class Chef
164
164
  def unused_cookbooks(used_list, cb_list)
165
165
  unused_list = {}
166
166
  cb_list.each do |name, versions|
167
- versions.sort! {| a, b | Gem::Version.new(a) <=> Gem::Version.new(b) }
167
+ versions.sort! { |a, b| Gem::Version.new(a) <=> Gem::Version.new(b) }
168
168
  if used_list[name].nil? # Not in the used list at all (Remove all versions)
169
169
  unused_list[name] = versions
170
- elsif used_list[name].sort != versions # Is in the used cookbook list, but version arrays do not match (Find unused versions)
171
- unused = versions - used_list[name] - [versions.last] # Don't delete the most recent version as it might not be in a run_list yet.
170
+ elsif used_list[name].sort != versions # Is in the used cookbook list, but version arrays do not match (Find unused versions)
171
+ unused = versions - used_list[name] - [versions.last] # Don't delete the most recent version as it might not be in a run_list yet.
172
172
  unused_list[name] = unused unless unused.empty?
173
173
  end
174
174
  end
@@ -176,7 +176,7 @@ class Chef
176
176
  end
177
177
 
178
178
  def all_orgs
179
- rest.get('organizations').keys
179
+ rest.get("organizations").keys
180
180
  end
181
181
 
182
182
  def all_environments(org)
@@ -187,7 +187,7 @@ class Chef
187
187
  constraints = {}
188
188
  all_environments(org).each do |env|
189
189
  e = rest.get(env)
190
- e['cookbook_versions'].each do |cb, version|
190
+ e["cookbook_versions"].each do |cb, version|
191
191
  if constraints[cb]
192
192
  constraints[cb].push(version) unless constraints[cb].include?(version)
193
193
  else
@@ -202,7 +202,7 @@ class Chef
202
202
  if cb_list[cb]
203
203
  cb_list[cb].each do |v|
204
204
  versions_not_satisfied = []
205
- if Gem::Dependency.new('', version).match?('', v)
205
+ if Gem::Dependency.new("", version).match?("", v)
206
206
  return [v]
207
207
  else
208
208
  versions_not_satisfied.push(v)
@@ -214,7 +214,7 @@ class Chef
214
214
  else
215
215
  ui.warn("Cookbook #{cb} #{version} is pinned in an environment, but does not exist on the server in this org.")
216
216
  end
217
- return nil
217
+ nil
218
218
  end
219
219
 
220
220
  def check_environment_pins(used_cookbooks, pins, cb_list)
@@ -224,7 +224,7 @@ class Chef
224
224
  if used_cookbooks[cb]
225
225
  # This pinned cookbook is in the used list, now check for a matching version.
226
226
  used_cookbooks[cb].each do |v|
227
- if Gem::Dependency.new('', version).match?('', v)
227
+ if Gem::Dependency.new("", version).match?("", v)
228
228
  break
229
229
  end
230
230
  end