summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/lint.yml2
-rw-r--r--CHANGELOG.md20
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock44
-rw-r--r--VERSION2
-rw-r--r--chef-bin/lib/chef-bin/version.rb2
-rw-r--r--chef-config/lib/chef-config/version.rb2
-rw-r--r--chef-utils/lib/chef-utils/version.rb2
-rw-r--r--kitchen-tests/cookbooks/end_to_end/recipes/_windows_printer.rb24
-rw-r--r--kitchen-tests/cookbooks/end_to_end/recipes/windows.rb2
-rw-r--r--knife/lib/chef/knife/configure.rb2
-rw-r--r--knife/lib/chef/knife/org_user_add.rb2
-rw-r--r--knife/lib/chef/knife/version.rb2
-rw-r--r--knife/spec/integration/commands_spec.rb55
-rw-r--r--lib/chef/action_collection.rb32
-rw-r--r--lib/chef/application.rb2
-rw-r--r--lib/chef/application/base.rb15
-rw-r--r--lib/chef/client.rb6
-rw-r--r--lib/chef/cookbook_version.rb30
-rw-r--r--lib/chef/data_collector.rb1
-rw-r--r--lib/chef/event_dispatch/base.rb3
-rw-r--r--lib/chef/exceptions.rb3
-rw-r--r--lib/chef/handler.rb54
-rw-r--r--lib/chef/handler/slow_report.rb66
-rw-r--r--lib/chef/provider/support/zypper_repo.erb6
-rw-r--r--lib/chef/provider/zypper_repository.rb58
-rw-r--r--lib/chef/resource/windows_pagefile.rb163
-rw-r--r--lib/chef/resource/windows_printer.rb19
-rw-r--r--lib/chef/resource/windows_printer_port.rb109
-rw-r--r--lib/chef/resource/zypper_repository.rb32
-rw-r--r--lib/chef/resource_reporter.rb1
-rw-r--r--lib/chef/version.rb2
-rw-r--r--omnibus/Gemfile.lock22
-rw-r--r--spec/functional/resource/windows_pagefile_spec.rb98
-rw-r--r--spec/unit/cookbook_version_spec.rb52
-rw-r--r--spec/unit/handler_spec.rb10
-rw-r--r--spec/unit/provider/zypper_repository_spec.rb13
-rw-r--r--spec/unit/resource/windows_pagefile_spec.rb13
-rw-r--r--spec/unit/resource/zypper_repository_spec.rb2
39 files changed, 691 insertions, 283 deletions
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 945fa0b503..9ea4b32227 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -19,7 +19,7 @@ jobs:
ruby-version: 2.7
bundler-cache: true
- uses: r7kamura/rubocop-problem-matchers-action@v1 # this shows the failures in the PR
- - run: bundle exec rake style
+ - run: bundle exec chefstyle -c .rubocop.yml
spellcheck:
runs-on: ubuntu-latest
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3ff3a30e87..a2590274ea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,17 +1,31 @@
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
This changelog lists individual merged pull requests to Chef Infra Client and geared towards developers. For a list of significant changes per release see the [Chef Infra Client Release Notes](https://docs.chef.io/release_notes_client/).
-<!-- latest_release 17.2.12 -->
-## [v17.2.12](https://github.com/chef/chef/tree/v17.2.12) (2021-05-27)
+<!-- latest_release 17.2.25 -->
+## [v17.2.25](https://github.com/chef/chef/tree/v17.2.25) (2021-06-07)
#### Merged Pull Requests
-- Bump inspec-core-bin to 4.37.20 [#11632](https://github.com/chef/chef/pull/11632) ([chef-expeditor[bot]](https://github.com/chef-expeditor[bot]))
+- Add ed25519 gem back to the omnibus install [#11664](https://github.com/chef/chef/pull/11664) ([tas50](https://github.com/tas50))
<!-- latest_release -->
<!-- release_rollup since=17.1.35 -->
### Changes not yet released to stable
#### Merged Pull Requests
+- Add ed25519 gem back to the omnibus install [#11664](https://github.com/chef/chef/pull/11664) ([tas50](https://github.com/tas50)) <!-- 17.2.25 -->
+- Cleanup the zypper_repository resource + support multiple GPG Keys [#11660](https://github.com/chef/chef/pull/11660) ([tas50](https://github.com/tas50)) <!-- 17.2.24 -->
+- Cleanup windows_printer_port and allow updating the port [#11662](https://github.com/chef/chef/pull/11662) ([tas50](https://github.com/tas50)) <!-- 17.2.23 -->
+- windows_printer: use powershell_exec to delete the printer instead of slower/double logging powershell_script [#11663](https://github.com/chef/chef/pull/11663) ([tas50](https://github.com/tas50)) <!-- 17.2.22 -->
+- Updated the Windows Pagefile resource to use PowerShell over WMI, added a corresponding test file [#11636](https://github.com/chef/chef/pull/11636) ([johnmccrae](https://github.com/johnmccrae)) <!-- 17.2.21 -->
+- Bump inspec-core-bin to 4.37.23 [#11655](https://github.com/chef/chef/pull/11655) ([chef-expeditor[bot]](https://github.com/chef-expeditor[bot])) <!-- 17.2.20 -->
+- Add tests to verify knife command load &amp; execution [#11653](https://github.com/chef/chef/pull/11653) ([marcparadise](https://github.com/marcparadise)) <!-- 17.2.19 -->
+- Fix incorrect require_relative causing failures in `knife org user add` [#11649](https://github.com/chef/chef/pull/11649) ([marcparadise](https://github.com/marcparadise)) <!-- 17.2.18 -->
+- Fix Chef::Handler specs and slow report behavior [#11648](https://github.com/chef/chef/pull/11648) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 17.2.17 -->
+- Support recipes that and in .yaml as well as .yml [#11629](https://github.com/chef/chef/pull/11629) ([marcparadise](https://github.com/marcparadise)) <!-- 17.2.16 -->
+- Make sure we load ohai in knife configure correctly [#11647](https://github.com/chef/chef/pull/11647) ([tas50](https://github.com/tas50)) <!-- 17.2.15 -->
+- Bump all deps to the latest [#11643](https://github.com/chef/chef/pull/11643) ([tas50](https://github.com/tas50)) <!-- 17.2.14 -->
+- Add a slow resources report to chef-client [#11642](https://github.com/chef/chef/pull/11642) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 17.2.13 -->
+- Bump chef/chefstyle to 082bbaf73d76000724f8d8ae3ba7f89c9123ad3f [#11635](https://github.com/chef/chef/pull/11635) ([chef-expeditor[bot]](https://github.com/chef-expeditor[bot])) <!-- 17.2.12 -->
- Bump inspec-core-bin to 4.37.20 [#11632](https://github.com/chef/chef/pull/11632) ([chef-expeditor[bot]](https://github.com/chef-expeditor[bot])) <!-- 17.2.12 -->
- Bump the knife ffi dep [#11618](https://github.com/chef/chef/pull/11618) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 17.2.11 -->
- inspec_waiver_file_entry: Autoload yaml and use dist file [#11552](https://github.com/chef/chef/pull/11552) ([tas50](https://github.com/tas50)) <!-- 17.2.10 -->
diff --git a/Gemfile b/Gemfile
index 4872842a5a..d25f5ef2bf 100644
--- a/Gemfile
+++ b/Gemfile
@@ -22,6 +22,7 @@ group(:omnibus_package) do
gem "rb-readline"
gem "inspec-core-bin", "~> 4.24" # need to provide the binaries for inspec
gem "chef-vault"
+ gem "ed25519", "~> 1.2" # to make it possible to install knife into chef. Remove this in Chef 18
end
group(:omnibus_package, :pry) do
diff --git a/Gemfile.lock b/Gemfile.lock
index 5e1c46f696..87bf08f0ce 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,10 +1,10 @@
GIT
remote: https://github.com/chef/chefstyle.git
- revision: aabbd0cd0b6ad646e55370277ee5af4eefed148a
+ revision: b257fe452318540c7016066beb845e0706917cb4
branch: master
specs:
- chefstyle (2.0.3)
- rubocop (= 1.14.0)
+ chefstyle (2.0.4)
+ rubocop (= 1.15.0)
GIT
remote: https://github.com/chef/ohai.git
@@ -35,10 +35,10 @@ GIT
PATH
remote: .
specs:
- chef (17.2.12)
+ chef (17.2.25)
addressable
- chef-config (= 17.2.12)
- chef-utils (= 17.2.12)
+ chef-config (= 17.2.25)
+ chef-utils (= 17.2.25)
chef-vault
chef-zero (>= 14.0.11)
diff-lcs (>= 1.2.4, < 1.4.0)
@@ -62,10 +62,10 @@ PATH
train-core (~> 3.2, >= 3.2.28)
train-winrm (>= 0.2.5)
uuidtools (>= 2.1.5, < 3.0)
- chef (17.2.12-universal-mingw32)
+ chef (17.2.25-universal-mingw32)
addressable
- chef-config (= 17.2.12)
- chef-utils (= 17.2.12)
+ chef-config (= 17.2.25)
+ chef-utils (= 17.2.25)
chef-vault
chef-zero (>= 14.0.11)
diff-lcs (>= 1.2.4, < 1.4.0)
@@ -104,15 +104,15 @@ PATH
PATH
remote: chef-bin
specs:
- chef-bin (17.2.12)
- chef (= 17.2.12)
+ chef-bin (17.2.25)
+ chef (= 17.2.25)
PATH
remote: chef-config
specs:
- chef-config (17.2.12)
+ chef-config (17.2.25)
addressable
- chef-utils (= 17.2.12)
+ chef-utils (= 17.2.25)
fuzzyurl
mixlib-config (>= 2.2.12, < 4.0)
mixlib-shellout (>= 2.0, < 4.0)
@@ -121,7 +121,7 @@ PATH
PATH
remote: chef-utils
specs:
- chef-utils (17.2.12)
+ chef-utils (17.2.25)
concurrent-ruby
GEM
@@ -152,11 +152,12 @@ GEM
chef-zero (>= 14.0)
net-ssh
coderay (1.1.3)
- concurrent-ruby (1.1.8)
+ concurrent-ruby (1.1.9)
crack (0.4.5)
rexml
debug_inspector (1.1.0)
diff-lcs (1.3)
+ ed25519 (1.2.4)
erubi (1.10.0)
erubis (2.7.0)
faraday (1.4.2)
@@ -194,7 +195,7 @@ GEM
hashie (4.1.0)
httpclient (2.8.3)
iniparse (1.5.0)
- inspec-core (4.37.20)
+ inspec-core (4.37.23)
addressable (~> 2.4)
chef-telemetry (~> 1.0, >= 1.0.8)
faraday (>= 0.9.0, < 1.5)
@@ -217,8 +218,8 @@ GEM
train-core (~> 3.0)
tty-prompt (~> 0.17)
tty-table (~> 0.10)
- inspec-core-bin (4.37.20)
- inspec-core (= 4.37.20)
+ inspec-core-bin (4.37.23)
+ inspec-core (= 4.37.23)
ipaddress (0.8.3)
iso8601 (0.13.0)
json (2.5.1)
@@ -294,7 +295,7 @@ GEM
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-support (3.10.2)
- rubocop (1.14.0)
+ rubocop (1.15.0)
parallel (~> 1.10)
parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0)
@@ -303,7 +304,7 @@ GEM
rubocop-ast (>= 1.5.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
- rubocop-ast (1.6.0)
+ rubocop-ast (1.7.0)
parser (>= 3.0.1.1)
ruby-progressbar (1.11.0)
ruby2_keywords (0.0.4)
@@ -414,6 +415,7 @@ DEPENDENCIES
chef-vault
cheffish (>= 17)
chefstyle!
+ ed25519 (~> 1.2)
fauxhai-ng
inspec-core-bin (~> 4.24)
ohai!
@@ -426,4 +428,4 @@ DEPENDENCIES
webmock
BUNDLED WITH
- 2.2.4
+ 2.2.19
diff --git a/VERSION b/VERSION
index 4a0d776d97..1b7ff0f664 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-17.2.12 \ No newline at end of file
+17.2.25 \ No newline at end of file
diff --git a/chef-bin/lib/chef-bin/version.rb b/chef-bin/lib/chef-bin/version.rb
index 1b68b3d488..aa1d8b99e3 100644
--- a/chef-bin/lib/chef-bin/version.rb
+++ b/chef-bin/lib/chef-bin/version.rb
@@ -21,7 +21,7 @@
module ChefBin
CHEFBIN_ROOT = File.expand_path("..", __dir__)
- VERSION = "17.2.12".freeze
+ VERSION = "17.2.25".freeze
end
#
diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb
index 3d73607b3b..b676cdffd1 100644
--- a/chef-config/lib/chef-config/version.rb
+++ b/chef-config/lib/chef-config/version.rb
@@ -15,5 +15,5 @@
module ChefConfig
CHEFCONFIG_ROOT = File.expand_path("..", __dir__)
- VERSION = "17.2.12".freeze
+ VERSION = "17.2.25".freeze
end
diff --git a/chef-utils/lib/chef-utils/version.rb b/chef-utils/lib/chef-utils/version.rb
index aa1d0c4e80..e423f26bb7 100644
--- a/chef-utils/lib/chef-utils/version.rb
+++ b/chef-utils/lib/chef-utils/version.rb
@@ -16,5 +16,5 @@
module ChefUtils
CHEFUTILS_ROOT = File.expand_path("..", __dir__)
- VERSION = "17.2.12"
+ VERSION = "17.2.25"
end
diff --git a/kitchen-tests/cookbooks/end_to_end/recipes/_windows_printer.rb b/kitchen-tests/cookbooks/end_to_end/recipes/_windows_printer.rb
new file mode 100644
index 0000000000..9b7f5c91d8
--- /dev/null
+++ b/kitchen-tests/cookbooks/end_to_end/recipes/_windows_printer.rb
@@ -0,0 +1,24 @@
+#
+# Cookbook:: end_to_end
+# Recipe:: _windows_printer
+#
+# Copyright:: Copyright (c) Chef Software Inc.
+#
+
+windows_printer_port "10.4.64.39" do
+ port_name "My awesome port"
+ snmp_enabled true
+ port_protocol 2
+end
+
+# change the port above
+windows_printer_port "10.4.64.39" do
+ port_name "My awesome port"
+ snmp_enabled false
+ port_protocol 2
+end
+
+# delete a port that doesn't exist
+windows_printer_port "10.4.64.37" do
+ action :delete
+end
diff --git a/kitchen-tests/cookbooks/end_to_end/recipes/windows.rb b/kitchen-tests/cookbooks/end_to_end/recipes/windows.rb
index e04396783b..f4cd74e3bf 100644
--- a/kitchen-tests/cookbooks/end_to_end/recipes/windows.rb
+++ b/kitchen-tests/cookbooks/end_to_end/recipes/windows.rb
@@ -176,3 +176,5 @@ end
windows_certificate "c:/mordor/ca.cert.pem" do
store_name "ROOT"
end
+
+include_recipe "::_windows_printer"
diff --git a/knife/lib/chef/knife/configure.rb b/knife/lib/chef/knife/configure.rb
index 4a73b6875b..9c806b4af6 100644
--- a/knife/lib/chef/knife/configure.rb
+++ b/knife/lib/chef/knife/configure.rb
@@ -29,7 +29,6 @@ class Chef
require "chef-config/path_helper" unless defined?(ChefConfig::PathHelper)
require_relative "client_create"
require_relative "user_create"
- require "ohai" unless defined?(Ohai)
Chef::Knife::ClientCreate.load_deps
Chef::Knife::UserCreate.load_deps
end
@@ -131,6 +130,7 @@ class Chef
# @return [String] our best guess at what the servername should be using Ohai data and falling back to localhost
def guess_servername
+ require "ohai" unless defined?(Ohai::System)
o = Ohai::System.new
o.all_plugins(%w{ os hostname fqdn })
o[:fqdn] || o[:machinename] || o[:hostname] || "localhost"
diff --git a/knife/lib/chef/knife/org_user_add.rb b/knife/lib/chef/knife/org_user_add.rb
index cd0ea88d56..d1fb3a2a5d 100644
--- a/knife/lib/chef/knife/org_user_add.rb
+++ b/knife/lib/chef/knife/org_user_add.rb
@@ -29,7 +29,7 @@ class Chef
description: "Add user to admin group"
deps do
- require_relative "../org"
+ require "chef/org"
end
def run
diff --git a/knife/lib/chef/knife/version.rb b/knife/lib/chef/knife/version.rb
index d73745a98f..03a77c9edf 100644
--- a/knife/lib/chef/knife/version.rb
+++ b/knife/lib/chef/knife/version.rb
@@ -17,7 +17,7 @@
class Chef
class Knife
KNIFE_ROOT = File.expand_path("../..", __dir__)
- VERSION = "17.2.12".freeze
+ VERSION = "17.2.25".freeze
end
end
diff --git a/knife/spec/integration/commands_spec.rb b/knife/spec/integration/commands_spec.rb
new file mode 100644
index 0000000000..a9626c38fc
--- /dev/null
+++ b/knife/spec/integration/commands_spec.rb
@@ -0,0 +1,55 @@
+#
+# Author:: Marc Pardise (<marc@chef.io>)
+# Copyright:: Copyright (c) Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require "chef/knife"
+
+Chef::Knife.subcommand_loader.load_commands
+commands = Chef::Knife::SubcommandLoader.generate_hash["_autogenerated_command_paths"]["plugins_paths"].keys
+
+# Directly execute each support knife command
+context "Command Sanity Check: executing ", :workstation do
+ describe "bundle exec knife" do
+ commands.each do |command|
+ command_name = command.gsub("_", " ")
+ modified_command, expected_result = case command_name
+ when /knife/
+ # because rspec is the actual executable running, the option parser error message
+ # is invalid from within the test.
+ next
+ when /config (use|get|list) profile.*/
+ # hyphenated special cases
+ [command_name, /^USAGE: knife config #{$1}-profile.*/]
+ when /(role|node|env) (env )?run list(.*)/
+ # underscored special cases...
+ env_part = $2.nil? ? "" : "env_"
+ ["#{$1} #{$2}run_list#{$3}", /^USAGE: knife #{$1} #{env_part}run_list#{$3}.*/]
+ else
+ [ command_name, /^USAGE: knife #{command_name}.*/]
+ end
+
+ # By using bundle exec knife instead of directly loading the command class or using the knife() helper,
+ # we ensure that this is a valid end-to-end test. This operates on the assumption
+ # that we continue to require the command class to be fully loaded so that it can handle the parsing of
+ # its own options.
+ full_command = "#{modified_command} --invalid-option outputs usage for '#{modified_command}' to stdout"
+ it full_command do
+ result = `bundle exec knife #{full_command}`
+ expect(result).to match(expected_result)
+ end
+ end
+ end
+end
diff --git a/lib/chef/action_collection.rb b/lib/chef/action_collection.rb
index 1ac47630a9..82a4ebb037 100644
--- a/lib/chef/action_collection.rb
+++ b/lib/chef/action_collection.rb
@@ -87,13 +87,11 @@ class Chef
attr_reader :action_records
attr_reader :pending_updates
attr_reader :run_context
- attr_reader :consumers
attr_reader :events
def initialize(events, run_context = nil, action_records = [])
@action_records = action_records
@pending_updates = []
- @consumers = []
@events = events
@run_context = run_context
end
@@ -118,17 +116,17 @@ class Chef
self.class.new(events, run_context, subrecords)
end
+ def resources
+ action_records.map(&:new_resource)
+ end
+
# This hook gives us the run_context immediately after it is created so that we can wire up this object to it.
#
- # This also causes the action_collection_registration event to fire, all consumers that have not yet registered with the
- # action_collection must register via this callback. This is the latest point before resources actually start to get
- # evaluated.
- #
# (see EventDispatch::Base#)
#
def cookbook_compilation_start(run_context)
run_context.action_collection = self
- # fire the action_colleciton_registration hook after cookbook_compilation_start -- last chance for consumers to register
+ # this hook is now poorly named since it is just a callback that lets other consumers snag a reference to the action_collection
run_context.events.enqueue(:action_collection_registration, self)
@run_context = run_context
end
@@ -139,7 +137,7 @@ class Chef
# @params object [Object] callers should call with `self`
#
def register(object)
- consumers << object
+ Chef::Log.warn "the action collection no longer requires registration at #{caller[0]}"
end
# End of an unsuccessful converge used to fire off detect_unprocessed_resources.
@@ -147,8 +145,6 @@ class Chef
# (see EventDispatch::Base#)
#
def converge_failed(exception)
- return if consumers.empty?
-
detect_unprocessed_resources
end
@@ -159,8 +155,6 @@ class Chef
# (see EventDispatch::Base#)
#
def resource_action_start(new_resource, action, notification_type = nil, notifier = nil)
- return if consumers.empty?
-
pending_updates << ActionRecord.new(new_resource, action, pending_updates.length)
end
@@ -170,8 +164,6 @@ class Chef
# (see EventDispatch::Base#)
#
def resource_current_state_loaded(new_resource, action, current_resource)
- return if consumers.empty?
-
current_record.current_resource = current_resource
end
@@ -181,8 +173,6 @@ class Chef
# (see EventDispatch::Base#)
#
def resource_after_state_loaded(new_resource, action, after_resource)
- return if consumers.empty?
-
current_record.after_resource = after_resource
end
@@ -191,8 +181,6 @@ class Chef
# (see EventDispatch::Base#)
#
def resource_up_to_date(new_resource, action)
- return if consumers.empty?
-
current_record.status = :up_to_date
end
@@ -201,8 +189,6 @@ class Chef
# (see EventDispatch::Base#)
#
def resource_skipped(resource, action, conditional)
- return if consumers.empty?
-
current_record.status = :skipped
current_record.conditional = conditional
end
@@ -212,8 +198,6 @@ class Chef
# (see EventDispatch::Base#)
#
def resource_updated(new_resource, action)
- return if consumers.empty?
-
current_record.status = :updated
end
@@ -222,8 +206,6 @@ class Chef
# (see EventDispatch::Base#)
#
def resource_failed(new_resource, action, exception)
- return if consumers.empty?
-
current_record.status = :failed
current_record.exception = exception
current_record.error_description = Formatters::ErrorMapper.resource_failed(new_resource, action, exception).for_json
@@ -234,8 +216,6 @@ class Chef
# (see EventDispatch::Base#)
#
def resource_completed(new_resource)
- return if consumers.empty?
-
current_record.elapsed_time = new_resource.elapsed_time
# Verify if the resource has sensitive data and create a new blank resource with only
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index 117f498831..356c4a4a30 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -310,7 +310,7 @@ class Chef
logger.info "Forking #{ChefUtils::Dist::Infra::PRODUCT} instance to converge..."
pid = fork do
# Want to allow forked processes to finish converging when
- # TERM singal is received (exit gracefully)
+ # TERM signal is received (exit gracefully)
trap("TERM") do
logger.debug("SIGTERM received during converge," +
" finishing converge to exit normally (send SIGINT to terminate immediately)")
diff --git a/lib/chef/application/base.rb b/lib/chef/application/base.rb
index 450fd7673b..b2f98d5f2f 100644
--- a/lib/chef/application/base.rb
+++ b/lib/chef/application/base.rb
@@ -297,6 +297,21 @@ class Chef::Application::Base < Chef::Application
long: "--named-run-list NAMED_RUN_LIST",
description: "Use a policyfile's named run list instead of the default run list."
+ option :slow_report,
+ long: "--[no-]slow-report [COUNT]",
+ description: "List the slowest resources at the end of the run (default: 10).",
+ boolean: true,
+ default: false,
+ proc: lambda { |argument|
+ if argument.nil?
+ true
+ elsif argument == false
+ false
+ else
+ Integer(argument)
+ end
+ }
+
IMMEDIATE_RUN_SIGNAL = "1".freeze
RECONFIGURE_SIGNAL = "H".freeze
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index 54d2a95ba3..3a312701d2 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -863,6 +863,12 @@ class Chef
end
def start_profiling
+ if Chef::Config[:slow_report]
+ require_relative "handler/slow_report"
+
+ Chef::Config.report_handlers << Chef::Handler::SlowReport.new(Chef::Config[:slow_report])
+ end
+
return unless Chef::Config[:profile_ruby]
profiling_prereqs!
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 420532585a..6e4f13c291 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -138,11 +138,14 @@ class Chef
end
def recipe_yml_filenames_by_name
- @recipe_ym_filenames_by_name ||= begin
+ @recipe_yml_filenames_by_name ||= begin
name_map = yml_filenames_by_name(files_for("recipes"))
- root_alias = cookbook_manifest.root_files.find { |record| record[:name] == "root_files/recipe.yml" }
+ root_alias = cookbook_manifest.root_files.find { |record|
+ record[:name] == "root_files/recipe.yml" ||
+ record[:name] == "root_files/recipe.yaml"
+ }
if root_alias
- Chef::Log.error("Cookbook #{name} contains both recipe.yml and and recipes/default.yml, ignoring recipes/default.yml") if name_map["default"]
+ Chef::Log.error("Cookbook #{name} contains both recipe.yml and recipes/default.yml, ignoring recipes/default.yml") if name_map["default"]
name_map["default"] = root_alias[:full_path]
end
name_map
@@ -582,8 +585,27 @@ class Chef
records.select { |record| record[:name] =~ /\.rb$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".rb")] = record[:full_path]; memo }
end
+ # Filters YAML files from the superset of provided files.
+ # Checks for duplicate basenames with differing extensions (eg yaml v yml)
+ # and raises error if any are detected.
+ # This prevents us from arbitrarily the ".yaml" or ".yml" version when both are present,
+ # because we don't know which is correct.
+ # This method runs in O(n^2) where N = number of yml files present. This number should be consistently
+ # low enough that there's no noticeable perf impact.
def yml_filenames_by_name(records)
- records.select { |record| record[:name] =~ /\.yml$/ }.inject({}) { |memo, record| memo[File.basename(record[:name], ".yml")] = record[:full_path]; memo }
+ yml_files = records.select { |record| record[:name] =~ /\.(y[a]?ml)$/ }
+ result = yml_files.inject({}) do |acc, record|
+ filename = record[:name]
+ base_dup_name = File.join(File.dirname(filename), File.basename(filename, File.extname(filename)))
+ yml_files.each do |other|
+ if other[:name] =~ /#{(File.extname(filename) == ".yml") ? "#{base_dup_name}.yaml" : "#{base_dup_name}.yml"}$/
+ raise Chef::Exceptions::AmbiguousYAMLFile.new("Cookbook #{name}@#{version} contains ambiguous files: #{filename} and #{other[:name]}. Please update the cookbook to remove the incorrect file.")
+ end
+ end
+ acc[File.basename(record[:name], File.extname(record[:name]))] = record[:full_path]
+ acc
+ end
+ result
end
def file_vendor
diff --git a/lib/chef/data_collector.rb b/lib/chef/data_collector.rb
index 8d76f8a7b2..0e621f1492 100644
--- a/lib/chef/data_collector.rb
+++ b/lib/chef/data_collector.rb
@@ -104,7 +104,6 @@ class Chef
#
def action_collection_registration(action_collection)
@action_collection = action_collection
- action_collection.register(self)
end
# - Creates and writes our NodeUUID back to the node object
diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb
index f7b706cb2c..f9504967a9 100644
--- a/lib/chef/event_dispatch/base.rb
+++ b/lib/chef/event_dispatch/base.rb
@@ -221,7 +221,8 @@ class Chef
# Called before convergence starts
def converge_start(run_context); end
- # Callback hook for handlers to register their interest in the action_collection
+ # Callback hook for handlers to grab a reference to the action_collection
+ # (sent before compiling cookbooks, consumers can also find it off the run_context.action_collection)
def action_collection_registration(action_collection); end
# Called when the converge phase is finished.
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb
index a0afd25208..ba34b22e61 100644
--- a/lib/chef/exceptions.rb
+++ b/lib/chef/exceptions.rb
@@ -174,6 +174,9 @@ class Chef
class CannotDetermineWindowsInstallerType < Package; end
class NoWindowsPackageSource < Package; end
+ # for example, if both recipes/default.yml, recipes/default.yaml are present
+ class AmbiguousYAMLFile < RuntimeError; end
+
# Can not create staging file during file deployment
class FileContentStagingError < RuntimeError
def initialize(errors)
diff --git a/lib/chef/handler.rb b/lib/chef/handler.rb
index 97562ea31b..173d4c4faa 100644
--- a/lib/chef/handler.rb
+++ b/lib/chef/handler.rb
@@ -55,6 +55,12 @@ class Chef
#
class Handler
+ # FIXME: Chef::Handler should probably inherit from EventDispatch::Base
+ # and should wire up to those events rather than the "notifications" system
+ # which is hanging off of Chef::Client. Those "notifications" could then be
+ # deprecated in favor of events, and this class could become decoupled from
+ # the Chef::Client object.
+
def self.handler_for(*args)
if args.include?(:start)
Chef::Config[:start_handlers] ||= []
@@ -207,17 +213,45 @@ class Chef
# The Chef::Node for this client run
def_delegator :@run_status, :node
- ##
- # :method: all_resources
+ # @return Array<Chef::Resource> all resources other than unprocessed
#
- # An Array containing all resources in the chef run's resource_collection
- def_delegator :@run_status, :all_resources
+ def all_resources
+ @all_resources ||= action_collection&.filtered_collection(unprocessed: false)&.resources || []
+ end
- ##
- # :method: updated_resources
+ # @return Array<Chef::Resource> all updated resources
+ #
+ def updated_resources
+ @updated_resources ||= action_collection&.filtered_collection(up_to_date: false, skipped: false, failed: false, unprocessed: false)&.resources || []
+ end
+
+ # @return Array<Chef::Resource> all up_to_date resources
+ #
+ def up_to_date_resources
+ @up_to_date_resources ||= action_collection&.filtered_collection(updated: false, skipped: false, failed: false, unprocessed: false)&.resources || []
+ end
+
+ # @return Array<Chef::Resource> all failed resources
#
- # An Array containing all resources that were updated during the chef run
- def_delegator :@run_status, :updated_resources
+ def failed_resources
+ @failed_resources ||= action_collection&.filtered_collection(updated: false, up_to_date: false, skipped: false, unprocessed: false)&.resources || []
+ end
+
+ # @return Array<Chef::Resource> all skipped resources
+ #
+ def skipped_resources
+ @skipped_resources ||= action_collection&.filtered_collection(updated: false, up_to_date: false, failed: false, unprocessed: false)&.resources || []
+ end
+
+ # Unprocessed resources are those which are left over in the outer recipe context when a run fails.
+ # Sub-resources of unprocessed resourced are impossible to capture because they would require processing
+ # the outer resource.
+ #
+ # @return Array<Chef::Resource> all unprocessed resources
+ #
+ def unprocessed_resources
+ @unprocessed_resources ||= action_collection&.filtered_collection(updated: false, up_to_date: false, failed: false, skipped: false)&.resources || []
+ end
##
# :method: success?
@@ -232,6 +266,10 @@ class Chef
# Did the chef run fail? True if the chef run raised an uncaught exception
def_delegator :@run_status, :failed?
+ def action_collection
+ @run_status.run_context.action_collection
+ end
+
# The main entry point for report handling. Subclasses should override this
# method with their own report handling logic.
def report; end
diff --git a/lib/chef/handler/slow_report.rb b/lib/chef/handler/slow_report.rb
new file mode 100644
index 0000000000..7bb472f4d5
--- /dev/null
+++ b/lib/chef/handler/slow_report.rb
@@ -0,0 +1,66 @@
+#
+# Copyright:: Copyright (c) Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require_relative "../handler"
+require "tty/table" unless defined?(TTY::Table)
+
+class Chef
+ class Handler
+ class SlowReport < ::Chef::Handler
+ attr_accessor :amount
+
+ def initialize(amount)
+ @amount = Integer(amount) rescue nil
+ @amount ||= 10
+ end
+
+ def report
+ if count == 0
+ puts "\nNo resources to profile\n\n"
+ return
+ end
+
+ top = all_records.sort_by(&:elapsed_time).last(amount).reverse
+ data = top.map { |r| [ r.new_resource.to_s, r.elapsed_time, r.action, r.new_resource.cookbook_name, r.new_resource.recipe_name, stripped_source_line(r.new_resource) ] }
+ puts "\nTop #{count} slowest #{count == 1 ? "resource" : "resources"}:\n\n"
+ table = TTY::Table.new(%w{resource elapsed_time action cookbook recipe source}, data)
+ rendered = table.render do |renderer|
+ renderer.border do
+ mid "-"
+ mid_mid " "
+ end
+ end
+ puts rendered
+ puts "\n"
+ end
+
+ def all_records
+ @all_records ||= action_collection&.filtered_collection(unprocessed: false) || []
+ end
+
+ def count
+ num = all_resources.count
+ num > amount ? amount : num
+ end
+
+ def stripped_source_line(resource)
+ # strip the leading path off of the source line
+ resource.source_line.gsub(%r{.*/cookbooks/}, "").gsub(%r{.*/chef-[0-9\.]+/}, "")
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/support/zypper_repo.erb b/lib/chef/provider/support/zypper_repo.erb
index 6d508fa77f..23e871e406 100644
--- a/lib/chef/provider/support/zypper_repo.erb
+++ b/lib/chef/provider/support/zypper_repo.erb
@@ -1,15 +1,17 @@
-# This file was generated by Chef
+# This file was generated by Chef Infra
# Do NOT modify this file by hand.
[<%= @config.repo_name %>]
<% %w{ type enabled autorefresh gpgcheck gpgkey baseurl mirrorlist path priority keeppackages mode refresh_cache }.each do |prop| -%>
-<% next if @config.send(prop.to_sym).nil? -%>
+<% next if @config.send(prop.to_sym).nil? || (@config.send(prop.to_sym).is_a?(Array) && @config.send(prop.to_sym).empty?) -%>
<%= prop %>=<%=
case @config.send(prop.to_sym)
when TrueClass
'1'
when FalseClass
'0'
+ when Array
+ @config.send(prop.to_sym).join("\n ")
else
@config.send(prop.to_sym)
end %>
diff --git a/lib/chef/provider/zypper_repository.rb b/lib/chef/provider/zypper_repository.rb
index bbb25ee6cd..c1c863e20e 100644
--- a/lib/chef/provider/zypper_repository.rb
+++ b/lib/chef/provider/zypper_repository.rb
@@ -31,12 +31,12 @@ class Chef
action :create do
if new_resource.gpgautoimportkeys
- install_gpg_key(new_resource.gpgkey)
+ install_gpg_keys(new_resource.gpgkey)
else
logger.debug("'gpgautoimportkeys' property is set to false. Skipping key import.")
end
- declare_resource(:template, "/etc/zypp/repos.d/#{escaped_repo_name}.repo") do
+ template "/etc/zypp/repos.d/#{escaped_repo_name}.repo" do
if template_available?(new_resource.source)
source new_resource.source
else
@@ -51,13 +51,13 @@ class Chef
end
action :delete do
- declare_resource(:execute, "zypper --quiet --non-interactive removerepo #{escaped_repo_name}") do
+ execute "zypper --quiet --non-interactive removerepo #{escaped_repo_name}" do
only_if "zypper --quiet lr #{escaped_repo_name}"
end
end
action :refresh do
- declare_resource(:execute, "zypper --quiet --non-interactive refresh --force #{escaped_repo_name}") do
+ execute "zypper --quiet --non-interactive refresh --force #{escaped_repo_name}" do
only_if "zypper --quiet lr #{escaped_repo_name}"
end
end
@@ -68,15 +68,7 @@ class Chef
# zypper repos are allowed to have spaces in the names
# @return [String] escaped repo string
def escaped_repo_name
- Shellwords.escape(new_resource.repo_name)
- end
-
- # return the specified cookbook name or the cookbook containing the
- # resource.
- #
- # @return [String] name of the cookbook
- def cookbook_name
- new_resource.cookbook || new_resource.cookbook_name
+ @escaped_repo_name ||= Shellwords.escape(new_resource.repo_name)
end
# determine if a template file is available in the current run
@@ -84,7 +76,7 @@ class Chef
#
# @return [Boolean] template file exists or doesn't
def template_available?(path)
- !path.nil? && run_context.has_template_in_cookbook?(cookbook_name, path)
+ !path.nil? && run_context.has_template_in_cookbook?(new_resource.cookbook, path)
end
# determine if a cookbook file is available in the run
@@ -92,7 +84,7 @@ class Chef
#
# @return [Boolean] cookbook file exists or doesn't
def has_cookbook_file?(fn)
- run_context.has_cookbook_file_in_cookbook?(cookbook_name, fn)
+ run_context.has_cookbook_file_in_cookbook?(new_resource.cookbook, fn)
end
# Given the provided key URI determine what kind of chef resource we need
@@ -158,27 +150,31 @@ class Chef
short_key_id
end
- # install the provided gpg key
- # @param [String] uri the uri of the local or remote gpg key
- def install_gpg_key(uri)
- unless uri
- logger.debug("'gpgkey' property not provided or set to nil. Skipping key import.")
+ # install the provided gpg keys
+ # @param [String] uris the uri of the local or remote gpg key
+ def install_gpg_keys(uris)
+ if uris.empty?
+ logger.debug("'gpgkey' property not provided or set. Skipping gpg key import.")
return
end
- cached_keyfile = ::File.join(Chef::Config[:file_cache_path], uri.split("/")[-1])
+ # fetch each key to the cache dir either from the cookbook or by downloading it
+ # and then import the key
+ uris.each do |uri|
+ cached_keyfile = ::File.join(Chef::Config[:file_cache_path], uri.split("/")[-1])
- declare_resource(key_type(new_resource.gpgkey), cached_keyfile) do
- source uri
- mode "0644"
- sensitive new_resource.sensitive
- action :create
- end
+ declare_resource(key_type(uri), cached_keyfile) do
+ source uri
+ mode "0644"
+ sensitive new_resource.sensitive
+ action :create
+ end
- declare_resource(:execute, "import gpg key from #{new_resource.gpgkey}") do
- command "/bin/rpm --import #{cached_keyfile}"
- not_if { key_installed?(cached_keyfile) }
- action :run
+ execute "import gpg key from #{uri}" do
+ command "/bin/rpm --import #{cached_keyfile}"
+ not_if { key_installed?(cached_keyfile) }
+ action :run
+ end
end
end
end
diff --git a/lib/chef/resource/windows_pagefile.rb b/lib/chef/resource/windows_pagefile.rb
index a5f6052849..6fb63f2f3b 100644
--- a/lib/chef/resource/windows_pagefile.rb
+++ b/lib/chef/resource/windows_pagefile.rb
@@ -39,16 +39,26 @@ class Chef
```ruby
windows_pagefile 'Delete the pagefile' do
- path 'C:\pagefile.sys'
+ path 'C'
action :delete
end
```
+ **Switch to system managed pagefiles**:
+
+ ```ruby
+ windows_pagefile 'Change the pagefile to System Managed' do
+ path 'E:\'
+ system_managed true
+ action :set
+ end
+ ```
+
**Create a pagefile with an initial and maximum size**:
```ruby
- windows_pagefile 'create the pagefile' do
- path 'C:\pagefile.sys'
+ windows_pagefile 'create the pagefile with these sizes' do
+ path 'f:\'
initial_size 100
maximum_size 200
end
@@ -64,8 +74,7 @@ class Chef
description: "Configures whether the system manages the pagefile size."
property :automatic_managed, [TrueClass, FalseClass],
- description: "Enable automatic management of pagefile initial and maximum size. Setting this to true ignores `initial_size` and `maximum_size` properties.",
- default: false
+ description: "Enable automatic management of pagefile initial and maximum size. Setting this to true ignores `initial_size` and `maximum_size` properties."
property :initial_size, Integer,
description: "Initial size of the pagefile in megabytes."
@@ -74,22 +83,25 @@ class Chef
description: "Maximum size of the pagefile in megabytes."
action :set, description: "Configures the default pagefile, creating if it doesn't exist." do
- pagefile = new_resource.path
- initial_size = new_resource.initial_size
- maximum_size = new_resource.maximum_size
- system_managed = new_resource.system_managed
automatic_managed = new_resource.automatic_managed
if automatic_managed
set_automatic_managed unless automatic_managed?
- else
+ elsif automatic_managed == false
unset_automatic_managed if automatic_managed?
+ else
+ pagefile = clarify_pagefile_name
+ initial_size = new_resource.initial_size
+ maximum_size = new_resource.maximum_size
+ system_managed = new_resource.system_managed
- # Check that the resource is not just trying to unset automatic managed, if it is do nothing more
- if (initial_size && maximum_size) || system_managed
- validate_name
- create(pagefile) unless exists?(pagefile)
+ # the method below is designed to raise an exception if the drive you are trying to create a pagefile for doesn't exist.
+ # PowerShell will happily let you create a pagefile called h:\pagefile.sys even though you don't have an H:\ drive.
+
+ pagefile_drive_exist?(pagefile)
+ create(pagefile) unless exists?(pagefile)
+ if (initial_size && maximum_size) || system_managed
if system_managed
set_system_managed(pagefile) unless max_and_min_set?(pagefile, 0, 0)
else
@@ -102,20 +114,32 @@ class Chef
end
action :delete, description: "Deletes the specified pagefile." do
- validate_name
- delete(new_resource.path) if exists?(new_resource.path)
+ pagefile = clarify_pagefile_name
+ delete(pagefile) if exists?(pagefile)
end
action_class do
private
- # make sure the provided name property matches the appropriate format
- # we do this here and not in the property itself because if automatic_managed
- # is set then this validation is not necessary / doesn't make sense at all
- def validate_name
- return if /^.:.*.sys/.match?(new_resource.path)
+ # We are adding support for a number of possibilities for how users will express the drive and location they want the pagefile written to.
+ def clarify_pagefile_name
+ case new_resource.path
+ # user enters C, C:, C:\, C:\\
+ when /^[a-zA-Z]/
+ new_resource.path[0] + ":\\pagefile.sys"
+ # user enters C:\pagefile.sys OR c:\foo\bar\pagefile.sys as the path
+ when /^[a-zA-Z]:.*.sys/
+ new_resource.path
+ else
+ raise "#{new_resource.path} does not match the format DRIVE:\\path\\pagefile.sys for pagefiles. Example: C:\\pagefile.sys"
+ end
+ end
- raise "#{new_resource.path} does not match the format DRIVE:\\path\\file.sys for pagefiles. Example: C:\\pagefile.sys"
+ # raise an exception if the target drive location is invalid
+ def pagefile_drive_exist?(pagefile)
+ if ::Dir.exist?(pagefile[0] + ":\\") == false
+ raise "You are trying to create a pagefile on a drive that does not exist!"
+ end
end
# See if the pagefile exists
@@ -124,9 +148,11 @@ class Chef
# @return [Boolean]
def exists?(pagefile)
@exists ||= begin
- logger.trace("Checking if #{pagefile} exists by running: wmic.exe pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" list /format:list")
- cmd = shell_out("wmic.exe pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" list /format:list", returns: [0])
- cmd.stderr.empty? && (cmd.stdout =~ /SettingID=#{get_setting_id(pagefile)}/i)
+ logger.trace("Checking if #{pagefile} exists by running: Get-CimInstance Win32_PagefileSetting | Where-Object { $_.name -eq $($pagefile)} ")
+ cmd = "$page_file_name = '#{pagefile}';"
+ cmd << "$pagefile = Get-CimInstance Win32_PagefileSetting | Where-Object { $_.name -eq $($page_file_name)};"
+ cmd << "if ([string]::IsNullOrEmpty($pagefile)) { return $false } else { return $true }"
+ powershell_exec!(cmd).result
end
end
@@ -137,11 +163,14 @@ class Chef
# @param [String] max the minimum size of the pagefile
# @return [Boolean]
def max_and_min_set?(pagefile, min, max)
- @max_and_min_set ||= begin
- logger.trace("Checking if #{pagefile} min: #{min} and max #{max} are set")
- cmd = shell_out("wmic.exe pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" list /format:list", returns: [0])
- cmd.stderr.empty? && (cmd.stdout =~ /InitialSize=#{min}/i) && (cmd.stdout =~ /MaximumSize=#{max}/i)
- end
+ logger.trace("Checking if #{pagefile} has max and initial disk size values set")
+ cmd = "$page_file = '#{pagefile}';"
+ cmd << "$driveLetter = $page_file.split(':')[0];"
+ cmd << "$page_file_settings = Get-CimInstance -ClassName Win32_PageFileSetting -Filter \"SettingID='pagefile.sys @ $($driveLetter):'\" -Property * -ErrorAction Stop;"
+ cmd << "if ($page_file_settings.InitialSize -eq #{min} -and $page_file_settings.MaximumSize -eq #{max})"
+ cmd << "{ return $true }"
+ cmd << "else { return $false }"
+ powershell_exec!(cmd).result
end
# create a pagefile
@@ -149,9 +178,10 @@ class Chef
# @param [String] pagefile path to the pagefile
def create(pagefile)
converge_by("create pagefile #{pagefile}") do
- logger.trace("Running wmic.exe pagefileset create name=\"#{pagefile}\"")
- cmd = shell_out("wmic.exe pagefileset create name=\"#{pagefile}\"")
- check_for_errors(cmd.stderr)
+ logger.trace("Running New-CimInstance -ClassName Win32_PageFileSetting to create new pagefile : #{pagefile}")
+ powershell_exec! <<~ELM
+ New-CimInstance -ClassName Win32_PageFileSetting -Property @{Name = "#{pagefile}"}
+ ELM
end
end
@@ -160,9 +190,13 @@ class Chef
# @param [String] pagefile path to the pagefile
def delete(pagefile)
converge_by("remove pagefile #{pagefile}") do
- logger.trace("Running wmic.exe pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" delete")
- cmd = shell_out("wmic.exe pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" delete")
- check_for_errors(cmd.stderr)
+ logger.trace("Running Remove-CimInstance for pagefile : #{pagefile}")
+ powershell_exec! <<~EOL
+ $page_file = "#{pagefile}"
+ $driveLetter = $page_file.split(':')[0]
+ $PageFile = (Get-CimInstance -ClassName Win32_PageFileSetting -Filter "SettingID='pagefile.sys @ $($driveLetter):'" -ErrorAction Stop)
+ $null = ($PageFile | Remove-CimInstance -ErrorAction SilentlyContinue)
+ EOL
end
end
@@ -172,26 +206,31 @@ class Chef
def automatic_managed?
@automatic_managed ||= begin
logger.trace("Checking if pagefiles are automatically managed")
- cmd = shell_out("wmic.exe computersystem where name=\"%computername%\" get AutomaticManagedPagefile /format:list")
- cmd.stderr.empty? && (cmd.stdout =~ /AutomaticManagedPagefile=TRUE/i)
+ cmd = "$sys = Get-CimInstance Win32_ComputerSystem -Property *;"
+ cmd << "return $sys.AutomaticManagedPagefile"
+ powershell_exec!(cmd).result
end
end
# turn on automatic management of all pagefiles by Windows
def set_automatic_managed
- converge_by("set pagefile to Automatic Managed") do
- logger.trace("Running wmic.exe computersystem where name=\"%computername%\" set AutomaticManagedPagefile=True")
- cmd = shell_out("wmic.exe computersystem where name=\"%computername%\" set AutomaticManagedPagefile=True")
- check_for_errors(cmd.stderr)
+ converge_by("Set pagefile to Automatic Managed") do
+ logger.trace("Running Set-CimInstance -InputObject $sys -Property @{AutomaticManagedPagefile=$true} -PassThru")
+ powershell_exec! <<~EOH
+ $sys = Get-CimInstance Win32_ComputerSystem -Property *
+ Set-CimInstance -InputObject $sys -Property @{AutomaticManagedPagefile=$true} -PassThru
+ EOH
end
end
# turn off automatic management of all pagefiles by Windows
def unset_automatic_managed
- converge_by("set pagefile to User Managed") do
- logger.trace("Running wmic.exe computersystem where name=\"%computername%\" set AutomaticManagedPagefile=False")
- cmd = shell_out("wmic.exe computersystem where name=\"%computername%\" set AutomaticManagedPagefile=False")
- check_for_errors(cmd.stderr)
+ converge_by("Turn off Automatically Managed on pagefiles") do
+ logger.trace("Running Set-CimInstance -InputObject $sys -Property @{AutomaticManagedPagefile=$false} -PassThru")
+ powershell_exec! <<~EOH
+ $sys = Get-CimInstance Win32_ComputerSystem -Property *
+ Set-CimInstance -InputObject $sys -Property @{AutomaticManagedPagefile=$false} -PassThru
+ EOH
end
end
@@ -202,9 +241,14 @@ class Chef
# @param [String] max the minimum size of the pagefile
def set_custom_size(pagefile, min, max)
converge_by("set #{pagefile} to InitialSize=#{min} & MaximumSize=#{max}") do
- logger.trace("Running wmic.exe pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" set InitialSize=#{min},MaximumSize=#{max}")
- cmd = shell_out("wmic.exe pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" set InitialSize=#{min},MaximumSize=#{max}", returns: [0])
- check_for_errors(cmd.stderr)
+ logger.trace("Set-CimInstance -Property @{InitialSize = #{min} MaximumSize = #{max}")
+ powershell_exec! <<~EOD
+ $page_file = "#{pagefile}"
+ $driveLetter = $page_file.split(':')[0]
+ Get-CimInstance -ClassName Win32_PageFileSetting -Filter "SettingID='pagefile.sys @ $($driveLetter):'" -ErrorAction Stop | Set-CimInstance -Property @{
+ InitialSize = #{min}
+ MaximumSize = #{max}}
+ EOD
end
end
@@ -213,21 +257,16 @@ class Chef
# @param [String] pagefile path to the pagefile
def set_system_managed(pagefile)
converge_by("set #{pagefile} to System Managed") do
- logger.trace("Running wmic.exe pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" set InitialSize=0,MaximumSize=0")
- cmd = shell_out("wmic.exe pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" set InitialSize=0,MaximumSize=0", returns: [0])
- check_for_errors(cmd.stderr)
+ logger.trace("Running ")
+ powershell_exec! <<~EOM
+ $page_file = "#{pagefile}"
+ $driveLetter = $page_file.split(':')[0]
+ Get-CimInstance -ClassName Win32_PageFileSetting -Filter "SettingID='pagefile.sys @ $($driveLetter):'" -ErrorAction Stop | Set-CimInstance -Property @{
+ InitialSize = 0
+ MaximumSize = 0}
+ EOM
end
end
-
- def get_setting_id(pagefile)
- split_path = pagefile.split("\\")
- "#{split_path[1]} @ #{split_path[0]}"
- end
-
- # raise if there's an error on stderr on a shellout
- def check_for_errors(stderr)
- raise stderr.chomp unless stderr.empty?
- end
end
end
end
diff --git a/lib/chef/resource/windows_printer.rb b/lib/chef/resource/windows_printer.rb
index c8d869b6b4..b1d6e29374 100644
--- a/lib/chef/resource/windows_printer.rb
+++ b/lib/chef/resource/windows_printer.rb
@@ -1,6 +1,7 @@
#
# Author:: Doug Ireton (<doug@1strategy.com>)
# Copyright:: 2012-2018, Nordstrom, Inc.
+# Copyright:: Chef Software, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -102,17 +103,15 @@ class Chef
action :delete, description: "Delete an existing printer. Note that this resource does not delete the associated printer port." do
if printer_exists?
- converge_by("Delete #{@new_resource}") do
- delete_printer
+ converge_by("Delete #{new_resource.device_id}") do
+ powershell_exec!("Remove-Printer -Name '#{new_resource.device_id}'")
end
else
- Chef::Log.info "#{@current_resource} doesn't exist - can't delete."
+ Chef::Log.info "#{new_resource.device_id} doesn't exist - can't delete."
end
end
action_class do
- private
-
# does the printer exist
#
# @param [String] name the name of the printer
@@ -132,7 +131,6 @@ class Chef
declare_resource(:powershell_script, "Creating printer: #{new_resource.device_id}") do
code <<-EOH
-
Set-WmiInstance -class Win32_Printer `
-EnableAllPrivileges `
-Argument @{ DeviceID = "#{new_resource.device_id}";
@@ -147,15 +145,6 @@ class Chef
EOH
end
end
-
- def delete_printer
- declare_resource(:powershell_script, "Deleting printer: #{new_resource.device_id}") do
- code <<-EOH
- $printer = Get-WMIObject -class Win32_Printer -EnableAllPrivileges -Filter "name = '#{new_resource.device_id}'"
- $printer.Delete()
- EOH
- end
- end
end
end
end
diff --git a/lib/chef/resource/windows_printer_port.rb b/lib/chef/resource/windows_printer_port.rb
index ae58ed3c6c..b109528b5d 100644
--- a/lib/chef/resource/windows_printer_port.rb
+++ b/lib/chef/resource/windows_printer_port.rb
@@ -1,6 +1,7 @@
#
# Author:: Doug Ireton <doug@1strategy.com>
# Copyright:: 2012-2018, Nordstrom, Inc.
+# Copyright:: Chef Software, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -68,14 +69,17 @@ class Chef
}
property :port_name, String,
- description: "The port name."
+ description: "The port name.",
+ default: lazy { |x| "IP_#{x.ipv4_address}" },
+ default_description: "The resource block name or the ipv4_address prepended with IP_."
property :port_number, Integer,
- description: "The port number.",
+ description: "The TCP port number.",
default: 9100
property :port_description, String,
- description: "The description of the port."
+ desired_state: false,
+ deprecated: true
property :snmp_enabled, [TrueClass, FalseClass],
description: "Determines if SNMP is enabled on the port.",
@@ -86,75 +90,58 @@ class Chef
validation_message: "port_protocol must be either 1 for RAW or 2 for LPR!",
default: 1, equal_to: [1, 2]
- PORTS_REG_KEY = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\\'.freeze unless defined?(PORTS_REG_KEY)
-
- # @todo Set @current_resource port properties from registry
load_current_value do |new_resource|
- name new_resource.name
- ipv4_address new_resource.ipv4_address
- port_name new_resource.port_name || "IP_#{new_resource.ipv4_address}"
- end
-
- action :create, description: "Create the printer port, if one doesn't already exist." do
- if port_exists?
- Chef::Log.info "#{@new_resource} already exists - nothing to do."
- else
- converge_by("Create #{@new_resource}") do
- create_printer_port
- end
- end
- end
+ port_data = powershell_exec(%Q{Get-WmiObject -Class Win32_TCPIPPrinterPort -Filter "Name='#{new_resource.port_name}'"}).result
- action :delete, description: "Delete an existing printer port." do
- if port_exists?
- converge_by("Delete #{@new_resource}") do
- delete_printer_port
- end
+ if port_data.empty?
+ current_value_does_not_exist!
else
- Chef::Log.info "#{@current_resource} doesn't exist - can't delete."
+ ipv4_address port_data["HostAddress"]
+ port_name port_data["Name"]
+ snmp_enabled port_data["SNMPEnabled"]
+ port_protocol port_data["Protocol"]
+ port_number port_data["PortNumber"]
end
end
- action_class do
- private
-
- def port_exists?
- name = new_resource.port_name || "IP_#{new_resource.ipv4_address}"
- port_reg_key = PORTS_REG_KEY + name
-
- logger.trace "Checking to see if this reg key exists: '#{port_reg_key}'"
- registry_key_exists?(port_reg_key)
- end
-
- def create_printer_port
- port_name = new_resource.port_name || "IP_#{new_resource.ipv4_address}"
-
- # create the printer port using PowerShell
- declare_resource(:powershell_script, "Creating printer port #{new_resource.port_name}") do
- code <<-EOH
-
- Set-WmiInstance -class Win32_TCPIPPrinterPort `
- -EnableAllPrivileges `
- -Argument @{ HostAddress = "#{new_resource.ipv4_address}";
- Name = "#{port_name}";
- Description = "#{new_resource.port_description}";
- PortNumber = "#{new_resource.port_number}";
- Protocol = "#{new_resource.port_protocol}";
- SNMPEnabled = "$#{new_resource.snmp_enabled}";
- }
+ action :create, description: "Create or update the printer port." do
+ converge_if_changed do
+ if current_resource
+ # update the printer port using PowerShell
+ powershell_exec! <<-EOH
+ Get-WmiObject Win32_TCPIPPrinterPort -EnableAllPrivileges -filter "Name='#{new_resource.port_name}'" |
+ ForEach-Object{
+ $_.HostAddress='#{new_resource.ipv4_address}'
+ $_.PortNumber='#{new_resource.port_number}'
+ $_.Protocol='#{new_resource.port_protocol}'
+ $_.SNMPEnabled='$#{new_resource.snmp_enabled}'
+ $_.Put()
+ }
+ EOH
+ else
+ # create the printer port using PowerShell
+ powershell_exec! <<-EOH
+ Set-WmiInstance -class Win32_TCPIPPrinterPort `
+ -EnableAllPrivileges `
+ -Argument @{ HostAddress = "#{new_resource.ipv4_address}";
+ Name = "#{new_resource.port_name}";
+ PortNumber = "#{new_resource.port_number}";
+ Protocol = "#{new_resource.port_protocol}";
+ SNMPEnabled = "$#{new_resource.snmp_enabled}";
+ }
EOH
end
- end
- def delete_printer_port
- port_name = new_resource.port_name || "IP_#{new_resource.ipv4_address}"
+ end
+ end
- declare_resource(:powershell_script, "Deleting printer port: #{new_resource.port_name}") do
- code <<-EOH
- $port = Get-WMIObject -class Win32_TCPIPPrinterPort -EnableAllPrivileges -Filter "name = '#{port_name}'"
- $port.Delete()
- EOH
+ action :delete, description: "Delete an existing printer port." do
+ if current_resource
+ converge_by("Delete #{new_resource.port_name}") do
+ powershell_exec!("Remove-PrinterPort -Name #{new_resource.port_name}")
end
+ else
+ Chef::Log.info "#{new_resource.port_name} doesn't exist - can't delete."
end
end
end
diff --git a/lib/chef/resource/zypper_repository.rb b/lib/chef/resource/zypper_repository.rb
index 89ed7f1aef..228329d2ea 100644
--- a/lib/chef/resource/zypper_repository.rb
+++ b/lib/chef/resource/zypper_repository.rb
@@ -24,7 +24,7 @@ class Chef
unified_mode true
provides(:zypper_repository) { true }
- provides(:zypper_repo) { true }
+ provides(:zypper_repo) { true } # legacy cookbook compatibility
description "Use the **zypper_repository** resource to create Zypper package repositories on SUSE Enterprise Linux and openSUSE systems. This resource maintains full compatibility with the **zypper_repository** resource in the existing **zypper** cookbook."
introduced "13.3"
@@ -34,11 +34,27 @@ class Chef
```ruby
zypper_repository 'apache' do
baseurl 'http://download.opensuse.org/repositories/Apache'
- path '/openSUSE_Leap_15.0'
+ path '/openSUSE_Leap_15.2'
type 'rpm-md'
priority '100'
end
```
+
+ **Remove the repo named 'apache'**:
+
+ ```ruby
+ zypper_repository 'apache' do
+ action :delete
+ end
+ ```
+
+ **Refresh the repo named 'apache'**:
+
+ ```ruby
+ zypper_repository 'apache' do
+ action :refresh
+ end
+ ```
DOC
property :repo_name, String,
@@ -66,8 +82,10 @@ class Chef
description: "Determines whether or not to perform a GPG signature check on the repository.",
default: true
- property :gpgkey, String,
- description: "The location of the repository key to be imported."
+ property :gpgkey, [String, Array],
+ description: "The location of the repository key(s) to be imported.",
+ coerce: proc { |v| Array(v) },
+ default: []
property :baseurl, String,
description: "The base URL for the Zypper repository, such as `http://download.opensuse.org`."
@@ -95,10 +113,12 @@ class Chef
default: true
property :source, String,
- description: "The name of the template for the repository file. Only necessary if you're not using the built in template."
+ description: "The name of the template for the repository file. Only necessary if you're using a custom template for the repository file."
property :cookbook, String,
- description: "The cookbook to source the repository template file from. Only necessary if you're not using the built in template.",
+ description: "The cookbook to source the repository template file from. Only necessary if you're using a custom template for the repository file.",
+ default: lazy { cookbook_name },
+ default_description: "The cookbook containing the resource",
desired_state: false
property :gpgautoimportkeys, [TrueClass, FalseClass],
diff --git a/lib/chef/resource_reporter.rb b/lib/chef/resource_reporter.rb
index 4051ac2f49..c6a7be133f 100644
--- a/lib/chef/resource_reporter.rb
+++ b/lib/chef/resource_reporter.rb
@@ -135,7 +135,6 @@ class Chef
def action_collection_registration(action_collection)
@action_collection = action_collection
- action_collection.register(self) if reporting_enabled?
end
def post_reporting_data
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index 42549e5eff..94aa23c20f 100644
--- a/lib/chef/version.rb
+++ b/lib/chef/version.rb
@@ -23,7 +23,7 @@ require_relative "version_string"
class Chef
CHEF_ROOT = File.expand_path("..", __dir__)
- VERSION = Chef::VersionString.new("17.2.12")
+ VERSION = Chef::VersionString.new("17.2.25")
end
#
diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock
index b1d660d223..32b2dd0d44 100644
--- a/omnibus/Gemfile.lock
+++ b/omnibus/Gemfile.lock
@@ -1,6 +1,6 @@
GIT
remote: https://github.com/chef/omnibus-software.git
- revision: a03d3ba3409d3a35c929d1192ead7a7215dac5b2
+ revision: 606edf8624241ad8b79200edabda4d788cb61882
branch: master
specs:
omnibus-software (4.0.0)
@@ -32,7 +32,7 @@ GEM
artifactory (3.0.15)
awesome_print (1.9.2)
aws-eventstream (1.1.1)
- aws-partitions (1.461.0)
+ aws-partitions (1.465.0)
aws-sdk-core (3.114.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
@@ -41,7 +41,7 @@ GEM
aws-sdk-kms (1.43.0)
aws-sdk-core (~> 3, >= 3.112.0)
aws-sigv4 (~> 1.1)
- aws-sdk-s3 (1.95.0)
+ aws-sdk-s3 (1.95.1)
aws-sdk-core (~> 3, >= 3.112.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
@@ -177,20 +177,24 @@ GEM
ed25519 (1.2.4)
erubi (1.10.0)
erubis (2.7.0)
- faraday (1.4.1)
+ faraday (1.4.2)
+ faraday-em_http (~> 1.0)
+ faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
+ faraday-em_http (1.0.0)
+ faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.1.0)
faraday_middleware (1.0.0)
faraday (~> 1.0)
- ffi (1.15.0)
- ffi (1.15.0-x64-mingw32)
- ffi (1.15.0-x86-mingw32)
+ ffi (1.15.1)
+ ffi (1.15.1-x64-mingw32)
+ ffi (1.15.1-x86-mingw32)
ffi-libarchive (1.0.17)
ffi (~> 1.0)
ffi-win32-extensions (1.0.4)
@@ -206,7 +210,7 @@ GEM
highline (2.0.3)
httpclient (2.8.3)
iniparse (1.5.0)
- inspec-core (4.37.17)
+ inspec-core (4.37.20)
addressable (~> 2.4)
chef-telemetry (~> 1.0, >= 1.0.8)
faraday (>= 0.9.0, < 1.5)
@@ -375,7 +379,7 @@ GEM
toml-rb (2.0.1)
citrus (~> 3.0, > 3.0)
tomlrb (1.3.0)
- train-core (3.7.0)
+ train-core (3.7.2)
addressable (~> 2.5)
ffi (!= 1.13.0)
json (>= 1.8, < 3.0)
diff --git a/spec/functional/resource/windows_pagefile_spec.rb b/spec/functional/resource/windows_pagefile_spec.rb
new file mode 100644
index 0000000000..fd44c01973
--- /dev/null
+++ b/spec/functional/resource/windows_pagefile_spec.rb
@@ -0,0 +1,98 @@
+# Author: John McCrae (john.mccrae@progress.com)
+# Copyright:: Copyright (c) Chef Software Inc.
+# License: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+require "chef/mixin/powershell_exec"
+
+describe Chef::Resource::WindowsPagefile, :windows_only do
+ include Chef::Mixin::PowershellExec
+
+ let(:c_path) { "c:\\" }
+ let(:e_path) { "e:\pagefile.sys" }
+
+ let(:run_context) do
+ node = Chef::Node.new
+ node.consume_external_attrs(OHAI_SYSTEM.data, {}) # node[:languages][:powershell][:version]
+ node.automatic["os"] = "windows"
+ node.automatic["platform"] = "windows"
+ node.automatic["platform_version"] = "6.1"
+ node.automatic["kernel"][:machine] = :x86_64 # Only 64-bit architecture is supported
+ empty_events = Chef::EventDispatch::Dispatcher.new
+ Chef::RunContext.new(node, {}, empty_events)
+ end
+
+ subject do
+ new_resource = Chef::Resource::WindowsPagefile.new("pagefile", run_context)
+ new_resource
+ end
+
+ describe "Setting Up Pagefile Management" do
+ context "Disable Automatic Management" do
+ it "Disables Automatic Management" do
+ subject.path c_path
+ subject.automatic_managed false
+ subject.run_action(:set)
+ expect(subject).to be_updated_by_last_action
+ end
+
+ it "Enable Automatic Management " do
+ subject.path c_path
+ subject.automatic_managed true
+ subject.run_action(:set)
+ expect(subject).to be_updated_by_last_action
+ end
+ end
+ end
+
+ describe "Creating a new Pagefile" do
+ context "Create new pagefile" do
+ it "Creates a new pagefile on a different drive that doesn't exist" do
+ subject.path e_path
+ expect { subject.run_action(:set) }.to raise_error(RuntimeError)
+ end
+ end
+
+ context "Update a pagefile" do
+ it "Changes a pagefile to use custom sizes" do
+ subject.path c_path
+ subject.initial_size 20000
+ subject.maximum_size 80000
+ subject.run_action(:set)
+ expect(subject).to be_updated_by_last_action
+ end
+ end
+ end
+
+ describe "Deleting a Pagefile and Resetting to Automatically Managed" do
+ context "delete the pagefile on disk" do
+ it "deletes the pagefile located at the given path" do
+ subject.path c_path
+ subject.run_action(:delete)
+ expect(subject).to be_updated_by_last_action
+ end
+ end
+
+ context "Re-enable automatic management of pagefiles" do
+ it "Enable Automatic Management " do
+ subject.path c_path
+ subject.automatic_managed true
+ subject.run_action(:set)
+ expect(subject).to be_updated_by_last_action
+ end
+ end
+ end
+end
diff --git a/spec/unit/cookbook_version_spec.rb b/spec/unit/cookbook_version_spec.rb
index 01345e32e7..4a964f74de 100644
--- a/spec/unit/cookbook_version_spec.rb
+++ b/spec/unit/cookbook_version_spec.rb
@@ -41,7 +41,59 @@ describe Chef::CookbookVersion do
it "has empty metadata" do
expect(cookbook_version.metadata).to eq(Chef::Cookbook::Metadata.new)
end
+ end
+
+ describe "#recipe_yml_filenames_by_name" do
+ let(:cookbook_version) { Chef::CookbookVersion.new("mycb", "/tmp/mycb") }
+
+ def files_for_recipe(extension)
+ [
+ { name: "recipes/default.#{extension}", full_path: "/home/user/repo/cookbooks/test/recipes/default.#{extension}" },
+ { name: "recipes/other.#{extension}", full_path: "/home/user/repo/cookbooks/test/recipes/other.#{extension}" },
+ ]
+ end
+ context "and YAML files present include both a recipes/default.yml and a recipes/default.yaml" do
+ before(:each) do
+ allow(cookbook_version).to receive(:files_for).with("recipes").and_return(
+ [
+ { name: "recipes/default.yml", full_path: "/home/user/repo/cookbooks/test/recipes/default.yml" },
+ { name: "recipes/default.yaml", full_path: "/home/user/repo/cookbooks/test/recipes/default.yaml" },
+ ]
+ )
+ end
+ it "because both are valid and we can't pick, it raises an error that contains the info needed to fix the problem" do
+ expect { cookbook_version.recipe_yml_filenames_by_name }
+ .to raise_error(Chef::Exceptions::AmbiguousYAMLFile, /.*default.yml.*default.yaml.*update the cookbook to remove/)
+ end
+ end
+
+ %w{yml yaml}.each do |extension|
+
+ context "and YAML files are present including a recipes/default.#{extension}" do
+ before(:each) do
+ allow(cookbook_version).to receive(:files_for).with("recipes").and_return(files_for_recipe(extension))
+ end
+
+ context "and manifest does not include a root_files/recipe.#{extension}" do
+ it "returns all YAML recipes with a correct default of default.#{extension}" do
+ expect(cookbook_version.recipe_yml_filenames_by_name).to eq({ "default" => "/home/user/repo/cookbooks/test/recipes/default.#{extension}",
+ "other" => "/home/user/repo/cookbooks/test/recipes/other.#{extension}" })
+ end
+ end
+
+ context "and manifest also includes a root_files/recipe.#{extension}" do
+ let(:root_files) { [{ name: "root_files/recipe.#{extension}", full_path: "/home/user/repo/cookbooks/test/recipe.#{extension}" } ] }
+ before(:each) do
+ allow(cookbook_version.cookbook_manifest).to receive(:root_files).and_return(root_files)
+ end
+ it "returns all YAML recipes with a correct default of recipe.#{extension}" do
+ expect(cookbook_version.recipe_yml_filenames_by_name).to eq({ "default" => "/home/user/repo/cookbooks/test/recipe.#{extension}",
+ "other" => "/home/user/repo/cookbooks/test/recipes/other.#{extension}" })
+ end
+ end
+ end
+ end
end
describe "with a cookbook directory named tatft" do
diff --git a/spec/unit/handler_spec.rb b/spec/unit/handler_spec.rb
index a9820e8a70..ee30113d1c 100644
--- a/spec/unit/handler_spec.rb
+++ b/spec/unit/handler_spec.rb
@@ -38,6 +38,8 @@ describe Chef::Handler do
@run_context = Chef::RunContext.new(@node, {}, @events)
@all_resources = [Chef::Resource::Cat.new("lolz"), Chef::Resource::ZenMaster.new("tzu")]
@all_resources.first.updated_by_last_action true
+ @handler.instance_variable_set(:@all_resources, @all_resources)
+ @handler.instance_variable_set(:@updated_resources, [@all_resources.first])
@run_context.resource_collection.all_resources.replace(@all_resources)
@run_status.run_context = @run_context
@start_time = Time.now
@@ -119,6 +121,8 @@ describe Chef::Handler do
@run_context = Chef::RunContext.new(@node, {}, @events)
@all_resources = [Chef::Resource::Cat.new("foo"), Chef::Resource::ZenMaster.new("moo")]
@all_resources.first.updated_by_last_action true
+ @handler.instance_variable_set(:@all_resources, @all_resources)
+ @handler.instance_variable_set(:@updated_resources, [@all_resources.first])
@run_context.resource_collection.all_resources.replace(@all_resources)
@run_status.run_context = @run_context
@start_time = Time.now
@@ -169,17 +173,19 @@ describe Chef::Handler do
# and this would test the start handler
describe "when running a start handler" do
before do
+ @handler.instance_variable_set(:@all_resources, [])
+ @handler.instance_variable_set(:@updated_resources, [])
@start_time = Time.now
allow(Time).to receive(:now).and_return(@start_time)
@run_status.start_clock
end
it "should not have all resources" do
- expect(@handler.all_resources).to be_falsey
+ expect(@handler.all_resources).to be_empty
end
it "should not have updated resources" do
- expect(@handler.updated_resources).to be_falsey
+ expect(@handler.updated_resources).to be_empty
end
it "has a shortcut for the start time" do
diff --git a/spec/unit/provider/zypper_repository_spec.rb b/spec/unit/provider/zypper_repository_spec.rb
index 950022080a..2cf4ed99c8 100644
--- a/spec/unit/provider/zypper_repository_spec.rb
+++ b/spec/unit/provider/zypper_repository_spec.rb
@@ -107,13 +107,6 @@ describe Chef::Provider::ZypperRepository do
end
end
- describe "#cookbook_name" do
- it "returns 'test' when the cookbook property is set" do
- new_resource.cookbook("test")
- expect(provider.cookbook_name).to eq("test")
- end
- end
-
describe "#key_type" do
it "returns :remote_file with an http URL" do
expect(provider.key_type("https://www.chef.io/key")).to eq(:remote_file)
@@ -167,10 +160,10 @@ describe Chef::Provider::ZypperRepository do
end
end
- describe "#install_gpg_key" do
- it "skips installing the key if a nil value for key is passed" do
+ describe "#install_gpg_keys" do
+ it "skips installing the key if an empty array for key URL is passed" do
expect(logger).to receive(:debug)
- provider.install_gpg_key(nil)
+ provider.install_gpg_keys([])
end
end
end
diff --git a/spec/unit/resource/windows_pagefile_spec.rb b/spec/unit/resource/windows_pagefile_spec.rb
index 9f12a74ca8..e11b096fc0 100644
--- a/spec/unit/resource/windows_pagefile_spec.rb
+++ b/spec/unit/resource/windows_pagefile_spec.rb
@@ -18,14 +18,14 @@
require "spec_helper"
describe Chef::Resource::WindowsPagefile do
- let(:resource) { Chef::Resource::WindowsPagefile.new("C:\\pagefile.sys") }
+ let(:resource) { Chef::Resource::WindowsPagefile.new("c:\\pagefile.sys") }
it "sets resource name as :windows_pagefile" do
expect(resource.resource_name).to eql(:windows_pagefile)
end
it "the path property is the name_property" do
- expect(resource.path).to eql("C:\\pagefile.sys")
+ expect(resource.path).to eql("c:\\pagefile.sys")
end
it "sets the default action as :set" do
@@ -38,12 +38,7 @@ describe Chef::Resource::WindowsPagefile do
end
it "coerces forward slashes in the path property to back slashes" do
- resource.path "C:/pagefile.sys"
- expect(resource.path).to eql("C:\\pagefile.sys")
+ resource.path "c:/pagefile.sys"
+ expect(resource.path).to eql("c:\\pagefile.sys")
end
-
- it "automatic_managed property defaults to false" do
- expect(resource.automatic_managed).to eql(false)
- end
-
end
diff --git a/spec/unit/resource/zypper_repository_spec.rb b/spec/unit/resource/zypper_repository_spec.rb
index b1b9cdf874..18ce0e47b3 100644
--- a/spec/unit/resource/zypper_repository_spec.rb
+++ b/spec/unit/resource/zypper_repository_spec.rb
@@ -85,7 +85,7 @@ describe Chef::Resource::ZypperRepository do
it "accepts the legacy 'key' property" do
resource.key "foo"
- expect(resource.gpgkey).to eql("foo")
+ expect(resource.gpgkey).to eql(["foo"])
end
it "accepts the legacy 'uri' property" do