summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml12
-rw-r--r--DOC_CHANGES.md133
-rw-r--r--MAINTAINERS.md53
-rw-r--r--MAINTAINERS.toml44
-rw-r--r--RELEASE_NOTES.md17
-rw-r--r--Rakefile1
-rw-r--r--VERSION2
-rw-r--r--acceptance/Gemfile5
-rw-r--r--acceptance/omnitruck/.acceptance/acceptance-cookbook/.gitignore2
-rw-r--r--acceptance/omnitruck/.acceptance/acceptance-cookbook/metadata.rb1
-rw-r--r--acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/destroy.rb1
-rw-r--r--acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/provision.rb1
-rw-r--r--acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/verify.rb61
-rw-r--r--chef-config/lib/chef-config/version.rb2
-rw-r--r--chef.gemspec2
-rw-r--r--lib/chef/application.rb15
-rw-r--r--lib/chef/application/client.rb59
-rw-r--r--lib/chef/knife/cookbook_create.rb54
-rw-r--r--lib/chef/knife/ssh.rb9
-rw-r--r--lib/chef/mixin/which.rb2
-rw-r--r--lib/chef/platform/provider_mapping.rb4
-rw-r--r--lib/chef/provider/mount.rb10
-rw-r--r--lib/chef/provider/noop.rb37
-rw-r--r--lib/chef/provider/package/homebrew.rb2
-rw-r--r--lib/chef/provider/service/redhat.rb14
-rw-r--r--lib/chef/providers.rb1
-rw-r--r--lib/chef/resource_builder.rb2
-rw-r--r--lib/chef/resource_collection.rb50
-rw-r--r--lib/chef/run_context.rb26
-rw-r--r--lib/chef/runner.rb40
-rw-r--r--lib/chef/version.rb2
-rw-r--r--lib/chef/win32/registry.rb8
-rw-r--r--omnibus/Gemfile10
-rw-r--r--spec/integration/recipes/noop_resource_spec.rb24
-rw-r--r--spec/integration/recipes/notifies_spec.rb334
-rw-r--r--spec/unit/application/client_spec.rb188
-rw-r--r--spec/unit/application_spec.rb27
-rw-r--r--spec/unit/knife/cookbook_create_spec.rb96
-rw-r--r--spec/unit/knife/ssh_spec.rb17
-rw-r--r--spec/unit/mixin/path_sanity_spec.rb2
-rw-r--r--spec/unit/mixin/xml_escape_spec.rb2
-rw-r--r--spec/unit/provider/mount/aix_spec.rb3
-rw-r--r--spec/unit/provider/mount/mount_spec.rb6
-rw-r--r--spec/unit/provider/mount/windows_spec.rb14
-rw-r--r--spec/unit/provider/mount_spec.rb19
-rw-r--r--spec/unit/provider/service/redhat_spec.rb14
-rw-r--r--spec/unit/resource_collection_spec.rb70
-rw-r--r--spec/unit/util/diff_spec.rb8
48 files changed, 1121 insertions, 385 deletions
diff --git a/.travis.yml b/.travis.yml
index 5504f4aa21..e93d6ce246 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,9 +35,12 @@ matrix:
- rvm: 2.2
sudo: true
bundler_args: --without server docgen maintenance
+ - rvm: 2.3.0
+ sudo: true
+ bundler_args: --without server docgen maintenance
- rvm: rbx
sudo: true
- bundler_args: --without server docgen maintenance ruby_prof
+ bundler_args: --without server docgen maintenance ruby_prof pry
- rvm: 2.2
env: "GEMFILE_MOD=\"gem 'chef-zero', github: 'chef/chef-zero'\""
script: bundle exec rake chef_zero_spec
@@ -146,10 +149,11 @@ matrix:
- sudo cat /var/log/squid3/access.log
allow_failures:
- - rvm: rbx
- rvm: 2.2
- env: "GEMFILE_MOD=\"gem 'halite', github: 'poise/halite'\""
- script: bundle exec rake halite_spec
+ env: "GEMFILE_MOD=\"gem 'poise', github: 'poise/poise'\""
+ script: bundle exec rake poise_spec
+ - rvm: 2.3.0
+ - rvm: rbx
notifications:
on_change: true
diff --git a/DOC_CHANGES.md b/DOC_CHANGES.md
index 79d60b856b..90b57c7e34 100644
--- a/DOC_CHANGES.md
+++ b/DOC_CHANGES.md
@@ -6,128 +6,17 @@ Example Doc Change:
Description of the required change.
-->
-### `chef_version` and `ohai_version`
+## Doc changes for Chef 12.9
-see: https://docs.chef.io/release/12-6/release_notes.html#new-metadata-rb-settings
+### New timeout option added to `knife ssh`
-The metadata.rb DSL is extended to support `chef_version` and `ohai_version` to establish ranges
-of chef and ohai versions that the cookbook supports.
+When doing a `knife ssh` call, if a connection to a host is not able
+to succeed due to host unreachable or down, the entire call can hang. In
+order to prevent this from happening, a new timeout option has been added
+to allow a connection timeout to be passed to the underlying SSH call
+(see ConnectTimeout setting in http://linux.die.net/man/5/ssh_config)
-When the running chef or ohai version does not match, then the chef-client run will abort with an
-exception immediately after cookbooks have been synchronized before any cookbook contents are
-parsed.
-
-The format of the dependencies is based on rubygems (and implemented with rubygems code). Pessimistic
-version constraints, floor and ceiling constraints, and specifying multiple constraints are all valid.
-
-Examples:
-
-```
-# matches any 12.x version, but not 11.x or 13.x
-chef_version "~> 12"
-```
-
-```
-# matches any 12.x, 13.x, etc version
-chef_version ">= 12"
-```
-
-```
-# matches any chef 12 version >= 12.5.1 or any chef 13 version
-chef_version ">= 12.5.1", "< 14.0"
-```
-
-```
-# matches chef 11 >= 11.18.4 or chef 12 >= 12.5.1 (i.e. depends on a backported bugfix)
-chef_version ">= 11.18.12", "< 12.0"
-chef_version ">= 12.5.1", "< 13.0"
-```
-
-As seen in the last example multiple constraints are OR'd.
-
-There is currently no support in supermarket for making this metadata visible in /universe to
-depsolvers, or support in Berksfile/PolicyFile for automatically pruning cookbooks that fail
-to match.
-
-### `ksh` resources
-
-Use the ksh resource to execute scripts using the Korn shell (ksh) interpreter.
-This resource may also use any of the actions and properties that are available
-to the execute resource.
-
-Example:
-```ruby
-ksh 'hello world' do
- code <<-EOH
- echo "Hello world!"
- echo "Current directory: " $cwd
- EOH
-end
-```
-
-See https://docs.chef.io/release/12-6/resource_ksh.html for more info.
-
-### `dsc_resource` resource
-
-Added reboot_action attribute to dsc_resource.
-
-If the DSC resource indicates that it requires a reboot, reboot_action can use the reboot resource to
-either reboot immediately (:reboot_now) or queue a reboot (:request_reboot). The default value of reboot_action is :nothing.
-
-The following two items in the dsc_resource doc in Chef 12.6.0 are ONLY applicable for PowerShell versions earlier than 5.0.10586.0. The latest version of WMF 5 has relaxed the limitation that prevented us from running in non-disabled RefreshMode configuration, and including both dsc_script and dsc_resource in the same run list:
-1. The RefreshMode configuration setting in the Local Configuration Manager must be set to Disabled
-2. The dsc_script resource may not be used in the same run-list with the dsc_resource. This is because the dsc_script resource requires that RefreshMode in the Local Configuration Manager be set to Push, whereas the dsc_resource resource requires it to be set to Disabled
-
-
-### `knife bootstrap --ssh-identity-file`
-
-The --identity-file option to `knife bootstrap` has been deprecated in favor of `knife bootstrap --ssh-identity-file`
-to better align with other ssh related options.
-
-### `windows_package` resource
-
-`windows_package` now supports more than just `MSI`. Most common windows installer types are supported including Inno Setup, Nullsoft, Wise and InstallShield. The new allowed `installer_type` values are: `inno`, `nsis`, `wise`, `installshield`, `custom`, and `msi`.
-
-**Non `:msi` package installation**
-When installing non `:msi` packages, the `package_name` should match the display name used for the installed package in the "Add/Remove Programs" settings application. This value can also be found in the following registry locations:
-* HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
-* HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall
-* HKEY_LOCAL_MACHINE\Software\Wow6464Node\Microsoft\Windows\CurrentVersion\Uninstall
-
- Further, non `:msi` packages must explicitly include a package `source` attribute when using the `:install` action. Unlike `:msi` packages, they will not default to the package name if missing. Without the name matching the software's display name, non `:msi` packages will always reconverge on `:install`.
-
-Also, while being able to download remote installers from a `HTTP` resource is not new, it looks as though the top of the docs page is incorrect stating that only local installers can be used as a source.
-
-Example Nullsoft (`nsis`) package resource:
-```
-package 'Mercurial 3.6.1 (64-bit)' do
- source 'http://mercurial.selenic.com/release/windows/Mercurial-3.6.1-x64.exe'
- checksum 'febd29578cb6736163d232708b834a2ddd119aa40abc536b2c313fc5e1b5831d'
-end
-```
-
-Example Custom `windows_package` resource:
-```
-package 'Microsoft Visual C++ 2005 Redistributable' do
- source 'https://download.microsoft.com/download/6/B/B/6BB661D6-A8AE-4819-B79F-236472F6070C/vcredist_x86.exe'
- installer_type :custom
- options '/Q'
-end
-```
-Using a `:custom` package is one way to install a non `.msi` file that embeds an `msi` based installer.
-
-**`windows_package` removal**
-Packages can now be removed without the need to include the package `source`. The relevent uninstall metadata will now be discovered from the registry.
-```
-package 'Mercurial 3.6.1 (64-bit)' do
- action :remove
-end
-```
-For non `:msi` packages, it is important that the package name used is EXACTLY the same as the display name found in "Add/Remove programs" or the `DisplayName` property in the appropriate registry key:
-* HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
-* HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall
-* HKEY_LOCAL_MACHINE\Software\Wow6464Node\Microsoft\Windows\CurrentVersion\Uninstall
-
-When removing `:msi` packages, this same package naming rule applies if the `source` is omitted.
-
-Note that if there are multiple versions of a package installed with the same display name, all packages will be removed unless a version is provided in the `version` attribute or can be discovered in the `source` installer file.
+The timeout setting can be passed in via a command line parameter
+(`-t` or `--ssh-timeout`) or via a knife config
+(`Chef::Config[:knife][:ssh_timeout]`). The value of the timeout is set
+in seconds.
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index 244f2ed1ad..8f47b40aef 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -44,6 +44,19 @@ To mention the team, use @chef/client-core
* [Ranjib Dey](https://github.com/ranjib)
* [Matt Wrock](https://github.com/mwrock)
+## Ohai
+
+To mention the team, use @chef/ohai
+
+### Lieutenant
+
+* [Claire McQuin](https://github.com/mcquin)
+
+### Maintainers
+
+* [Bryan McLellan](https://github.com/btm)
+* [Tim Smith](https://github.com/tas50)
+
## Dev Tools
ChefDK, Chef Zero, Knife, Chef Apply and Chef Shell.
@@ -71,6 +84,22 @@ To mention the team, use @chef/client-test-tools
* [Lamont Granquist](https://github.com/lamont-granquist)
* [Ranjib Dey](https://github.com/ranjib)
+## Chef Provisioning
+
+Chef Provisioning and Drivers. Supported Drivers are listed in the [README](https://github.com/chef/chef-provisioning/blob/master/README.md#chef-provisioning).
+
+To mention the team, use @chef/provisioning
+
+### Lieutenant
+
+* [Tyler Ball](https://github.com/tyler-ball)
+
+### Maintainers
+
+* [John Keiser](https://github.com/jkeiser)
+* [Stuart Preston](https://github.com/stuartpreston)
+* [JJ Asghar](https://github.com/jjasghar)
+
## Platform Specific Components
The specific components of Chef related to a given platform - including (but not limited to) resources, providers, and the core DSL.
@@ -161,6 +190,30 @@ To mention the team, use @chef/client-debian
* [Lamont Granquist](https://github.com/lamont-granquist)
+## Cisco NX-OS
+
+To mention the team, use @chef/client-nxos
+
+### Lieutenant
+
+* [Carl Perry](https://github.com/edolnx)
+
+### Maintainers
+
+* [Carl Perry](https://github.com/edolnx)
+
+## Cisco IOS XR
+
+To mention the team, use @chef/client-iosxr
+
+### Lieutenant
+
+* [Carl Perry](https://github.com/edolnx)
+
+### Maintainers
+
+* [Carl Perry](https://github.com/edolnx)
+
## Fedora
To mention the team, use @chef/client-fedora
diff --git a/MAINTAINERS.toml b/MAINTAINERS.toml
index 3b9507938c..a75a2f532e 100644
--- a/MAINTAINERS.toml
+++ b/MAINTAINERS.toml
@@ -51,6 +51,17 @@ another component.
"mwrock"
]
+ [Org.Components.Ohai]
+ title = "Ohai"
+ team = "ohai"
+
+ lieutenant = "mcquin"
+
+ maintainers = [
+ "btm",
+ "tas50"
+ ]
+
[Org.Components.DevTools]
title = "Dev Tools"
team = "client-dev-tools"
@@ -84,6 +95,21 @@ another component.
"ranjib"
]
+ [Org.Components.Provisioning]
+ title = "Chef Provisioning"
+ team = "provisioning"
+ text = """
+Chef Provisioning and Drivers. Supported Drivers are listed in the [README](https://github.com/chef/chef-provisioning/blob/master/README.md#chef-provisioning).
+"""
+
+ lieutenant = "tyler-ball"
+
+ maintainers = [
+ "jkeiser",
+ "stuartpreston",
+ "jjasghar"
+ ]
+
[Org.Components.Subsystems]
title = "Platform Specific Components"
text = """
@@ -360,3 +386,21 @@ The specific components of Chef related to a given platform - including (but not
[people.cperry]
Name = "Carl Perry"
GitHub = "edolnx"
+
+ [people.tas50]
+ Name = "Tim Smith"
+ GitHub = "tas50"
+
+ [people.jkeiser]
+ Name = "John Keiser"
+ GitHub = "jkeiser"
+
+ [people.stuartpreston]
+ Name = "Stuart Preston"
+ GitHub = "stuartpreston"
+
+ [people.jjasghar]
+ Name = "JJ Asghar"
+ GitHub = "jjasghar"
+ Twitter = "jjasghar"
+ IRC = "j^2"
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 6f67aa7b09..c25d6396c2 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -36,3 +36,20 @@ from Chef::Provider when mixing `use_inline_resources` into classes that only in
class. If any code has been written like this, it should be modified to correctly inherit from
Chef::Provider::LWRPBase instead (which will have the side effect of fixing it so that it correctly works
on Chef 11.0-12.5 as well).
+
+## Shorthand options for `log_location`
+
+The `log_location` setting now accepts shorthand `:syslog` and
+`:win_evt` options. `:syslog` is shorthand for `Chef::Log::Syslog.new`
+and `:win_evt` is shorthand for `Chef::Log::WinEvt.new`. All previously
+valid options are still valid, including Logger or Logger-like
+instances, e.g. `Chef::Log::Syslog.new` with other args than the
+defaults.
+
+## chef-client `--daemonize` option now takes an optional integer argument
+
+Optional integer argument (.e.g `chef-client --daemonize 5`) is the
+number of seconds to wait before the first daemonized run. See
+[#3305] for background.
+
+[#3305]: https://github.com/chef/chef/issues/3305
diff --git a/Rakefile b/Rakefile
index 99fba03ff8..772b2bca18 100644
--- a/Rakefile
+++ b/Rakefile
@@ -20,6 +20,7 @@
VERSION = IO.read(File.expand_path("../VERSION", __FILE__)).strip
require "rubygems"
+require "chef/version"
require "chef-config/package_task"
require "rdoc/task"
require_relative "tasks/rspec"
diff --git a/VERSION b/VERSION
index ef69408323..cf3915e04d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-12.8.6 \ No newline at end of file
+12.9.29 \ No newline at end of file
diff --git a/acceptance/Gemfile b/acceptance/Gemfile
index 4573bc5fb3..72dded468c 100644
--- a/acceptance/Gemfile
+++ b/acceptance/Gemfile
@@ -1,8 +1,7 @@
source "https://rubygems.org"
-gem "mixlib-install", github: "chef/mixlib-install"
gem "chef-acceptance", github: "chef/chef-acceptance"
-gem "test-kitchen", github: "sersut/test-kitchen", branch: "sersut/mixlib-install-update"
+gem "test-kitchen"
gem "kitchen-ec2", github: "test-kitchen/kitchen-ec2", branch: "jk/image-search-only"
gem "kitchen-inspec"
gem "inspec"
@@ -10,5 +9,5 @@ gem "inspec"
# puts in a box_url for bento when a vagrant box in atlas is specified
gem "kitchen-vagrant", github: "test-kitchen/kitchen-vagrant"
gem "windows_chef_zero"
-gem "winrm-transport"
+gem "winrm-fs"
gem "berkshelf"
diff --git a/acceptance/omnitruck/.acceptance/acceptance-cookbook/.gitignore b/acceptance/omnitruck/.acceptance/acceptance-cookbook/.gitignore
new file mode 100644
index 0000000000..041413b040
--- /dev/null
+++ b/acceptance/omnitruck/.acceptance/acceptance-cookbook/.gitignore
@@ -0,0 +1,2 @@
+nodes/
+tmp/
diff --git a/acceptance/omnitruck/.acceptance/acceptance-cookbook/metadata.rb b/acceptance/omnitruck/.acceptance/acceptance-cookbook/metadata.rb
new file mode 100644
index 0000000000..4c7c42d9bd
--- /dev/null
+++ b/acceptance/omnitruck/.acceptance/acceptance-cookbook/metadata.rb
@@ -0,0 +1 @@
+name 'acceptance-cookbook'
diff --git a/acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/destroy.rb b/acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/destroy.rb
new file mode 100644
index 0000000000..f890b597fe
--- /dev/null
+++ b/acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/destroy.rb
@@ -0,0 +1 @@
+log "NOOP 'destroy' recipe from the acceptance-cookbook in directory '#{node['chef-acceptance']['suite-dir']}'"
diff --git a/acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/provision.rb b/acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/provision.rb
new file mode 100644
index 0000000000..64ef7581ac
--- /dev/null
+++ b/acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/provision.rb
@@ -0,0 +1 @@
+log "NOOP 'provision' recipe from the acceptance-cookbook in directory '#{node['chef-acceptance']['suite-dir']}'"
diff --git a/acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/verify.rb b/acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/verify.rb
new file mode 100644
index 0000000000..7db51450e1
--- /dev/null
+++ b/acceptance/omnitruck/.acceptance/acceptance-cookbook/recipes/verify.rb
@@ -0,0 +1,61 @@
+control_group "omnitruck" do
+ require 'chef/http'
+ require 'chef/json_compat'
+
+ # We do this to be able to reference 'rest' both inside and outside example
+ # blocks
+ rest = Chef::HTTP.new("https://omnitruck.chef.io/chef/metadata", headers: {"Accept" => "application/json"})
+ let(:rest) { rest }
+
+ def request(url)
+ Chef::JSONCompat.parse(rest.get(url))["sha256"]
+ end
+
+ shared_examples "32 matches 64" do |version|
+ it "only returns 32-bit packages" do
+ sha32 = request("?p=windows&pv=2012r2&v=#{version}&m=i386")
+ sha64 = request("?p=windows&pv=2012r2&v=#{version}&m=x86_64")
+ expect(sha32).to eq(sha64)
+ end
+ end
+
+ context "from the current channel" do
+ it "returns both 32-bit and 64-bit packages" do
+ # We cannot verify from the returned URL if the package is 64 or 32 bit because
+ # it is often lying, so we just make sure they are different.
+ # The current channel is often cleaned so only the latest builds are in
+ # it, so we just request the latest version instead of trying to check
+ # old versions
+ sha32 = request("?p=windows&pv=2012r2&m=i386&prerelease=true")
+ sha64 = request("?p=windows&pv=2012r2&m=x86_64&prerelease=true")
+ expect(sha32).to_not eq(sha64)
+ end
+ end
+
+ context "from the stable channel" do
+ %w{11 12.3 12.4.2 12.6.0 12.8.1}.each do |version|
+ describe "with version #{version}" do
+ include_examples "32 matches 64", version
+ end
+ end
+
+ begin
+ rest.get("?p=windows&pv=2012r2&v=12.9")
+ describe "with version 12.9" do
+ it "returns both 32-bit and 64-bit packages" do
+ sha32 = request("?p=windows&pv=2012r2&v=12.9&m=i386")
+ sha64 = request("?p=windows&pv=2012r2&v=12.9&m=x86_64")
+ expect(sha32).to_not eq(sha64)
+ end
+ end
+ rescue Net::HTTPServerException => e
+ # Once 12.9 is released this will stop 404ing and the example
+ # will be executed
+ unless e.response.code == "404"
+ raise
+ end
+ end
+
+ end
+
+end
diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb
index a00d9e8e05..2118595ea0 100644
--- a/chef-config/lib/chef-config/version.rb
+++ b/chef-config/lib/chef-config/version.rb
@@ -21,7 +21,7 @@
module ChefConfig
CHEFCONFIG_ROOT = File.expand_path("../..", __FILE__)
- VERSION = "12.8.6"
+ VERSION = "12.9.29"
end
#
diff --git a/chef.gemspec b/chef.gemspec
index 8d19051dbd..e1055e01b5 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
s.email = "adam@chef.io"
s.homepage = "http://www.chef.io"
- s.required_ruby_version = ">= 2.0.0"
+ s.required_ruby_version = ">= 2.1.0"
s.add_dependency "chef-config", "= #{Chef::VERSION}"
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index cd3e7f8c24..7dbffd8dec 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -141,6 +141,7 @@ class Chef
# that a user has configured a log_location in client.rb, but is running
# chef-client by hand to troubleshoot a problem.
def configure_logging
+ configure_log_location
Chef::Log.init(MonoLogger.new(Chef::Config[:log_location]))
if want_additional_logger?
configure_stdout_logger
@@ -151,6 +152,20 @@ class Chef
Chef::Application.fatal!("Aborting due to invalid 'log_location' configuration", 2)
end
+ # Turn `log_location :syslog` and `log_location :win_evt` into the
+ # appropriate loggers.
+ def configure_log_location
+ log_location = Chef::Config[:log_location]
+ return unless log_location.respond_to?(:to_sym)
+
+ Chef::Config[:log_location] =
+ case log_location.to_sym
+ when :syslog then Chef::Log::Syslog.new
+ when :win_evt then Chef::Log::WinEvt.new
+ else log_location # Probably a path; let MonoLogger sort it out
+ end
+ end
+
def configure_stdout_logger
stdout_logger = MonoLogger.new(STDOUT)
stdout_logger.formatter = Chef::Log.logger.formatter
diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb
index 500aa8ac59..ac46e533dd 100644
--- a/lib/chef/application/client.rb
+++ b/lib/chef/application/client.rb
@@ -105,10 +105,12 @@ class Chef::Application::Client < Chef::Application
unless Chef::Platform.windows?
option :daemonize,
- :short => "-d",
- :long => "--daemonize",
- :description => "Daemonize the process",
- :proc => lambda { |p| true }
+ :short => "-d [WAIT]",
+ :long => "--daemonize [WAIT]",
+ :description =>
+ "Daemonize the process. Accepts an optional integer which is the " \
+ "number of seconds to wait before the first daemonized run.",
+ :proc => lambda { |wait| wait =~ /^\d+$/ ? wait.to_i : true }
end
option :pid_file,
@@ -430,33 +432,38 @@ class Chef::Application::Client < Chef::Application
def interval_run_chef_client
if Chef::Config[:daemonize]
Chef::Daemon.daemonize("chef-client")
+
+ # Start first daemonized run after configured number of seconds
+ if Chef::Config[:daemonize].is_a?(Integer)
+ sleep_then_run_chef_client(Chef::Config[:daemonize])
+ end
end
loop do
- begin
- @signal = test_signal
- if @signal != IMMEDIATE_RUN_SIGNAL
- sleep_sec = time_to_sleep
- Chef::Log.debug("Sleeping for #{sleep_sec} seconds")
- interval_sleep(sleep_sec)
- end
-
- @signal = nil
- run_chef_client(Chef::Config[:specific_recipes])
+ sleep_then_run_chef_client(time_to_sleep)
+ Chef::Application.exit!("Exiting", 0) if !Chef::Config[:interval]
+ end
+ end
- Chef::Application.exit!("Exiting", 0) if !Chef::Config[:interval]
- rescue SystemExit => e
- raise
- rescue Exception => e
- if Chef::Config[:interval]
- Chef::Log.error("#{e.class}: #{e}")
- Chef::Log.debug("#{e.class}: #{e}\n#{e.backtrace.join("\n")}")
- retry
- else
- Chef::Application.fatal!("#{e.class}: #{e.message}", 1)
- end
- end
+ def sleep_then_run_chef_client(sleep_sec)
+ @signal = test_signal
+ unless @signal == IMMEDIATE_RUN_SIGNAL
+ Chef::Log.debug("Sleeping for #{sleep_sec} seconds")
+ interval_sleep(sleep_sec)
+ end
+ @signal = nil
+
+ run_chef_client(Chef::Config[:specific_recipes])
+ rescue SystemExit => e
+ raise
+ rescue Exception => e
+ if Chef::Config[:interval]
+ Chef::Log.error("#{e.class}: #{e}")
+ Chef::Log.debug("#{e.class}: #{e}\n#{e.backtrace.join("\n")}")
+ retry
end
+
+ Chef::Application.fatal!("#{e.class}: #{e.message}", 1)
end
def test_signal
diff --git a/lib/chef/knife/cookbook_create.rb b/lib/chef/knife/cookbook_create.rb
index 1e19535fbf..950de380f8 100644
--- a/lib/chef/knife/cookbook_create.rb
+++ b/lib/chef/knife/cookbook_create.rb
@@ -185,13 +185,11 @@ EOH
unless File.exists?(File.join(dir, cookbook_name, "CHANGELOG.md"))
open(File.join(dir, cookbook_name, "CHANGELOG.md"), "w") do |file|
file.puts <<-EOH
-#{cookbook_name} CHANGELOG
-#{'=' * "#{cookbook_name} CHANGELOG".length}
+# #{cookbook_name} CHANGELOG
This file is used to list changes made in each version of the #{cookbook_name} cookbook.
-0.1.0
------
+## 0.1.0
- [your_name] - Initial release of #{cookbook_name}
- - -
@@ -205,7 +203,7 @@ EOH
def create_readme(dir, cookbook_name, readme_format)
msg("** Creating README for cookbook: #{cookbook_name}")
- unless File.exists?(File.join(dir, cookbook_name, "README.#{readme_format}"))
+ unless File.exist?(File.join(dir, cookbook_name, "README.#{readme_format}"))
open(File.join(dir, cookbook_name, "README.#{readme_format}"), "w") do |file|
case readme_format
when "rdoc"
@@ -273,27 +271,37 @@ Authors: TODO: List authors
EOH
when "md", "mkd", "txt"
file.puts <<-EOH
-#{cookbook_name} Cookbook
-#{'=' * "#{cookbook_name} Cookbook".length}
+# #{cookbook_name} Cookbook
+
TODO: Enter the cookbook description here.
e.g.
This cookbook makes your favorite breakfast sandwich.
-Requirements
-------------
+## Requirements
+
TODO: List your cookbook requirements. Be sure to include any requirements this cookbook has on platforms, libraries, other cookbooks, packages, operating systems, etc.
e.g.
-#### packages
+### Platforms
+
+- SandwichOS
+
+### Chef
+
+- Chef 12.0 or later
+
+### Cookbooks
+
- `toaster` - #{cookbook_name} needs toaster to brown your bagel.
-Attributes
-----------
+## Attributes
+
TODO: List your cookbook attributes here.
e.g.
-#### #{cookbook_name}::default
+### #{cookbook_name}::default
+
<table>
<tr>
<th>Key</th>
@@ -309,9 +317,10 @@ e.g.
</tr>
</table>
-Usage
------
-#### #{cookbook_name}::default
+## Usage
+
+### #{cookbook_name}::default
+
TODO: Write usage instructions for each cookbook.
e.g.
@@ -326,8 +335,8 @@ Just include `#{cookbook_name}` in your node's `run_list`:
}
```
-Contributing
-------------
+## Contributing
+
TODO: (optional) If this is a public cookbook, detail the process for contributing. If this is a private cookbook, remove this section.
e.g.
@@ -338,9 +347,10 @@ e.g.
5. Run the tests, ensuring they all pass
6. Submit a Pull Request using Github
-License and Authors
--------------------
+## License and Authors
+
Authors: TODO: List authors
+
EOH
else
file.puts <<-EOH
@@ -415,9 +425,9 @@ EOH
"All rights reserved"
end
- unless File.exists?(File.join(dir, cookbook_name, "metadata.rb"))
+ unless File.exist?(File.join(dir, cookbook_name, "metadata.rb"))
open(File.join(dir, cookbook_name, "metadata.rb"), "w") do |file|
- if File.exists?(File.join(dir, cookbook_name, "README.#{readme_format}"))
+ if File.exist?(File.join(dir, cookbook_name, "README.#{readme_format}"))
long_description = "long_description IO.read(File.join(File.dirname(__FILE__), 'README.#{readme_format}'))"
end
file.puts <<-EOH
diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb
index 4ccc300036..31356b6f48 100644
--- a/lib/chef/knife/ssh.rb
+++ b/lib/chef/knife/ssh.rb
@@ -80,6 +80,12 @@ class Chef
:description => "The ssh port",
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key.strip }
+ option :ssh_timeout,
+ :short => "-t SECONDS",
+ :long => "--ssh-timeout SECONDS",
+ :description => "The ssh connection timeout",
+ :proc => Proc.new { |key| Chef::Config[:knife][:ssh_timeout] = key.strip.to_i }
+
option :ssh_gateway,
:short => "-G GATEWAY",
:long => "--ssh-gateway GATEWAY",
@@ -258,6 +264,9 @@ class Chef
# Handle port overrides for the main connection.
session_opts[:port] = Chef::Config[:knife][:ssh_port] if Chef::Config[:knife][:ssh_port]
session_opts[:port] = config[:ssh_port] if config[:ssh_port]
+ # Handle connection timeout
+ session_opts[:timeout] = Chef::Config[:knife][:ssh_timeout] if Chef::Config[:knife][:ssh_timeout]
+ session_opts[:timeout] = config[:ssh_timeout] if config[:ssh_timeout]
# Create the hostspec.
hostspec = session_opts[:user] ? "#{session_opts.delete(:user)}@#{host}" : host
# Connect a new session on the multi.
diff --git a/lib/chef/mixin/which.rb b/lib/chef/mixin/which.rb
index de446d93cf..63c84883d5 100644
--- a/lib/chef/mixin/which.rb
+++ b/lib/chef/mixin/which.rb
@@ -1,5 +1,5 @@
#--
-# Author:: Lamont Granquist <lamont@getchef.io>
+# Author:: Lamont Granquist <lamont@chef.io>
# Copyright:: Copyright 2010-2016, Chef Software Inc.
# License:: Apache License, Version 2.0
#
diff --git a/lib/chef/platform/provider_mapping.rb b/lib/chef/platform/provider_mapping.rb
index 3e90797802..40474242f0 100644
--- a/lib/chef/platform/provider_mapping.rb
+++ b/lib/chef/platform/provider_mapping.rb
@@ -200,10 +200,10 @@ class Chef
class_name = resource_type.class.name ? resource_type.class.name.split("::").last :
convert_to_class_name(resource_type.resource_name.to_s)
- if Chef::Provider.const_defined?(class_name)
+ if Chef::Provider.const_defined?(class_name, false)
Chef::Log.warn("Class Chef::Provider::#{class_name} does not declare 'provides #{convert_to_snake_case(class_name).to_sym.inspect}'.")
Chef::Log.warn("This will no longer work in Chef 13: you must use 'provides' to use the resource's DSL.")
- return Chef::Provider.const_get(class_name)
+ return Chef::Provider.const_get(class_name, false)
end
end
nil
diff --git a/lib/chef/provider/mount.rb b/lib/chef/provider/mount.rb
index cc4a548ac1..9e9ee29bde 100644
--- a/lib/chef/provider/mount.rb
+++ b/lib/chef/provider/mount.rb
@@ -42,17 +42,13 @@ class Chef
end
def action_mount
- if current_resource.mounted
- if mount_options_unchanged?
- Chef::Log.debug("#{new_resource} is already mounted")
- else
- action_remount
- end
- else
+ unless current_resource.mounted
converge_by("mount #{current_resource.device} to #{current_resource.mount_point}") do
mount_fs
Chef::Log.info("#{new_resource} mounted")
end
+ else
+ Chef::Log.debug("#{new_resource} is already mounted")
end
end
diff --git a/lib/chef/provider/noop.rb b/lib/chef/provider/noop.rb
new file mode 100644
index 0000000000..207bf7dedb
--- /dev/null
+++ b/lib/chef/provider/noop.rb
@@ -0,0 +1,37 @@
+#
+# Author:: Thom May (<thom@chef.io>)
+# Copyright:: Copyright (c) 2016 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.
+#
+
+class Chef
+ class Provider
+ class Noop < Chef::Provider
+ def load_current_resource; end
+
+ def respond_to_missing?(method_sym, include_private = false)
+ method_sym.to_s.start_with?("action_") || super
+ end
+
+ def method_missing(method_sym, *arguments, &block)
+ if method_sym.to_s =~ /^action_/
+ Chef::Log.debug("NoOp-ing for #{method_sym}")
+ else
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider/package/homebrew.rb b/lib/chef/provider/package/homebrew.rb
index 853a354b28..a105f6d7d0 100644
--- a/lib/chef/provider/package/homebrew.rb
+++ b/lib/chef/provider/package/homebrew.rb
@@ -127,7 +127,7 @@ class Chef
Chef::Log.debug "Executing '#{command}' as user '#{homebrew_user.name}'"
# FIXME: this 1800 second default timeout should be deprecated
- output = shell_out_with_timeout!(command, :timeout => 1800, :user => homebrew_uid, :environment => { "HOME" => homebrew_user.dir, "RUBYOPT" => nil })
+ output = shell_out_with_timeout!(command, :timeout => 1800, :user => homebrew_uid, :environment => { "HOME" => homebrew_user.dir, "RUBYOPT" => nil, "TMPDIR" => nil })
output.stdout.chomp
end
diff --git a/lib/chef/provider/service/redhat.rb b/lib/chef/provider/service/redhat.rb
index 08f8e108d5..200a2d3400 100644
--- a/lib/chef/provider/service/redhat.rb
+++ b/lib/chef/provider/service/redhat.rb
@@ -57,15 +57,21 @@ class Chef
requirements.assert(:all_actions) do |a|
chkconfig_file = "/sbin/chkconfig"
a.assertion { ::File.exists? chkconfig_file }
- a.failure_message Chef::Exceptions::Service, "#{chkconfig_file} dbleoes not exist!"
+ a.failure_message Chef::Exceptions::Service, "#{chkconfig_file} does not exist!"
end
- requirements.assert(:start, :enable, :reload, :restart) do |a|
+ requirements.assert(:enable) do |a|
+ a.assertion { !@service_missing }
+ a.failure_message Chef::Exceptions::Service, "#{new_resource}: Service is not known to chkconfig."
+ a.whyrun "Assuming service would be enabled. The init script is not presently installed."
+ end
+
+ requirements.assert(:start, :reload, :restart) do |a|
a.assertion do
- custom_command_for_action?(action) || !@service_missing
+ new_resource.init_command || custom_command_for_action?(action) || !@service_missing
end
a.failure_message Chef::Exceptions::Service, "#{new_resource}: No custom command for #{action} specified and unable to locate the init.d script!"
- a.whyrun "Assuming service would be disabled. The init script is not presently installed."
+ a.whyrun "Assuming service would be enabled. The init script is not presently installed."
end
end
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index e5635daed3..f1c836614d 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -41,6 +41,7 @@ require "chef/provider/log"
require "chef/provider/ohai"
require "chef/provider/mdadm"
require "chef/provider/mount"
+require "chef/provider/noop"
require "chef/provider/package"
require "chef/provider/powershell_script"
require "chef/provider/osx_profile"
diff --git a/lib/chef/resource_builder.rb b/lib/chef/resource_builder.rb
index f3ca2e95ad..138e401d5c 100644
--- a/lib/chef/resource_builder.rb
+++ b/lib/chef/resource_builder.rb
@@ -137,7 +137,7 @@ class Chef
@prior_resource ||=
begin
key = "#{type}[#{name}]"
- run_context.resource_collection.lookup(key)
+ run_context.resource_collection.lookup_local(key)
rescue Chef::Exceptions::ResourceNotFound
nil
end
diff --git a/lib/chef/resource_collection.rb b/lib/chef/resource_collection.rb
index 6c5b4289d8..1429c25d7f 100644
--- a/lib/chef/resource_collection.rb
+++ b/lib/chef/resource_collection.rb
@@ -33,9 +33,12 @@ class Chef
extend Forwardable
attr_reader :resource_set, :resource_list
- private :resource_set, :resource_list
+ attr_accessor :run_context
- def initialize
+ protected :resource_set, :resource_list
+
+ def initialize(run_context = nil)
+ @run_context = run_context
@resource_set = ResourceSet.new
@resource_list = ResourceList.new
end
@@ -79,11 +82,50 @@ class Chef
resource_list_methods = Enumerable.instance_methods +
[:iterator, :all_resources, :[], :each, :execute_each_resource, :each_index, :empty?] -
- [:find] # find needs to run on the set
- resource_set_methods = [:lookup, :find, :resources, :keys, :validate_lookup_spec!]
+ [:find] # find overridden below
+ resource_set_methods = [:resources, :keys, :validate_lookup_spec!]
def_delegators :resource_list, *resource_list_methods
def_delegators :resource_set, *resource_set_methods
+ def lookup_local(key)
+ resource_set.lookup(key)
+ end
+
+ def find_local(*args)
+ resource_set.find(*args)
+ end
+
+ def lookup(key)
+ if run_context.nil?
+ lookup_local(key)
+ else
+ lookup_recursive(run_context, key)
+ end
+ end
+
+ def find(*args)
+ if run_context.nil?
+ find_local(*args)
+ else
+ find_recursive(run_context, *args)
+ end
+ end
+
+ private
+
+ def lookup_recursive(rc, key)
+ rc.resource_collection.resource_set.lookup(key)
+ rescue Chef::Exceptions::ResourceNotFound
+ raise if rc.parent_run_context.nil?
+ lookup_recursive(rc.parent_run_context, key)
+ end
+
+ def find_recursive(rc, *args)
+ rc.resource_collection.resource_set.find(*args)
+ rescue Chef::Exceptions::ResourceNotFound
+ raise if rc.parent_run_context.nil?
+ find_recursive(rc.parent_run_context, *args)
+ end
end
end
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb
index cb3338d3de..29c936a932 100644
--- a/lib/chef/run_context.rb
+++ b/lib/chef/run_context.rb
@@ -130,6 +130,14 @@ class Chef
#
attr_reader :delayed_notification_collection
+ #
+ # An Array containing the delayed (end of run) notifications triggered by
+ # resources during the converge phase of the chef run.
+ #
+ # @return [Array[Chef::Resource::Notification]] An array of notification objects
+ #
+ attr_reader :delayed_actions
+
# Creates a new Chef::RunContext object and populates its fields. This object gets
# used by the Chef Server to generate a fully compiled recipe list for a node.
#
@@ -152,6 +160,7 @@ class Chef
@loaded_attributes_hash = {}
@reboot_info = {}
@cookbook_compiler = nil
+ @delayed_actions = []
initialize_child_state
end
@@ -172,10 +181,11 @@ class Chef
#
def initialize_child_state
@audits = {}
- @resource_collection = Chef::ResourceCollection.new
+ @resource_collection = Chef::ResourceCollection.new(self)
@before_notification_collection = Hash.new { |h, k| h[k] = [] }
@immediate_notification_collection = Hash.new { |h, k| h[k] = [] }
@delayed_notification_collection = Hash.new { |h, k| h[k] = [] }
+ @delayed_actions = []
end
#
@@ -221,6 +231,18 @@ class Chef
end
#
+ # Adds a delayed action to the +delayed_actions+.
+ #
+ def add_delayed_action(notification)
+ if delayed_actions.any? { |existing_notification| existing_notification.duplicates?(notification) }
+ Chef::Log.info( "#{notification.notifying_resource} not queuing delayed action #{notification.action} on #{notification.resource}"\
+ " (delayed), as it's already been queued")
+ else
+ delayed_actions << notification
+ end
+ end
+
+ #
# Get the list of before notifications sent by the given resource.
#
# TODO seriously, this is actually wrong. resource.name is not unique,
@@ -640,6 +662,8 @@ ERROR_MESSAGE
audits
audits=
create_child
+ add_delayed_action
+ delayed_actions
delayed_notification_collection
delayed_notification_collection=
delayed_notifications
diff --git a/lib/chef/runner.rb b/lib/chef/runner.rb
index ce128203f2..cd5615bcec 100644
--- a/lib/chef/runner.rb
+++ b/lib/chef/runner.rb
@@ -30,13 +30,14 @@ class Chef
attr_reader :run_context
- attr_reader :delayed_actions
-
include Chef::Mixin::ParamsValidate
def initialize(run_context)
- @run_context = run_context
- @delayed_actions = []
+ @run_context = run_context
+ end
+
+ def delayed_actions
+ @run_context.delayed_actions
end
def events
@@ -48,16 +49,11 @@ class Chef
def run_action(resource, action, notification_type = nil, notifying_resource = nil)
# If there are any before notifications, why-run the resource
# and notify anyone who needs notifying
- # TODO cheffish has a bug where it passes itself instead of the run_context to us, so doesn't have before_notifications. Fix there, update dependency requirement, and remove this if statement.
- before_notifications = run_context.before_notifications(resource) if run_context.respond_to?(:before_notifications)
- if before_notifications && !before_notifications.empty?
- whyrun_before = Chef::Config[:why_run]
- begin
- Chef::Config[:why_run] = true
+ before_notifications = run_context.before_notifications(resource) || []
+ unless before_notifications.empty?
+ forced_why_run do
Chef::Log.info("#{resource} running why-run #{action} action to support before action")
resource.run_action(action, notification_type, notifying_resource)
- ensure
- Chef::Config[:why_run] = whyrun_before
end
if resource.updated_by_last_action?
@@ -65,8 +61,8 @@ class Chef
Chef::Log.info("#{resource} sending #{notification.action} action to #{notification.resource} (before)")
run_action(notification.resource, notification.action, :before, resource)
end
+ resource.updated_by_last_action(false)
end
-
end
# Actually run the action for realsies
@@ -82,12 +78,8 @@ class Chef
end
run_context.delayed_notifications(resource).each do |notification|
- if delayed_actions.any? { |existing_notification| existing_notification.duplicates?(notification) }
- Chef::Log.info( "#{resource} not queuing delayed action #{notification.action} on #{notification.resource}"\
- " (delayed), as it's already been queued")
- else
- delayed_actions << notification
- end
+ # send the notification to the run_context of the receiving resource
+ notification.resource.run_context.add_delayed_action(notification)
end
end
end
@@ -137,5 +129,15 @@ class Chef
rescue Exception => e
e
end
+
+ # helper to run a block of code with why_run forced to true and then restore it correctly
+ def forced_why_run
+ saved = Chef::Config[:why_run]
+ Chef::Config[:why_run] = true
+ yield
+ ensure
+ Chef::Config[:why_run] = saved
+ end
+
end
end
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index be629e58e4..e81011764c 100644
--- a/lib/chef/version.rb
+++ b/lib/chef/version.rb
@@ -21,7 +21,7 @@
class Chef
CHEF_ROOT = File.expand_path("../..", __FILE__)
- VERSION = "12.8.6"
+ VERSION = "12.9.29"
end
#
diff --git a/lib/chef/win32/registry.rb b/lib/chef/win32/registry.rb
index bccd2e3c72..613994295c 100644
--- a/lib/chef/win32/registry.rb
+++ b/lib/chef/win32/registry.rb
@@ -61,7 +61,9 @@ class Chef
end
def set_value(key_path, value)
- Chef::Log.debug("Updating value #{value[:name]} in registry key #{key_path} with type #{value[:type]} and data #{value[:data]}")
+ data = value[:data]
+ data = data.to_s if value[:type] == :string
+ Chef::Log.debug("Updating value #{value[:name]} in registry key #{key_path} with type #{value[:type]} and data #{data}")
key_exists!(key_path)
hive, key = get_hive_and_key(key_path)
if value_exists?(key_path, value)
@@ -70,13 +72,13 @@ class Chef
return false
else
hive.open(key, ::Win32::Registry::KEY_SET_VALUE | ::Win32::Registry::KEY_QUERY_VALUE | registry_system_architecture) do |reg|
- reg.write(value[:name], get_type_from_name(value[:type]), value[:data])
+ reg.write(value[:name], get_type_from_name(value[:type]), data)
end
Chef::Log.debug("Value #{value[:name]} in registry key #{key_path} updated")
end
else
hive.open(key, ::Win32::Registry::KEY_SET_VALUE | ::Win32::Registry::KEY_QUERY_VALUE | registry_system_architecture) do |reg|
- reg.write(value[:name], get_type_from_name(value[:type]), value[:data])
+ reg.write(value[:name], get_type_from_name(value[:type]), data)
end
Chef::Log.debug("Value #{value[:name]} in registry key #{key_path} created")
end
diff --git a/omnibus/Gemfile b/omnibus/Gemfile
index 07d1e0c9f3..295fb2f490 100644
--- a/omnibus/Gemfile
+++ b/omnibus/Gemfile
@@ -7,6 +7,12 @@ gem "omnibus-software", git: "https://github.com/chef/omnibus-software.git"
# bundler very unhappy. Remove this when upstream has merged zed-0xff/pedump#6 .
gem "pedump", git: "https://github.com/ksubrama/pedump.git", branch: "patch-1"
+# `json_pure` has a bug in it that is failing Chef builds. We include the
+# json gem into the Gemfile so that running `bundle exec` will have
+# this gem on the load path, and cause `require 'json/ext'` to succeed. This
+# prevents loading the `json_pure` gem
+gem "json", ">= 1.8.1"
+
# This development group is installed by default when you run `bundle install`,
# but if you are using Omnibus in a CI-based infrastructure, you do not need
# the Test Kitchen-based build lab. You can skip these unnecessary dependencies
@@ -16,9 +22,9 @@ group :development do
gem "berkshelf", "~> 3.0"
# Use Test Kitchen with Vagrant for converging the build environment
- gem "test-kitchen", "~> 1.5.0"
+ gem "test-kitchen", "~> 1.7.1"
gem "kitchen-vagrant", "~> 0.19.0"
- gem "winrm-transport", "~> 1.0"
+ gem "winrm-fs", "~> 0.4.0"
gem "pry"
gem "pry-byebug"
gem "pry-stack_explorer"
diff --git a/spec/integration/recipes/noop_resource_spec.rb b/spec/integration/recipes/noop_resource_spec.rb
new file mode 100644
index 0000000000..c8ff3e6b5e
--- /dev/null
+++ b/spec/integration/recipes/noop_resource_spec.rb
@@ -0,0 +1,24 @@
+require "support/shared/integration/integration_helper"
+
+describe "Resources with a no-op provider" do
+ include IntegrationSupport
+
+ context "with noop provider providing foo" do
+ before(:context) {
+ class NoOpFoo < Chef::Resource
+ resource_name "hi_there"
+ default_action :update
+ end
+ Chef::Provider::Noop.provides :hi_there
+ }
+
+ it "does not blow up a run with a noop'd resource" do
+ recipe = converge {
+ hi_there "blah" do
+ action :update
+ end
+ }
+ expect(recipe.logged_warnings).to eq ""
+ end
+ end
+end
diff --git a/spec/integration/recipes/notifies_spec.rb b/spec/integration/recipes/notifies_spec.rb
new file mode 100644
index 0000000000..000f5e37bf
--- /dev/null
+++ b/spec/integration/recipes/notifies_spec.rb
@@ -0,0 +1,334 @@
+require "support/shared/integration/integration_helper"
+require "chef/mixin/shell_out"
+
+describe "notifications" do
+ include IntegrationSupport
+ include Chef::Mixin::ShellOut
+
+ let(:chef_dir) { File.expand_path("../../../../bin", __FILE__) }
+ let(:chef_client) { "ruby '#{chef_dir}/chef-client' --minimal-ohai" }
+
+ when_the_repository "notifies delayed one" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/notifying_test.rb", <<EOM
+default_action :run
+provides :notifying_test
+resource_name :notifying_test
+
+action :run do
+ log "bar" do
+ notifies :write, 'log[foo]', :delayed
+ end
+end
+EOM
+
+ file "recipes/default.rb", <<EOM
+log "foo" do
+ action :nothing
+end
+notifying_test "whatever"
+log "baz"
+EOM
+
+ end
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+log_level :warn
+EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ # our delayed notification should run at the end of the parent run_context after the baz resource
+ expect(result.stdout).to match(/\* log\[bar\] action write\s+\* log\[baz\] action write\s+\* log\[foo\] action write/)
+ result.error!
+ end
+ end
+
+ when_the_repository "notifies delayed two" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/notifying_test.rb", <<EOM
+default_action :run
+provides :notifying_test
+resource_name :notifying_test
+
+action :run do
+ log "bar" do
+ notifies :write, 'log[foo]', :delayed
+ end
+end
+EOM
+
+ file "recipes/default.rb", <<EOM
+log "foo" do
+ action :nothing
+end
+notifying_test "whatever"
+log "baz" do
+ notifies :write, 'log[foo]', :delayed
+end
+EOM
+
+ end
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+log_level :warn
+EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ # our delayed notification should run at the end of the parent run_context after the baz resource
+ expect(result.stdout).to match(/\* log\[bar\] action write\s+\* log\[baz\] action write\s+\* log\[foo\] action write/)
+ # and only run once
+ expect(result.stdout).not_to match(/\* log\[foo\] action write.*\* log\[foo\] action write/)
+ result.error!
+ end
+ end
+
+ when_the_repository "notifies delayed three" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/notifying_test.rb", <<EOM
+default_action :run
+provides :notifying_test
+resource_name :notifying_test
+
+action :run do
+ log "bar" do
+ notifies :write, 'log[foo]', :delayed
+ end
+end
+EOM
+
+ file "recipes/default.rb", <<EOM
+log "foo" do
+ action :nothing
+end
+log "quux" do
+ notifies :write, 'log[foo]', :delayed
+ notifies :write, 'log[baz]', :delayed
+end
+notifying_test "whatever"
+log "baz"
+EOM
+
+ end
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+log_level :warn
+EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ # the delayed notification from the sub-resource is de-duplicated by the notification already in the parent run_context
+ expect(result.stdout).to match(/\* log\[quux\] action write\s+\* notifying_test\[whatever\] action run\s+\* log\[bar\] action write\s+\* log\[baz\] action write\s+\* log\[foo\] action write\s+\* log\[baz\] action write/)
+ # and only run once
+ expect(result.stdout).not_to match(/\* log\[foo\] action write.*\* log\[foo\] action write/)
+ result.error!
+ end
+ end
+
+ when_the_repository "notifies delayed four" do
+ before do
+ directory "cookbooks/x" do
+ file "recipes/default.rb", <<EOM
+log "foo" do
+ action :nothing
+end
+log "bar" do
+ notifies :write, 'log[foo]', :delayed
+end
+log "baz" do
+ notifies :write, 'log[foo]', :delayed
+end
+EOM
+
+ end
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+log_level :warn
+EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ # the delayed notification from the sub-resource is de-duplicated by the notification already in the parent run_context
+ expect(result.stdout).to match(/\* log\[bar\] action write\s+\* log\[baz\] action write\s+\* log\[foo\] action write/)
+ # and only run once
+ expect(result.stdout).not_to match(/\* log\[foo\] action write.*\* log\[foo\] action write/)
+ result.error!
+ end
+ end
+
+ when_the_repository "notifies immediately" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/notifying_test.rb", <<EOM
+default_action :run
+provides :notifying_test
+resource_name :notifying_test
+
+action :run do
+ log "bar" do
+ notifies :write, 'log[foo]', :immediately
+ end
+end
+EOM
+
+ file "recipes/default.rb", <<EOM
+log "foo" do
+ action :nothing
+end
+notifying_test "whatever"
+log "baz"
+EOM
+
+ end
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+log_level :warn
+EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ expect(result.stdout).to match(/\* log\[bar\] action write\s+\* log\[foo\] action write\s+\* log\[baz\] action write/)
+ result.error!
+ end
+ end
+
+ when_the_repository "uses old notifies syntax" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/notifying_test.rb", <<EOM
+default_action :run
+provides :notifying_test
+resource_name :notifying_test
+
+action :run do
+ log "bar" do
+ notifies :write, resources(log: "foo"), :immediately
+ end
+end
+EOM
+
+ file "recipes/default.rb", <<EOM
+log "foo" do
+ action :nothing
+end
+notifying_test "whatever"
+log "baz"
+EOM
+
+ end
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+log_level :warn
+EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ expect(result.stdout).to match(/\* log\[bar\] action write\s+\* log\[foo\] action write\s+\* log\[baz\] action write/)
+ result.error!
+ end
+ end
+
+ when_the_repository "does not have a matching resource" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/notifying_test.rb", <<EOM
+default_action :run
+provides :notifying_test
+resource_name :notifying_test
+
+action :run do
+ log "bar" do
+ notifies :write, "log[foo]"
+ end
+end
+EOM
+
+ file "recipes/default.rb", <<EOM
+notifying_test "whatever"
+log "baz"
+EOM
+
+ end
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+log_level :warn
+EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ expect(result.stdout).to match(/Chef::Exceptions::ResourceNotFound/)
+ expect(result.exitstatus).not_to eql(0)
+ end
+ end
+
+ when_the_repository "encounters identical resources in parent and child resource collections" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/cloning_test.rb", <<EOM
+default_action :run
+provides :cloning_test
+resource_name :cloning_test
+
+action :run do
+ log "bar" do
+ level :info
+ end
+end
+EOM
+
+ file "recipes/default.rb", <<EOM
+log "bar" do
+ level :warn
+end
+
+cloning_test "whatever"
+EOM
+
+ end
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+log_level :warn
+EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ expect(result.stdout).not_to match(/CHEF-3694/)
+ result.error!
+ end
+ end
+end
diff --git a/spec/unit/application/client_spec.rb b/spec/unit/application/client_spec.rb
index 97a297ccb5..6765ca93ae 100644
--- a/spec/unit/application/client_spec.rb
+++ b/spec/unit/application/client_spec.rb
@@ -17,6 +17,55 @@
require "spec_helper"
+shared_context "with signal handlers" do
+ before do
+ Chef::Config[:specific_recipes] = [] # normally gets set in @app.reconfigure
+
+ @app = Chef::Application::Client.new
+ @app.setup_signal_handlers
+ # Default logger doesn't work correctly when logging from a trap handler.
+ @app.configure_logging
+ end
+end
+
+shared_context "with interval_sleep" do
+ before do
+ run_count = 0
+
+ # uncomment to debug failures...
+ # Chef::Log.init($stderr)
+ # Chef::Log.level = :debug
+
+ allow(@app).to receive(:run_chef_client) do
+ run_count += 1
+ if run_count > 3
+ exit 0
+ end
+
+ # If everything is fine, sending USR1 to self should prevent
+ # app to go into splay sleep forever.
+ Process.kill("USR1", Process.pid)
+ # On Ruby < 2.1, we need to give the signal handlers a little
+ # more time, otherwise the test will fail because interleavings.
+ sleep 1
+ end
+
+ number_of_sleep_calls = 0
+
+ # This is a very complicated way of writing
+ # @app.should_receive(:sleep).once.
+ # We have to do it this way because the main loop of
+ # Chef::Application::Client swallows most exceptions, and we need to be
+ # able to expose our expectation failures to the parent process in the test.
+ allow(@app).to receive(:interval_sleep) do |arg|
+ number_of_sleep_calls += 1
+ if number_of_sleep_calls > 1
+ exit 127
+ end
+ end
+ end
+end
+
describe Chef::Application::Client, "reconfigure" do
let(:app) do
a = described_class.new
@@ -26,6 +75,7 @@ describe Chef::Application::Client, "reconfigure" do
before do
allow(Kernel).to receive(:trap).and_return(:ok)
+ allow(::File).to receive(:read).and_call_original
allow(::File).to receive(:read).with(Chef::Config.platform_specific_path("/etc/chef/client.rb")).and_return("")
@original_argv = ARGV.dup
@@ -52,17 +102,44 @@ describe Chef::Application::Client, "reconfigure" do
app.reconfigure
end
- context "when given a named_run_list" do
+ shared_examples "sets the configuration" do |cli_arguments, expected_config|
+ describe cli_arguments do
+ before do
+ ARGV.replace(cli_arguments.split)
+ app.reconfigure
+ end
- before do
- ARGV.replace( %w{ --named-run-list arglebargle-example } )
- app.reconfigure
+ it "sets #{expected_config}" do
+ expect(Chef::Config.configuration).to include expected_config
+ end
+ end
+ end
+
+ describe "--named-run-list" do
+ it_behaves_like "sets the configuration",
+ "--named-run-list arglebargle-example",
+ :named_run_list => "arglebargle-example"
+ end
+
+ describe "--no-listen" do
+ it_behaves_like "sets the configuration", "--no-listen", :listen => false
+ end
+
+ describe "--daemonize", :unix_only do
+ context "with no value" do
+ it_behaves_like "sets the configuration", "--daemonize",
+ :daemonize => true
end
- it "sets named_run_list in Chef::Config" do
- expect(Chef::Config[:named_run_list]).to eq("arglebargle-example")
+ context "with an integer value" do
+ it_behaves_like "sets the configuration", "--daemonize 5",
+ :daemonize => 5
end
+ context "with a non-integer value" do
+ it_behaves_like "sets the configuration", "--daemonize foo",
+ :daemonize => true
+ end
end
end
@@ -116,15 +193,46 @@ Enable chef-client interval runs by setting `:client_fork = true` in your config
end
end
- describe "when in daemonized mode and no interval has been set" do
+ describe "daemonized mode", :unix_only do
+ let(:daemonize) { true }
+
before do
- Chef::Config[:daemonize] = true
- Chef::Config[:interval] = nil
+ Chef::Config[:daemonize] = daemonize
+ allow(Chef::Daemon).to receive(:daemonize)
end
- it "should set the interval to 1800" do
- app.reconfigure
- expect(Chef::Config.interval).to eq(1800)
+ context "when no interval has been set" do
+ before do
+ Chef::Config[:interval] = nil
+ end
+
+ it "should set the interval to 1800" do
+ app.reconfigure
+ expect(Chef::Config.interval).to eq(1800)
+ end
+ end
+
+ context "when the daemonize option is an integer" do
+ include_context "with signal handlers"
+ include_context "with interval_sleep"
+
+ let(:wait_secs) { 1 }
+ let(:daemonize) { wait_secs }
+
+ before do
+ allow(@app).to receive(:interval_sleep).with(wait_secs).and_return true
+ allow(@app).to receive(:interval_sleep).with(0).and_call_original
+ end
+
+ it "sleeps for the amount of time passed" do
+ pid = fork do
+ expect(@app).to receive(:interval_sleep).with(wait_secs)
+ @app.run_application
+ end
+ _pid, result = Process.waitpid2(pid)
+
+ expect(result.exitstatus).to eq 0
+ end
end
end
@@ -148,16 +256,6 @@ Enable chef-client interval runs by setting `:client_fork = true` in your config
end
- describe "when --no-listen is set" do
-
- it "configures listen = false" do
- app.config[:listen] = false
- app.reconfigure
- expect(Chef::Config[:listen]).to eq(false)
- end
-
- end
-
describe "when the json_attribs configuration option is specified" do
let(:json_attribs) { { "a" => "b" } }
@@ -305,14 +403,9 @@ describe Chef::Application::Client, "configure_chef" do
end
describe Chef::Application::Client, "run_application", :unix_only do
- before(:each) do
- Chef::Config[:specific_recipes] = [] # normally gets set in @app.reconfigure
-
- @app = Chef::Application::Client.new
- @app.setup_signal_handlers
- # Default logger doesn't work correctly when logging from a trap handler.
- @app.configure_logging
+ include_context "with signal handlers"
+ before(:each) do
@pipe = IO.pipe
@client = Chef::Client.new
allow(Chef::Client).to receive(:new).and_return(@client)
@@ -383,44 +476,11 @@ describe Chef::Application::Client, "run_application", :unix_only do
end
describe "when splay is set" do
+ include_context "with interval_sleep"
+
before do
Chef::Config[:splay] = 10
Chef::Config[:interval] = 10
-
- run_count = 0
-
- # uncomment to debug failures...
- # Chef::Log.init($stderr)
- # Chef::Log.level = :debug
-
- allow(@app).to receive(:run_chef_client) do
-
- run_count += 1
- if run_count > 3
- exit 0
- end
-
- # If everything is fine, sending USR1 to self should prevent
- # app to go into splay sleep forever.
- Process.kill("USR1", Process.pid)
- # On Ruby < 2.1, we need to give the signal handlers a little
- # more time, otherwise the test will fail because interleavings.
- sleep 1
- end
-
- number_of_sleep_calls = 0
-
- # This is a very complicated way of writing
- # @app.should_receive(:sleep).once.
- # We have to do it this way because the main loop of
- # Chef::Application::Client swallows most exceptions, and we need to be
- # able to expose our expectation failures to the parent process in the test.
- allow(@app).to receive(:interval_sleep) do |arg|
- number_of_sleep_calls += 1
- if number_of_sleep_calls > 1
- exit 127
- end
- end
end
it "shouldn't sleep when sent USR1" do
diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb
index 462b7314c4..8ab6e13204 100644
--- a/spec/unit/application_spec.rb
+++ b/spec/unit/application_spec.rb
@@ -247,6 +247,33 @@ describe Chef::Application do
it_behaves_like "log_level_is_auto"
end
+
+ describe "log_location" do
+ shared_examples("sets log_location") do |config_value, expected_class|
+ context "when the configured value is #{config_value.inspect}" do
+ let(:logger_instance) { instance_double(expected_class).as_null_object }
+
+ before do
+ allow(expected_class).to receive(:new).and_return(logger_instance)
+ Chef::Config[:log_location] = config_value
+ end
+
+ it "it sets log_location to an instance of #{expected_class}" do
+ expect(expected_class).to receive(:new).with no_args
+ @app.configure_logging
+ expect(Chef::Config[:log_location]).to be logger_instance
+ end
+ end
+ end
+
+ if Chef::Platform.windows?
+ it_behaves_like "sets log_location", :win_evt, Chef::Log::WinEvt
+ it_behaves_like "sets log_location", "win_evt", Chef::Log::WinEvt
+ else
+ it_behaves_like "sets log_location", :syslog, Chef::Log::Syslog
+ it_behaves_like "sets log_location", "syslog", Chef::Log::Syslog
+ end
+ end
end
end
diff --git a/spec/unit/knife/cookbook_create_spec.rb b/spec/unit/knife/cookbook_create_spec.rb
index a183bef103..5e343f3db1 100644
--- a/spec/unit/knife/cookbook_create_spec.rb
+++ b/spec/unit/knife/cookbook_create_spec.rb
@@ -56,13 +56,13 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
+ :cookbook_copyright => "Chef Software, Inc.",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "none")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "none")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "YOUR_EMAIL", "none", "md")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "YOUR_EMAIL", "none", "md")
@knife.run
end
@@ -70,14 +70,14 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "none")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "none")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "none", "md")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "none", "md")
@knife.run
end
@@ -85,15 +85,15 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
:cookbook_license => "apachev2",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "apachev2")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "apachev2")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "apachev2", "md")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "apachev2", "md")
@knife.run
end
@@ -101,15 +101,15 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
:cookbook_license => false,
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "none")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "none")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "none", "md")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "none", "md")
@knife.run
end
@@ -117,15 +117,15 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
:cookbook_license => "false",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "none")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "none")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "none", "md")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "none", "md")
@knife.run
end
@@ -133,15 +133,15 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
:cookbook_license => "gplv2",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "gplv2")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "gplv2")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "gplv2", "md")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "gplv2", "md")
@knife.run
end
@@ -149,15 +149,15 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
:cookbook_license => "gplv3",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "gplv3")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "gplv3")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "gplv3", "md")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "gplv3", "md")
@knife.run
end
@@ -165,15 +165,15 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
:cookbook_license => "mit",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "mit")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "mit")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "md")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "mit", "md")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "mit", "md")
@knife.run
end
@@ -181,33 +181,33 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
:cookbook_license => "mit",
:readme_format => "rdoc",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "mit")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "mit")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "rdoc")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "mit", "rdoc")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "mit", "rdoc")
@knife.run
end
- it "should allow specifying the mkd readme format" do
+ it "should allow specifying the md readme format" do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
:cookbook_license => "mit",
:readme_format => "mkd",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "mit")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "mit")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "mkd")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "mit", "mkd")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "mit", "mkd")
@knife.run
end
@@ -215,16 +215,16 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
:cookbook_license => "mit",
:readme_format => "txt",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "mit")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "mit")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "txt")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "mit", "txt")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "mit", "txt")
@knife.run
end
@@ -232,16 +232,16 @@ describe Chef::Knife::CookbookCreate do
@dir = Dir.tmpdir
@knife.config = {
:cookbook_path => @dir,
- :cookbook_copyright => "Opscode, Inc",
- :cookbook_email => "nuo@opscode.com",
+ :cookbook_copyright => "Chef Software, Inc.",
+ :cookbook_email => "test@chef.io",
:cookbook_license => "mit",
:readme_format => "foo",
}
@knife.name_args = ["foobar"]
- expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Opscode, Inc", "mit")
+ expect(@knife).to receive(:create_cookbook).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "mit")
expect(@knife).to receive(:create_readme).with(@dir, @knife.name_args.first, "foo")
expect(@knife).to receive(:create_changelog).with(@dir, @knife.name_args.first)
- expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Opscode, Inc", "nuo@opscode.com", "mit", "foo")
+ expect(@knife).to receive(:create_metadata).with(@dir, @knife.name_args.first, "Chef Software, Inc.", "test@chef.io", "mit", "foo")
@knife.run
end
diff --git a/spec/unit/knife/ssh_spec.rb b/spec/unit/knife/ssh_spec.rb
index 3a8728515d..65cc5a97b4 100644
--- a/spec/unit/knife/ssh_spec.rb
+++ b/spec/unit/knife/ssh_spec.rb
@@ -203,6 +203,23 @@ describe Chef::Knife::Ssh do
expect(@knife.session.servers[0].port).to eq(123)
end
+ it "uses the timeout from Chef Config" do
+ Chef::Config[:knife][:ssh_timeout] = 5
+ @knife.session_from_list([["the.b.org", nil]])
+ expect(@knife.session.servers[0].options[:timeout]).to eq(5)
+ end
+
+ it "uses the timeout from knife config" do
+ @knife.config[:ssh_timeout] = 6
+ @knife.session_from_list([["the.b.org", nil]])
+ expect(@knife.session.servers[0].options[:timeout]).to eq(6)
+ end
+
+ it "defaults to no timeout" do
+ @knife.session_from_list([["the.b.org", nil]])
+ expect(@knife.session.servers[0].options[:timeout]).to eq(nil)
+ end
+
it "uses the user from an ssh config file" do
@knife.session_from_list([["the.b.org", 123]])
expect(@knife.session.servers[0].user).to eq("locutus")
diff --git a/spec/unit/mixin/path_sanity_spec.rb b/spec/unit/mixin/path_sanity_spec.rb
index 2c26e2fb79..675b5722be 100644
--- a/spec/unit/mixin/path_sanity_spec.rb
+++ b/spec/unit/mixin/path_sanity_spec.rb
@@ -57,7 +57,7 @@ describe Chef::Mixin::PathSanity do
end
it "creates path with utf-8 encoding" do
- env = { "PATH" => "/usr/bin:/sbin:/bin:/b\x81t".force_encoding("ISO-8859-1") }
+ env = { "PATH" => "/usr/bin:/sbin:/bin:/b#{0x81.chr}t".force_encoding("ISO-8859-1") }
@sanity.enforce_path_sanity(env)
expect(env["PATH"].encoding.to_s).to eq("UTF-8")
end
diff --git a/spec/unit/mixin/xml_escape_spec.rb b/spec/unit/mixin/xml_escape_spec.rb
index 2723fce765..903c91164e 100644
--- a/spec/unit/mixin/xml_escape_spec.rb
+++ b/spec/unit/mixin/xml_escape_spec.rb
@@ -49,6 +49,6 @@ describe Chef::Mixin::XMLEscape do
end
it "converts win 1252 characters correctly" do
- expect(@escaper.xml_escape("\x80")).to eq('&#8364;')
+ expect(@escaper.xml_escape("#{0x80.chr}")).to eq('&#8364;')
end
end
diff --git a/spec/unit/provider/mount/aix_spec.rb b/spec/unit/provider/mount/aix_spec.rb
index 9a34a6d21d..3371c270c5 100644
--- a/spec/unit/provider/mount/aix_spec.rb
+++ b/spec/unit/provider/mount/aix_spec.rb
@@ -126,10 +126,9 @@ ENABLED
@provider.run_action(:mount)
end
- it "should not mount resource if it is already mounted and the options have not changed" do
+ it "should not mount resource if it is already mounted" do
stub_mounted_enabled(@provider, @mounted_output, "")
- allow(@provider).to receive(:mount_options_unchanged?).and_return(true)
expect(@provider).not_to receive(:mount_fs)
@provider.run_action(:mount)
diff --git a/spec/unit/provider/mount/mount_spec.rb b/spec/unit/provider/mount/mount_spec.rb
index 52be15b2a8..42585d9e3e 100644
--- a/spec/unit/provider/mount/mount_spec.rb
+++ b/spec/unit/provider/mount/mount_spec.rb
@@ -323,12 +323,6 @@ describe Chef::Provider::Mount::Mount do
@provider.mount_fs()
end
- it "should not mount the filesystem if it is mounted and the options have not changed" do
- allow(@current_resource).to receive(:mounted).and_return(true)
- expect(@provider).to_not receive(:shell_out!)
- @provider.mount_fs()
- end
-
end
describe "umount_fs" do
diff --git a/spec/unit/provider/mount/windows_spec.rb b/spec/unit/provider/mount/windows_spec.rb
index ec1945de50..fdb44836b5 100644
--- a/spec/unit/provider/mount/windows_spec.rb
+++ b/spec/unit/provider/mount/windows_spec.rb
@@ -112,14 +112,6 @@ describe Chef::Provider::Mount::Windows do
@provider.mount_fs
end
- it "should remount the filesystem if it is mounted and the options have changed" do
- expect(@vol).to receive(:add).with(:remote => @new_resource.device,
- :username => @new_resource.username,
- :domainname => @new_resource.domain,
- :password => @new_resource.password)
- @provider.mount_fs
- end
-
context "mount_options_unchanged?" do
it "should return true if mounted device is the same" do
allow(@current_resource).to receive(:device).and_return(GUID)
@@ -131,12 +123,6 @@ describe Chef::Provider::Mount::Windows do
expect(@provider.send :mount_options_unchanged?).to be false
end
end
-
- it "should not mount the filesystem if it is mounted and the options have not changed" do
- expect(@vol).to_not receive(:add)
- allow(@current_resource).to receive(:mounted).and_return(true)
- @provider.mount_fs
- end
end
describe "when unmounting a file system" do
diff --git a/spec/unit/provider/mount_spec.rb b/spec/unit/provider/mount_spec.rb
index fa168e571e..19967e8496 100644
--- a/spec/unit/provider/mount_spec.rb
+++ b/spec/unit/provider/mount_spec.rb
@@ -60,25 +60,6 @@ describe Chef::Provider::Mount do
provider.run_action(:mount)
expect(new_resource).to be_updated_by_last_action
end
-
- it "should remount the filesystem if it is mounted and the options have changed" do
- allow(current_resource).to receive(:mounted).and_return(true)
- allow(provider).to receive(:mount_options_unchanged?).and_return(false)
- expect(provider).to receive(:umount_fs).and_return(true)
- expect(provider).to receive(:wait_until_unmounted)
- expect(provider).to receive(:mount_fs).and_return(true)
- provider.run_action(:mount)
- expect(new_resource).to be_updated_by_last_action
- end
-
- it "should not mount the filesystem if it is mounted and the options have not changed" do
- allow(current_resource).to receive(:mounted).and_return(true)
- expect(provider).to receive(:mount_options_unchanged?).and_return(true)
- expect(provider).not_to receive(:mount_fs)
- provider.run_action(:mount)
- expect(new_resource).not_to be_updated_by_last_action
- end
-
end
describe "when the target state is an unmounted filesystem" do
diff --git a/spec/unit/provider/service/redhat_spec.rb b/spec/unit/provider/service/redhat_spec.rb
index 9b878abcd6..40f9bc3a91 100644
--- a/spec/unit/provider/service/redhat_spec.rb
+++ b/spec/unit/provider/service/redhat_spec.rb
@@ -157,6 +157,20 @@ describe "Chef::Provider::Service::Redhat" do
end
end
+ %w{start reload restart}.each do |action|
+ it "should not raise an error when the action is #{action} and init_command is set" do
+ @new_resource.init_command("/etc/init.d/chef")
+ @provider.action = action
+ expect { @provider.process_resource_requirements }.not_to raise_error
+ end
+
+ it "should not raise an error when the action is #{action} and #{action}_command is set" do
+ @new_resource.send("#{action}_command", "/etc/init.d/chef #{action}")
+ @provider.action = action
+ expect { @provider.process_resource_requirements }.not_to raise_error
+ end
+ end
+
%w{stop disable}.each do |action|
it "should not raise an error when the action is #{action}" do
@provider.action = action
diff --git a/spec/unit/resource_collection_spec.rb b/spec/unit/resource_collection_spec.rb
index a6ad895c51..256ae090e0 100644
--- a/spec/unit/resource_collection_spec.rb
+++ b/spec/unit/resource_collection_spec.rb
@@ -283,6 +283,76 @@ describe Chef::ResourceCollection do
end
end
+ describe "multiple run_contexts" do
+ let(:node) { Chef::Node.new }
+ let(:parent_run_context) { Chef::RunContext.new(node, {}, nil) }
+ let(:parent_resource_collection) { parent_run_context.resource_collection }
+ let(:child_run_context) { parent_run_context.create_child }
+ let(:child_resource_collection) { child_run_context.resource_collection }
+
+ it "should find resources in the parent run_context with lookup" do
+ zmr = Chef::Resource::ZenMaster.new("dog")
+ parent_resource_collection << zmr
+ expect(child_resource_collection.lookup(zmr.to_s)).to eql(zmr)
+ end
+
+ it "should not find resources in the parent run_context with lookup_local" do
+ zmr = Chef::Resource::ZenMaster.new("dog")
+ parent_resource_collection << zmr
+ expect { child_resource_collection.lookup_local(zmr.to_s) }.to raise_error(Chef::Exceptions::ResourceNotFound)
+ end
+
+ it "should find resources in the child run_context with lookup_local" do
+ zmr = Chef::Resource::ZenMaster.new("dog")
+ child_resource_collection << zmr
+ expect(child_resource_collection.lookup_local(zmr.to_s)).to eql(zmr)
+ end
+
+ it "should find resources in the parent run_context with find" do
+ zmr = Chef::Resource::ZenMaster.new("dog")
+ parent_resource_collection << zmr
+ expect(child_resource_collection.find(zmr.to_s)).to eql(zmr)
+ end
+
+ it "should not find resources in the parent run_context with find_local" do
+ zmr = Chef::Resource::ZenMaster.new("dog")
+ parent_resource_collection << zmr
+ expect { child_resource_collection.find_local(zmr.to_s) }.to raise_error(Chef::Exceptions::ResourceNotFound)
+ end
+
+ it "should find resources in the child run_context with find_local" do
+ zmr = Chef::Resource::ZenMaster.new("dog")
+ child_resource_collection << zmr
+ expect(child_resource_collection.find_local(zmr.to_s)).to eql(zmr)
+ end
+
+ it "should not find resources in the child run_context in any way from the parent" do
+ zmr = Chef::Resource::ZenMaster.new("dog")
+ child_resource_collection << zmr
+ expect { parent_resource_collection.find_local(zmr.to_s) }.to raise_error(Chef::Exceptions::ResourceNotFound)
+ expect { parent_resource_collection.find(zmr.to_s) }.to raise_error(Chef::Exceptions::ResourceNotFound)
+ expect { parent_resource_collection.lookup_local(zmr.to_s) }.to raise_error(Chef::Exceptions::ResourceNotFound)
+ expect { parent_resource_collection.lookup(zmr.to_s) }.to raise_error(Chef::Exceptions::ResourceNotFound)
+ end
+
+ it "should behave correctly when there is an identically named resource in the child and parent" do
+ a = Chef::Resource::File.new("something")
+ a.content("foo")
+ parent_resource_collection << a
+ b = Chef::Resource::File.new("something")
+ b.content("bar")
+ child_resource_collection << b
+ expect(child_resource_collection.find_local("file[something]").content).to eql("bar")
+ expect(child_resource_collection.find("file[something]").content).to eql("bar")
+ expect(child_resource_collection.lookup_local("file[something]").content).to eql("bar")
+ expect(child_resource_collection.lookup("file[something]").content).to eql("bar")
+ expect(parent_resource_collection.find_local("file[something]").content).to eql("foo")
+ expect(parent_resource_collection.find("file[something]").content).to eql("foo")
+ expect(parent_resource_collection.lookup_local("file[something]").content).to eql("foo")
+ expect(parent_resource_collection.lookup("file[something]").content).to eql("foo")
+ end
+ end
+
def check_by_names(results, *names)
names.each do |res_name|
expect(results.detect { |res| res.name == res_name }).not_to eql(nil)
diff --git a/spec/unit/util/diff_spec.rb b/spec/unit/util/diff_spec.rb
index 29c645bb1d..4bb0abd087 100644
--- a/spec/unit/util/diff_spec.rb
+++ b/spec/unit/util/diff_spec.rb
@@ -76,7 +76,7 @@ shared_examples_for "a diff util" do
describe "when the old_file has binary content" do
before do
- old_tempfile.write("\x01\xff")
+ old_tempfile.write("#{0x01.chr}#{0xFF.chr}")
old_tempfile.close
end
@@ -91,7 +91,7 @@ shared_examples_for "a diff util" do
describe "when the new_file has binary content" do
before do
- new_tempfile.write("\x01\xff")
+ new_tempfile.write("#{0x01.chr}#{0xFF.chr}")
new_tempfile.close
end
@@ -553,8 +553,8 @@ describe Chef::Util::Diff, :uses_diff => true do
let(:plain_ascii) { "This is a text file.\nWith more than one line.\nAnd a \tTab.\nAnd lets make sure that other printable chars work too: ~!@\#$%^&*()`:\"<>?{}|_+,./;'[]\\-=\n" }
# these are all byte sequences that are illegal in the other encodings... (but they may legally transcode)
let(:utf_8) { "testing utf-8 unicode...\n\n\non a new line: \xE2\x80\x93\n" } # unicode em-dash
- let(:latin_1) { "It is more metal.\nif you have an \xFDmlaut.\n" } # NB: changed to y-with-diaresis, but i'm American so I don't know the difference
- let(:shift_jis) { "I have no idea what this character is:\n \x83\x80.\n" } # seriously, no clue, but \x80 is nice and illegal in other encodings
+ let(:latin_1) { "It is more metal.\nif you have an #{0xFD.chr}mlaut.\n" } # NB: changed to y-with-diaresis, but i'm American so I don't know the difference
+ let(:shift_jis) { "I have no idea what this character is:\n #{0x83.chr}#{0x80.chr}.\n" } # seriously, no clue, but \x80 is nice and illegal in other encodings
let(:differ) do # subject
differ = Chef::Util::Diff.new