chef 16.8.14 → 16.9.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -3
  3. data/README.md +1 -1
  4. data/chef.gemspec +10 -1
  5. data/lib/chef/compliance/default_attributes.rb +5 -1
  6. data/lib/chef/compliance/fetcher/automate.rb +2 -2
  7. data/lib/chef/compliance/fetcher/chef_server.rb +2 -2
  8. data/lib/chef/compliance/reporter/automate.rb +1 -2
  9. data/lib/chef/compliance/reporter/chef_server_automate.rb +2 -2
  10. data/lib/chef/compliance/runner.rb +7 -2
  11. data/lib/chef/http/ssl_policies.rb +27 -14
  12. data/lib/chef/knife/core/formatting_options.rb +49 -0
  13. data/lib/chef/knife/core/node_presenter.rb +0 -25
  14. data/lib/chef/knife/core/status_presenter.rb +1 -26
  15. data/lib/chef/knife/core/windows_bootstrap_context.rb +1 -1
  16. data/lib/chef/knife/node_show.rb +2 -1
  17. data/lib/chef/knife/search.rb +2 -1
  18. data/lib/chef/knife/status.rb +8 -11
  19. data/lib/chef/policy_builder/policyfile.rb +1 -1
  20. data/lib/chef/provider/package.rb +53 -19
  21. data/lib/chef/provider/package/dnf.rb +39 -12
  22. data/lib/chef/provider/package/dnf/dnf_helper.py +18 -5
  23. data/lib/chef/provider/package/dnf/python_helper.rb +6 -6
  24. data/lib/chef/provider/yum_repository.rb +2 -2
  25. data/lib/chef/resource/chef_gem.rb +2 -2
  26. data/lib/chef/resource/cron/cron_d.rb +1 -0
  27. data/lib/chef/resource/file.rb +1 -1
  28. data/lib/chef/resource/gem_package.rb +2 -2
  29. data/lib/chef/resource/homebrew_cask.rb +3 -3
  30. data/lib/chef/resource/http_request.rb +1 -1
  31. data/lib/chef/resource/locale.rb +1 -1
  32. data/lib/chef/resource/mdadm.rb +2 -2
  33. data/lib/chef/resource/osx_profile.rb +7 -7
  34. data/lib/chef/resource/remote_directory.rb +1 -1
  35. data/lib/chef/resource/ruby.rb +1 -5
  36. data/lib/chef/resource/ruby_block.rb +1 -1
  37. data/lib/chef/resource/user/windows_user.rb +5 -0
  38. data/lib/chef/resource/windows_certificate.rb +2 -12
  39. data/lib/chef/resource/yum_repository.rb +5 -0
  40. data/lib/chef/version.rb +1 -1
  41. data/spec/data/rubygems.org/latest_specs.4.8.gz +0 -0
  42. data/spec/data/rubygems.org/nonexistent_gem +0 -0
  43. data/spec/data/rubygems.org/sexp_processor +0 -0
  44. data/spec/data/rubygems.org/sexp_processor-4.15.1.gemspec.rz +0 -0
  45. data/spec/data/ssl/binary/chef-rspec-der.cert +0 -0
  46. data/spec/data/ssl/binary/chef-rspec-der.key +0 -0
  47. data/spec/functional/resource/dnf_package_spec.rb +319 -16
  48. data/spec/functional/resource/windows_certificate_spec.rb +204 -384
  49. data/spec/unit/compliance/runner_spec.rb +28 -0
  50. data/spec/unit/http/ssl_policies_spec.rb +106 -78
  51. data/spec/unit/knife/bootstrap_spec.rb +5 -17
  52. data/spec/unit/knife/core/status_presenter_spec.rb +54 -0
  53. data/spec/unit/mixin/openssl_helper_spec.rb +0 -7
  54. data/spec/unit/provider/package/rubygems_spec.rb +39 -7
  55. data/spec/unit/resource/user/windows_user_spec.rb +36 -0
  56. metadata +24 -12
  57. data/spec/data/trusted_certs_empty/.gitkeep +0 -0
  58. data/spec/data/trusted_certs_empty/README.md +0 -1
  59. data/spec/scripts/ssl-serve.rb +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6124227fa2dd345401b335be52a9d261458f5d8fe7a75de8478f66e2c4f9a493
4
- data.tar.gz: a0ce3f48fe7d680d1fe36f69684e20efbacf7ee4ce20ff7adeb7f251a002b25a
3
+ metadata.gz: b7281deb86006f8f7411e4120fbbe38fce4cecf8da53238f1bd683673032b85b
4
+ data.tar.gz: ddbae290d6ac865004a078e256f01ab840009d78d95f536bad567afc026d7082
5
5
  SHA512:
6
- metadata.gz: 208c095249a456996ea54930f11bad6d6402c3a47208c1bf62eaff0eed6e9bc54783cd2af48f92885ab1bd34dcdc5e58863bbd3bce9badb57ea1cecb571b113d
7
- data.tar.gz: 053ae58aa1d72aa1bdede2fe27d6bfb5cd4d56e0123fe0d52e6fed5ac7478847741476e8fbb18da8f530a9639a057d9e0ad27f3845606572511de3c7c17639bb
6
+ metadata.gz: cecf1f0d7c0bc892a5c7165178a65382f813a7c0728596b1537a6e9333085258a413fd70d59596a166507a80a1a987dc8b34ed64bf08f7477852be6d8d9ca4e4
7
+ data.tar.gz: 4e87ed0f3f3ab0b5c9461e45576b2e7eccd4f7c15d21c35fba5065024adc70f6ff2a44d37c04630a831baf8c71bfa0d72d4d2b97157f2681665450d8b8cc400a
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ source "https://rubygems.org"
7
7
  # of bundler versions prior to 1.12.0 (https://github.com/bundler/bundler/commit/193a14fe5e0d56294c7b370a0e59f93b2c216eed)
8
8
  gem "chef", path: "."
9
9
 
10
- gem "ohai", git: "https://github.com/chef/ohai.git", branch: "master"
10
+ gem "ohai", git: "https://github.com/chef/ohai.git", branch: "16-stable"
11
11
 
12
12
  gem "chef-utils", path: File.expand_path("chef-utils", __dir__) if File.exist?(File.expand_path("chef-utils", __dir__))
13
13
  gem "chef-config", path: File.expand_path("chef-config", __dir__) if File.exist?(File.expand_path("chef-config", __dir__))
@@ -56,8 +56,7 @@ group(:development, :test) do
56
56
  end
57
57
 
58
58
  group(:chefstyle) do
59
- # for testing new chefstyle rules
60
- gem "chefstyle", git: "https://github.com/chef/chefstyle.git", branch: "master"
59
+ gem "chefstyle", "= 1.5.9"
61
60
  end
62
61
 
63
62
  instance_eval(ENV["GEMFILE_MOD"]) if ENV["GEMFILE_MOD"]
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Chef Infra
2
2
  [![Code Climate](https://codeclimate.com/github/chef/chef.svg)](https://codeclimate.com/github/chef/chef)
3
- [![Build Status](https://badge.buildkite.com/c82093430ceec7d27af05febb9dcafe3aa331fff9d74c0ab9d.svg?branch=master)](https://buildkite.com/chef-oss/chef-chef-master-verify)
3
+ [![Build Status](https://badge.buildkite.com/c82093430ceec7d27af05febb9dcafe3aa331fff9d74c0ab9d.svg?branch=chef-16)](https://buildkite.com/chef-oss/chef-chef-chef-16-verify)
4
4
  [![Gem Version](https://badge.fury.io/rb/chef.svg)](https://badge.fury.io/rb/chef)
5
5
  [![](https://img.shields.io/badge/Release%20Policy-Cadence%20Release-brightgreen.svg)](https://github.com/chef/chef/blob/master/docs/dev/design_documents/client_release_cadence.md)
6
6
 
@@ -35,7 +35,7 @@ Gem::Specification.new do |s|
35
35
  s.add_dependency "net-ssh-multi", "~> 1.2", ">= 1.2.1"
36
36
  s.add_dependency "net-sftp", ">= 2.1.2", "< 4.0"
37
37
  s.add_dependency "ed25519", "~> 1.2" # ed25519 ssh key support
38
- s.add_dependency "bcrypt_pbkdf", "= 1.1.0.rc1" # ed25519 ssh key support
38
+ s.add_dependency "bcrypt_pbkdf", "= 1.1.0.rc2" # ed25519 ssh key support
39
39
  s.add_dependency "highline", ">= 1.6.9", "< 3"
40
40
  s.add_dependency "tty-prompt", "~> 0.21" # knife ui.ask prompt
41
41
  s.add_dependency "tty-screen", "~> 0.6" # knife list
@@ -67,4 +67,13 @@ Gem::Specification.new do |s|
67
67
  Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) } +
68
68
  Dir.glob("*.gemspec") +
69
69
  Dir.glob("tasks/rspec.rb")
70
+
71
+ s.metadata = {
72
+ "bug_tracker_uri" => "https://github.com/chef/chef/issues",
73
+ "changelog_uri" => "https://github.com/chef/chef/blob/master/CHANGELOG.md",
74
+ "documentation_uri" => "https://docs.chef.io/",
75
+ "homepage_uri" => "https://www.chef.io",
76
+ "mailing_list_uri" => "https://discourse.chef.io/",
77
+ "source_code_uri" => "https://github.com/chef/chef/",
78
+ }
70
79
  end
@@ -83,7 +83,11 @@ class Chef
83
83
 
84
84
  # The array of results per control will be truncated at this limit to avoid large reports that cannot be
85
85
  # processed by Chef Automate. A summary of removed results will be sent with each impacted control.
86
- "control_results_limit" => 50
86
+ "control_results_limit" => 50,
87
+
88
+ # If enabled, a hash representation of the Chef Infra node object will be sent to Chef InSpec in an input
89
+ # named `chef_node`.
90
+ "chef_node_attribute_enabled" => false
87
91
  )
88
92
  end
89
93
  end
@@ -7,8 +7,8 @@ class Chef
7
7
  class Automate < ::InspecPlugins::Compliance::Fetcher
8
8
  name "chef-automate"
9
9
 
10
- # it positions itself before `compliance` fetcher
11
- # only load it, if you want to use audit cookbook in Chef Solo with Chef Automate
10
+ # Positions this fetcher before Chef InSpec's `compliance` fetcher.
11
+ # Only load this file if you want to use Compliance Phase in Chef Solo with Chef Automate.
12
12
  priority 502
13
13
 
14
14
  CONFIG = {
@@ -95,11 +95,11 @@ class Chef
95
95
  def handle_http_error_code(code)
96
96
  case code
97
97
  when /401|403/
98
- Chef::Log.error "Auth issue: see audit cookbook TROUBLESHOOTING.md"
98
+ Chef::Log.error "Auth issue: see the Compliance Phase troubleshooting documentation (http://docs.chef.io/chef_compliance_phase/#troubleshooting)."
99
99
  when /404/
100
100
  Chef::Log.error "Object does not exist on remote server."
101
101
  when /413/
102
- Chef::Log.error "You most likely hit the erchef request size in #{ChefUtils::Dist::Server::PRODUCT} that defaults to ~2MB. To increase this limit see audit cookbook TROUBLESHOOTING.md OR https://docs.chef.io/config_rb_server.html"
102
+ Chef::Log.error "You most likely hit the erchef request size in #{ChefUtils::Dist::Server::PRODUCT} that defaults to ~2MB. To increase this limit see the Compliance Phase troubleshooting documentation (http://docs.chef.io/chef_compliance_phase/#troubleshooting) or the Chef Infra Server configuration documentation (https://docs.chef.io/server/config_rb_server/)"
103
103
  when /429/
104
104
  Chef::Log.error "This error typically means the data sent was larger than #{ChefUtils::Dist::Automate::PRODUCT}'s limit (4 MB). Run InSpec locally to identify any controls producing large diffs."
105
105
  end
@@ -36,8 +36,7 @@ class Chef
36
36
  end
37
37
 
38
38
  unless @url && @token
39
- Chef::Log.warn "data_collector.token and data_collector.server_url must be defined in client.rb!"
40
- Chef::Log.warn "Further information: https://github.com/chef-cookbooks/audit#direct-reporting-to-chef-automate"
39
+ Chef::Log.warn "data_collector.token and data_collector.server_url must be defined in client.rb! Further information: https://docs.chef.io/chef_compliance_phase/#direct-reporting-to-chef-automate"
41
40
  return false
42
41
  end
43
42
 
@@ -76,11 +76,11 @@ class Chef
76
76
  def handle_http_error_code(code)
77
77
  case code
78
78
  when /401|403/
79
- Chef::Log.error "Auth issue: see audit cookbook TROUBLESHOOTING.md"
79
+ Chef::Log.error "Auth issue: see the Compliance Phase troubleshooting documentation (http://docs.chef.io/chef_compliance_phase/#troubleshooting)."
80
80
  when /404/
81
81
  Chef::Log.error "Object does not exist on remote server."
82
82
  when /413/
83
- Chef::Log.error "You most likely hit the erchef request size in #{ChefUtils::Dist::Server::PRODUCT} that defaults to ~2MB. To increase this limit see audit cookbook TROUBLESHOOTING.md OR https://docs.chef.io/config_rb_server.html"
83
+ Chef::Log.error "You most likely hit the erchef request size in #{ChefUtils::Dist::Server::PRODUCT} that defaults to ~2MB. To increase this limit see the Compliance Phase troubleshooting documentation (http://docs.chef.io/chef_compliance_phase/#troubleshooting) or the Chef Infra Server configuration documentation (https://docs.chef.io/server/config_rb_server/)"
84
84
  when /429/
85
85
  Chef::Log.error "This error typically means the data sent was larger than #{ChefUtils::Dist::Automate::PRODUCT}'s limit (4 MB). Run InSpec locally to identify any controls producing large diffs."
86
86
  end
@@ -61,7 +61,6 @@ class Chef
61
61
 
62
62
  DEPRECATED_CONFIG_VALUES = %w{
63
63
  attributes_save
64
- chef_node_attribute_enabled
65
64
  fail_if_not_present
66
65
  inspec_gem_source
67
66
  inspec_version
@@ -93,9 +92,15 @@ class Chef
93
92
  end
94
93
 
95
94
  def inspec_opts
95
+ inputs = node["audit"]["attributes"].to_h
96
+ if node["audit"]["chef_node_attribute_enabled"]
97
+ inputs["chef_node"] = node.to_h
98
+ inputs["chef_node"]["chef_environment"] = node.chef_environment
99
+ end
100
+
96
101
  {
97
102
  backend_cache: node["audit"]["inspec_backend_cache"],
98
- inputs: node["audit"]["attributes"],
103
+ inputs: inputs,
99
104
  logger: logger,
100
105
  output: node["audit"]["quiet"] ? ::File::NULL : STDOUT,
101
106
  report: true,
@@ -85,28 +85,41 @@ class Chef
85
85
  http_client.cert_store.set_default_paths
86
86
  end
87
87
  if config.trusted_certs_dir
88
- certs = Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(config.trusted_certs_dir), "*.{crt,pem}"))
88
+ certs = Dir.glob(::File.join(Chef::Util::PathHelper.escape_glob_dir(config.trusted_certs_dir), "*.{crt,pem}"))
89
89
  certs.each do |cert_file|
90
- cert = OpenSSL::X509::Certificate.new(File.read(cert_file))
90
+ cert = begin
91
+ OpenSSL::X509::Certificate.new(::File.binread(cert_file))
92
+ rescue OpenSSL::X509::CertificateError => e
93
+ raise Chef::Exceptions::ConfigurationError, "Error reading cert file '#{cert_file}', original error '#{e.class}: #{e.message}'"
94
+ end
91
95
  add_trusted_cert(cert)
92
96
  end
93
97
  end
94
98
  end
95
99
 
96
100
  def set_client_credentials
97
- if config[:ssl_client_cert] || config[:ssl_client_key]
98
- unless config[:ssl_client_cert] && config[:ssl_client_key]
99
- raise Chef::Exceptions::ConfigurationError, "You must configure ssl_client_cert and ssl_client_key together"
100
- end
101
- unless ::File.exists?(config[:ssl_client_cert])
102
- raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_cert #{config[:ssl_client_cert]} does not exist"
103
- end
104
- unless ::File.exists?(config[:ssl_client_key])
105
- raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_key #{config[:ssl_client_key]} does not exist"
106
- end
101
+ return unless config[:ssl_client_cert] || config[:ssl_client_key]
102
+
103
+ unless config[:ssl_client_cert] && config[:ssl_client_key]
104
+ raise Chef::Exceptions::ConfigurationError, "You must configure ssl_client_cert and ssl_client_key together"
105
+ end
106
+ unless ::File.exists?(config[:ssl_client_cert])
107
+ raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_cert #{config[:ssl_client_cert]} does not exist"
108
+ end
109
+ unless ::File.exists?(config[:ssl_client_key])
110
+ raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_key #{config[:ssl_client_key]} does not exist"
111
+ end
112
+
113
+ begin
114
+ http_client.cert = OpenSSL::X509::Certificate.new(::File.binread(config[:ssl_client_cert]))
115
+ rescue OpenSSL::X509::CertificateError => e
116
+ raise Chef::Exceptions::ConfigurationError, "Error reading cert file '#{config[:ssl_client_cert]}', original error '#{e.class}: #{e.message}'"
117
+ end
107
118
 
108
- http_client.cert = OpenSSL::X509::Certificate.new(::File.read(config[:ssl_client_cert]))
109
- http_client.key = OpenSSL::PKey::RSA.new(::File.read(config[:ssl_client_key]))
119
+ begin
120
+ http_client.key = OpenSSL::PKey::RSA.new(::File.binread(config[:ssl_client_key]))
121
+ rescue OpenSSL::PKey::RSAError => e
122
+ raise Chef::Exceptions::ConfigurationError, "Error reading key file '#{config[:ssl_client_key]}', original error '#{e.class}: #{e.message}'"
110
123
  end
111
124
  end
112
125
 
@@ -0,0 +1,49 @@
1
+ #
2
+ # Author:: Nicolas DUPEUX (<nicolas.dupeux@arkea.com>)
3
+ # Copyright:: Copyright (c) Chef Software Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ class Chef
20
+ class Knife
21
+ module Core
22
+
23
+ # This module may be included into a knife subcommand class to automatically
24
+ # add configuration options used by the StatusPresenter and NodePresenter.
25
+ module FormattingOptions
26
+ # @private
27
+ # Would prefer to do this in a rational way, but can't be done b/c of
28
+ # Mixlib::CLI's design :(
29
+ def self.included(includer)
30
+ includer.class_eval do
31
+ option :medium_output,
32
+ short: "-m",
33
+ long: "--medium",
34
+ boolean: true,
35
+ default: false,
36
+ description: "Include normal attributes in the output"
37
+
38
+ option :long_output,
39
+ short: "-l",
40
+ long: "--long",
41
+ boolean: true,
42
+ default: false,
43
+ description: "Include all attributes in the output"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -23,31 +23,6 @@ class Chef
23
23
  class Knife
24
24
  module Core
25
25
 
26
- # This module may be included into a knife subcommand class to automatically
27
- # add configuration options used by the NodePresenter
28
- module NodeFormattingOptions
29
- # @private
30
- # Would prefer to do this in a rational way, but can't be done b/c of
31
- # Mixlib::CLI's design :(
32
- def self.included(includer)
33
- includer.class_eval do
34
- option :medium_output,
35
- short: "-m",
36
- long: "--medium",
37
- boolean: true,
38
- default: false,
39
- description: "Include normal attributes in the output"
40
-
41
- option :long_output,
42
- short: "-l",
43
- long: "--long",
44
- boolean: true,
45
- default: false,
46
- description: "Include all attributes in the output"
47
- end
48
- end
49
- end
50
-
51
26
  # A customized presenter for Chef::Node objects. Supports variable-length
52
27
  # output formats for displaying node data
53
28
  class NodePresenter < GenericPresenter
@@ -23,31 +23,6 @@ class Chef
23
23
  class Knife
24
24
  module Core
25
25
 
26
- # This module may be included into a knife subcommand class to automatically
27
- # add configuration options used by the StatusPresenter
28
- module StatusFormattingOptions
29
- # @private
30
- # Would prefer to do this in a rational way, but can't be done b/c of
31
- # Mixlib::CLI's design :(
32
- def self.included(includer)
33
- includer.class_eval do
34
- option :medium_output,
35
- short: "-m",
36
- long: "--medium",
37
- boolean: true,
38
- default: false,
39
- description: "Include normal attributes in the output"
40
-
41
- option :long_output,
42
- short: "-l",
43
- long: "--long",
44
- boolean: true,
45
- default: false,
46
- description: "Include all attributes in the output"
47
- end
48
- end
49
- end
50
-
51
26
  # A customized presenter for Chef::Node objects. Supports variable-length
52
27
  # output formats for displaying node data
53
28
  class StatusPresenter < GenericPresenter
@@ -67,7 +42,7 @@ class Chef
67
42
 
68
43
  result["name"] = node["name"] || node.name
69
44
  result["chef_environment"] = node["chef_environment"]
70
- ip = (node["cloud"] && node["cloud"]["public_ipv4_addrs"].first) || node["ipaddress"]
45
+ ip = (node["cloud"] && node["cloud"]["public_ipv4_addrs"]&.first) || node["ipaddress"]
71
46
  fqdn = (node["cloud"] && node["cloud"]["public_hostname"]) || node["fqdn"]
72
47
  result["ip"] = ip if ip
73
48
  result["fqdn"] = fqdn if fqdn
@@ -140,7 +140,7 @@ class Chef
140
140
  end
141
141
 
142
142
  unless trusted_certs_script.empty?
143
- client_rb << %Q{trusted_certs_dir "#{ChefConfig::Config.etc_chef_dir(windows: true)}/trusted_certs"\n}
143
+ client_rb << %Q{trusted_certs_dir "#{ChefConfig::PathHelper.escapepath(ChefConfig::Config.etc_chef_dir(windows: true))}\\\\trusted_certs"\n}
144
144
  end
145
145
 
146
146
  if chef_config[:fips]
@@ -18,13 +18,14 @@
18
18
 
19
19
  require_relative "../knife"
20
20
  require_relative "core/node_presenter"
21
+ require_relative "core/formatting_options"
21
22
  require "chef-utils/dist" unless defined?(ChefUtils::Dist)
22
23
 
23
24
  class Chef
24
25
  class Knife
25
26
  class NodeShow < Knife
26
27
 
27
- include Knife::Core::NodeFormattingOptions
28
+ include Knife::Core::FormattingOptions
28
29
  include Knife::Core::MultiAttributeReturnOption
29
30
 
30
31
  deps do
@@ -18,6 +18,7 @@
18
18
 
19
19
  require_relative "../knife"
20
20
  require_relative "core/node_presenter"
21
+ require_relative "core/formatting_options"
21
22
 
22
23
  class Chef
23
24
  class Knife
@@ -32,7 +33,7 @@ class Chef
32
33
  require_relative "../search/query"
33
34
  end
34
35
 
35
- include Knife::Core::NodeFormattingOptions
36
+ include Knife::Core::FormattingOptions
36
37
 
37
38
  banner "knife search INDEX QUERY (options)"
38
39
 
@@ -18,13 +18,13 @@
18
18
 
19
19
  require_relative "../knife"
20
20
  require_relative "core/status_presenter"
21
- require_relative "core/node_presenter"
21
+ require_relative "core/formatting_options"
22
22
  require "chef-utils/dist" unless defined?(ChefUtils::Dist)
23
23
 
24
24
  class Chef
25
25
  class Knife
26
26
  class Status < Knife
27
- include Knife::Core::NodeFormattingOptions
27
+ include Knife::Core::FormattingOptions
28
28
 
29
29
  deps do
30
30
  require_relative "../search/query"
@@ -68,11 +68,11 @@ class Chef
68
68
  append_to_query("chef_environment:#{config[:environment]}") if config[:environment]
69
69
 
70
70
  if config[:hide_by_mins]
71
- hidemins = config[:hide_by_mins].to_i
71
+ hide_by_mins = config[:hide_by_mins].to_i
72
72
  time = Time.now.to_i
73
73
  # AND NOT is not valid lucene syntax, so don't use append_to_query
74
74
  @query << " " unless @query.empty?
75
- @query << "NOT ohai_time:[#{(time - hidemins * 60)} TO #{time}]"
75
+ @query << "NOT ohai_time:[#{(time - hide_by_mins * 60)} TO #{time}]"
76
76
  end
77
77
 
78
78
  @query = @query.empty? ? "*:*" : @query
@@ -84,13 +84,10 @@ class Chef
84
84
  all_nodes << node
85
85
  end
86
86
 
87
- output(all_nodes.sort do |n1, n2|
88
- if config[:sort_reverse] || config[:sort_status_reverse]
89
- (n2["ohai_time"] || 0) <=> (n1["ohai_time"] || 0)
90
- else
91
- (n1["ohai_time"] || 0) <=> (n2["ohai_time"] || 0)
92
- end
93
- end)
87
+ all_nodes.sort_by! { |n| n["ohai_time"] || 0 }
88
+ all_nodes.reverse! if config[:sort_reverse] || config[:sort_status_reverse]
89
+
90
+ output(all_nodes)
94
91
  end
95
92
 
96
93
  end
@@ -475,7 +475,7 @@ class Chef
475
475
  end
476
476
 
477
477
  # @api private
478
- # Fetches the CookbookVersion object for the given name and identifer
478
+ # Fetches the CookbookVersion object for the given name and identifier
479
479
  # specified in the lock_data.
480
480
  # TODO: This only implements Chef 11 compatibility mode, which means that
481
481
  # cookbooks are fetched by the "dotted_decimal_identifier": a
@@ -28,14 +28,41 @@ class Chef
28
28
  class Package < Chef::Provider
29
29
  extend Chef::Mixin::SubclassDirective
30
30
 
31
- # subclasses declare this if they want all their arguments as arrays of packages and names
31
+ # subclasses declare this if they want all their arguments as arrays of packages and names.
32
+ # any new packages using this should also use allow_nils below.
33
+ #
32
34
  subclass_directive :use_multipackage_api
33
- # subclasses declare this if they want sources (filenames) pulled from their package names
35
+
36
+ # subclasses declare this if they want sources (filenames) pulled from their package names.
37
+ # this is for package providers that take a path into the filesystem (rpm, dpkg).
38
+ #
34
39
  subclass_directive :use_package_name_for_source
40
+
35
41
  # keeps package_names_for_targets and versions_for_targets indexed the same as package_name at
36
- # the cost of having the subclass needing to deal with nils
42
+ # the cost of having the subclass needing to deal with nils. all providers are encouraged to
43
+ # migrate to using this as it simplifies dealing with package aliases in subclasses.
44
+ #
37
45
  subclass_directive :allow_nils
38
46
 
47
+ # subclasses that implement complex pattern matching using constraints, particularly the yum and
48
+ # dnf classes, should filter the installed version against the desired version constraint and
49
+ # return nil if it does not match. this means that 'nil' does not mean that no version of the
50
+ # package is installed, but that the installed version does not satisfy the desired constraints.
51
+ # (the package plus the constraints are not installed)
52
+ #
53
+ # [ this may arguably be useful for all package providers and it greatly simplifies the logic
54
+ # in the superclass that gets executed, so maybe this should always be used now? ]
55
+ #
56
+ # note that when using this feature that the current_resource.version must be loaded with the
57
+ # correct currently installed version, without doing the filtering -- for reporting and for
58
+ # correctly displaying version upgrades. that means there are 3 different arrays which must be
59
+ # loaded by the subclass: candidate_version, magic_version and current_resource.version.
60
+ #
61
+ # NOTE: magic_version is a terrible name, but I couldn't think of anything better, at least this
62
+ # way it stands out clearly.
63
+ #
64
+ subclass_directive :use_magic_version
65
+
39
66
  #
40
67
  # Hook that subclasses use to populate the candidate_version(s)
41
68
  #
@@ -414,19 +441,21 @@ class Chef
414
441
  each_package do |package_name, new_version, current_version, candidate_version|
415
442
  case action
416
443
  when :upgrade
417
- if version_equals?(current_version, new_version)
418
- # this is an odd use case
419
- logger.trace("#{new_resource} #{package_name} #{new_version} is already installed -- you are equality pinning with an :upgrade action, this may be deprecated in the future")
420
- target_version_array.push(nil)
421
- elsif version_equals?(current_version, candidate_version)
422
- logger.trace("#{new_resource} #{package_name} #{candidate_version} is already installed")
444
+ if current_version.nil?
445
+ # with use_magic_version there may be a package installed, but it fails the user's
446
+ # requested new_resource.version constraints
447
+ logger.trace("#{new_resource} has no existing installed version. Installing install #{candidate_version}")
448
+ target_version_array.push(candidate_version)
449
+ elsif version_equals?(current_version, new_version)
450
+ # this is a short-circuit to avoid needing to (expensively) query the candidate_version which must come later
451
+ logger.trace("#{new_resource} #{package_name} #{new_version} is already installed")
423
452
  target_version_array.push(nil)
424
453
  elsif candidate_version.nil?
425
454
  logger.trace("#{new_resource} #{package_name} has no candidate_version to upgrade to")
426
455
  target_version_array.push(nil)
427
- elsif current_version.nil?
428
- logger.trace("#{new_resource} has no existing installed version. Installing install #{candidate_version}")
429
- target_version_array.push(candidate_version)
456
+ elsif version_equals?(current_version, candidate_version)
457
+ logger.trace("#{new_resource} #{package_name} #{candidate_version} is already installed")
458
+ target_version_array.push(nil)
430
459
  elsif !allow_downgrade && version_compare(current_version, candidate_version) == 1
431
460
  logger.trace("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{candidate_version}. Skipping...)")
432
461
  target_version_array.push(nil)
@@ -436,21 +465,20 @@ class Chef
436
465
  end
437
466
 
438
467
  when :install
439
- if new_version
468
+ if new_version && !use_magic_version?
440
469
  if version_requirement_satisfied?(current_version, new_version)
441
470
  logger.trace("#{new_resource} #{package_name} #{current_version} satisfies #{new_version} requirement")
442
471
  target_version_array.push(nil)
443
472
  elsif current_version && !allow_downgrade && version_compare(current_version, new_version) == 1
444
473
  logger.warn("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{new_version}. Skipping...)")
445
474
  target_version_array.push(nil)
446
- elsif version_equals?(current_version, candidate_version)
447
- logger.trace("#{new_resource} #{package_name} #{candidate_version} is already installed")
448
- target_version_array.push(nil)
449
475
  else
450
476
  logger.trace("#{new_resource} #{package_name} #{current_version} needs updating to #{new_version}")
451
477
  target_version_array.push(new_version)
452
478
  end
453
479
  elsif current_version.nil?
480
+ # with use_magic_version there may be a package installed, but it fails the user's
481
+ # requested new_resource.version constraints
454
482
  logger.trace("#{new_resource} #{package_name} not installed, installing #{candidate_version}")
455
483
  target_version_array.push(candidate_version)
456
484
  else
@@ -511,8 +539,14 @@ class Chef
511
539
  each_package do |package_name, new_version, current_version, candidate_version|
512
540
  next if new_version.nil? || current_version.nil?
513
541
 
514
- if !version_requirement_satisfied?(current_version, new_version) && candidate_version.nil?
515
- missing.push(package_name)
542
+ if use_magic_version?
543
+ if !magic_version && candidate_version.nil?
544
+ missing.push(package_name)
545
+ end
546
+ else
547
+ if !version_requirement_satisfied?(current_version, new_version) && candidate_version.nil?
548
+ missing.push(package_name)
549
+ end
516
550
  end
517
551
  end
518
552
  missing
@@ -525,7 +559,7 @@ class Chef
525
559
  def each_package
526
560
  package_name_array.each_with_index do |package_name, i|
527
561
  candidate_version = candidate_version_array[i]
528
- current_version = current_version_array[i]
562
+ current_version = use_magic_version? ? magic_version[i] : current_version_array[i]
529
563
  new_version = new_version_array[i]
530
564
  yield package_name, new_version, current_version, candidate_version
531
565
  end