summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.expeditor/release.omnibus.yml2
-rw-r--r--.expeditor/verify.pipeline.yml4
-rw-r--r--CHANGELOG.md15
-rw-r--r--Gemfile.lock28
-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/README.md11
-rw-r--r--chef-utils/lib/chef-utils/dsl/architecture.rb10
-rw-r--r--chef-utils/lib/chef-utils/version.rb2
-rw-r--r--chef-utils/spec/unit/dsl/architecture_spec.rb8
-rw-r--r--chef.gemspec2
-rw-r--r--kitchen-tests/cookbooks/end_to_end/recipes/default.rb6
-rw-r--r--kitchen-tests/kitchen.yml1
-rw-r--r--lib/chef/knife/bootstrap.rb5
-rw-r--r--lib/chef/knife/core/bootstrap_context.rb6
-rw-r--r--lib/chef/provider.rb16
-rw-r--r--lib/chef/provider/launchd.rb2
-rw-r--r--lib/chef/provider/osx_profile.rb3
-rw-r--r--lib/chef/provider/user/dscl.rb6
-rw-r--r--lib/chef/provider/user/mac.rb5
-rw-r--r--lib/chef/resource.rb14
-rw-r--r--lib/chef/resource/build_essential.rb2
-rw-r--r--lib/chef/resource/chef_client_cron.rb47
-rw-r--r--lib/chef/resource/chef_client_scheduled_task.rb8
-rw-r--r--lib/chef/resource/chef_client_systemd_timer.rb177
-rw-r--r--lib/chef/resource/plist.rb207
-rw-r--r--lib/chef/resource/sysctl.rb1
-rw-r--r--lib/chef/resources.rb2
-rw-r--r--lib/chef/run_context/cookbook_compiler.rb2
-rw-r--r--lib/chef/version.rb2
-rw-r--r--omnibus/omnibus-test.sh2
-rw-r--r--spec/functional/assets/inittest15
-rw-r--r--spec/functional/resource/insserv_spec.rb2
-rw-r--r--spec/integration/recipes/notifies_spec.rb16
-rw-r--r--spec/integration/recipes/use_partial_spec.rb112
-rw-r--r--spec/spec_helper.rb2
-rw-r--r--spec/support/platform_helpers.rb4
-rw-r--r--spec/unit/knife/core/bootstrap_context_spec.rb4
-rw-r--r--spec/unit/resource/chef_client_systemd_timer_spec.rb70
-rw-r--r--spec/unit/resource/plist_spec.rb130
41 files changed, 872 insertions, 85 deletions
diff --git a/.expeditor/release.omnibus.yml b/.expeditor/release.omnibus.yml
index 1b744416fc..59850b1266 100644
--- a/.expeditor/release.omnibus.yml
+++ b/.expeditor/release.omnibus.yml
@@ -21,6 +21,7 @@ builder-to-testers-map:
el-7-aarch64:
- el-7-aarch64
- el-8-aarch64
+ - amzn-2-aarch64
el-7-ppc64:
- el-7-ppc64
el-7-ppc64le:
@@ -28,6 +29,7 @@ builder-to-testers-map:
el-7-x86_64:
- el-7-x86_64
- el-8-x86_64
+ - amzn-2-x86_64
freebsd-11-amd64:
- freebsd-11-amd64
- freebsd-12-amd64
diff --git a/.expeditor/verify.pipeline.yml b/.expeditor/verify.pipeline.yml
index 69b65ad155..d2389cde90 100644
--- a/.expeditor/verify.pipeline.yml
+++ b/.expeditor/verify.pipeline.yml
@@ -89,6 +89,7 @@ steps:
- label: "Integration Specs openSUSE :ruby: 2.6"
commands:
- /workdir/scripts/bk_tests/bk_container_prep.sh
+ - zypper install -y cron insserv-compat
- cd /workdir; bundle install --jobs=3 --retry=3 --path=vendor/bundle --without omnibus_package docgen
- bundle exec rake spec:integration
expeditor:
@@ -100,7 +101,7 @@ steps:
- label: "Functional Specs openSUSE :ruby: 2.6"
commands:
- /workdir/scripts/bk_tests/bk_container_prep.sh
- - zypper install -y cronie
+ - zypper install -y cronie insserv-compat
- cd /workdir; bundle install --jobs=3 --retry=3 --path=vendor/bundle --without omnibus_package docgen ruby_prof
- bundle exec rake spec:functional
expeditor:
@@ -112,6 +113,7 @@ steps:
- label: "Unit Specs openSUSE :ruby: 2.6"
commands:
- /workdir/scripts/bk_tests/bk_container_prep.sh
+ - zypper install -y cron insserv-compat
- bundle install --jobs=3 --retry=3 --path=vendor/bundle --without omnibus_package docgen ruby_prof
- bundle exec rake spec:unit
- bundle exec rake component_specs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a5353e5f16..d0ff1746a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,15 +1,24 @@
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
-<!-- latest_release 16.0.194 -->
-## [v16.0.194](https://github.com/chef/chef/tree/v16.0.194) (2020-04-08)
+<!-- latest_release 16.0.203 -->
+## [v16.0.203](https://github.com/chef/chef/tree/v16.0.203) (2020-04-13)
#### Merged Pull Requests
-- Bump train-core to 3.2.27 [#9628](https://github.com/chef/chef/pull/9628) ([chef-expeditor[bot]](https://github.com/chef-expeditor[bot]))
+- Remove support for SLES11 and update tests to just on openSUSE [#9299](https://github.com/chef/chef/pull/9299) ([dheerajd-msys](https://github.com/dheerajd-msys))
<!-- latest_release -->
<!-- release_rollup since=15.6.10 -->
### Changes not yet released to stable
#### Merged Pull Requests
+- Remove support for SLES11 and update tests to just on openSUSE [#9299](https://github.com/chef/chef/pull/9299) ([dheerajd-msys](https://github.com/dheerajd-msys)) <!-- 16.0.203 -->
+- Add the plist resource from the macos cookbook [#9642](https://github.com/chef/chef/pull/9642) ([tas50](https://github.com/tas50)) <!-- 16.0.202 -->
+- Support non-Linux hosts in chef_client_cron [#9647](https://github.com/chef/chef/pull/9647) ([tas50](https://github.com/tas50)) <!-- 16.0.201 -->
+- Add resource partials [#9632](https://github.com/chef/chef/pull/9632) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 16.0.200 -->
+- Add Amazon Linux 2 Testers [#9641](https://github.com/chef/chef/pull/9641) ([christopher-snapp](https://github.com/christopher-snapp)) <!-- 16.0.199 -->
+- Add chef_client_systemd_timer resource [#9624](https://github.com/chef/chef/pull/9624) ([tas50](https://github.com/tas50)) <!-- 16.0.198 -->
+- Fix knife bootstrap_version CLI option overriding config option [#9634](https://github.com/chef/chef/pull/9634) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 16.0.197 -->
+- Bump highline to 2.x [#9633](https://github.com/chef/chef/pull/9633) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 16.0.196 -->
+- Add arm? helper to chef-utils [#9622](https://github.com/chef/chef/pull/9622) ([tas50](https://github.com/tas50)) <!-- 16.0.195 -->
- Bump train-core to 3.2.27 [#9628](https://github.com/chef/chef/pull/9628) ([chef-expeditor[bot]](https://github.com/chef-expeditor[bot])) <!-- 16.0.194 -->
- Fixed systemd_unit not respecting sensitive property [#9623](https://github.com/chef/chef/pull/9623) ([sanga1794](https://github.com/sanga1794)) <!-- 16.0.193 -->
- Bump inspec-core to 4.18.104 [#9625](https://github.com/chef/chef/pull/9625) ([chef-expeditor[bot]](https://github.com/chef-expeditor[bot])) <!-- 16.0.192 -->
diff --git a/Gemfile.lock b/Gemfile.lock
index 80077d2089..d1f4db4ca0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -27,12 +27,12 @@ GIT
PATH
remote: .
specs:
- chef (16.0.194)
+ chef (16.0.203)
addressable
bcrypt_pbkdf (~> 1.0)
bundler (>= 1.10)
- chef-config (= 16.0.194)
- chef-utils (= 16.0.194)
+ chef-config (= 16.0.203)
+ chef-utils (= 16.0.203)
chef-vault
chef-zero (>= 14.0.11)
diff-lcs (~> 1.2, >= 1.2.4)
@@ -41,7 +41,7 @@ PATH
ffi (~> 1.9, >= 1.9.25)
ffi-libarchive
ffi-yajl (~> 2.2)
- highline (>= 1.6.9, < 2)
+ highline (>= 1.6.9, < 3)
iniparse (~> 1.4)
license-acceptance (~> 1.0, >= 1.0.5)
mixlib-archive (>= 0.4, < 2.0)
@@ -61,12 +61,12 @@ PATH
train-winrm (>= 0.2.5)
tty-screen (~> 0.6)
uuidtools (~> 2.1.5)
- chef (16.0.194-universal-mingw32)
+ chef (16.0.203-universal-mingw32)
addressable
bcrypt_pbkdf (~> 1.0)
bundler (>= 1.10)
- chef-config (= 16.0.194)
- chef-utils (= 16.0.194)
+ chef-config (= 16.0.203)
+ chef-utils (= 16.0.203)
chef-vault
chef-zero (>= 14.0.11)
diff-lcs (~> 1.2, >= 1.2.4)
@@ -75,7 +75,7 @@ PATH
ffi (~> 1.9, >= 1.9.25)
ffi-libarchive
ffi-yajl (~> 2.2)
- highline (>= 1.6.9, < 2)
+ highline (>= 1.6.9, < 3)
iniparse (~> 1.4)
iso8601 (~> 0.12.1)
license-acceptance (~> 1.0, >= 1.0.5)
@@ -111,15 +111,15 @@ PATH
PATH
remote: chef-bin
specs:
- chef-bin (16.0.194)
- chef (= 16.0.194)
+ chef-bin (16.0.203)
+ chef (= 16.0.203)
PATH
remote: chef-config
specs:
- chef-config (16.0.194)
+ chef-config (16.0.203)
addressable
- chef-utils (= 16.0.194)
+ chef-utils (= 16.0.203)
fuzzyurl
mixlib-config (>= 2.2.12, < 4.0)
mixlib-shellout (>= 2.0, < 4.0)
@@ -128,7 +128,7 @@ PATH
PATH
remote: chef-utils
specs:
- chef-utils (16.0.194)
+ chef-utils (16.0.203)
GEM
remote: https://rubygems.org/
@@ -197,7 +197,7 @@ GEM
hana (1.3.5)
hashdiff (1.0.1)
hashie (3.6.0)
- highline (1.7.10)
+ highline (2.0.3)
htmlentities (4.3.4)
http (2.2.2)
addressable (~> 2.3)
diff --git a/VERSION b/VERSION
index efe6db8be5..879e748dc2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-16.0.194 \ No newline at end of file
+16.0.203 \ 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 a5ff71f8ef..547b2ff61e 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("../..", __FILE__)
- VERSION = "16.0.194".freeze
+ VERSION = "16.0.203".freeze
end
#
diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb
index c1c6ab7f44..116dbcfe38 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("../..", __FILE__)
- VERSION = "16.0.194".freeze
+ VERSION = "16.0.203".freeze
end
diff --git a/chef-utils/README.md b/chef-utils/README.md
index e44d4d6937..18830d07c1 100644
--- a/chef-utils/README.md
+++ b/chef-utils/README.md
@@ -108,17 +108,18 @@ The OS helpers provide an alternative to comparing data from `node['os']`.
Architecture Helpers allow you to determine the processor architecture of your node.
-* `_64_bit?`
* `_32_bit?`
+* `_64_bit?`
+* `arm?`
+* `armhf?`
* `i386?`
* `intel?`
-* `sparc?`
+* `powerpc?`
* `ppc64?`
* `ppc64le?`
-* `powerpc?`
-* `armhf?`
-* `s390x?`
* `s390?`
+* `s390x?`
+* `sparc?`
### Cloud Helpers
diff --git a/chef-utils/lib/chef-utils/dsl/architecture.rb b/chef-utils/lib/chef-utils/dsl/architecture.rb
index d20c6c5a76..03f2756ab1 100644
--- a/chef-utils/lib/chef-utils/dsl/architecture.rb
+++ b/chef-utils/lib/chef-utils/dsl/architecture.rb
@@ -103,6 +103,16 @@ module ChefUtils
%w{powerpc}.include?(node["kernel"]["machine"])
end
+ # Determine if the current architecture is arm
+ #
+ # @since 15.10
+ #
+ # @return [Boolean]
+ #
+ def arm?(node = __getnode)
+ %w{armhf aarch64 arm64 arch64}.include?(node["kernel"]["machine"])
+ end
+
# Determine if the current architecture is 32-bit ARM.
#
# @since 15.5
diff --git a/chef-utils/lib/chef-utils/version.rb b/chef-utils/lib/chef-utils/version.rb
index b770c6154b..3fab094169 100644
--- a/chef-utils/lib/chef-utils/version.rb
+++ b/chef-utils/lib/chef-utils/version.rb
@@ -15,5 +15,5 @@
module ChefUtils
CHEFUTILS_ROOT = File.expand_path("../..", __FILE__)
- VERSION = "16.0.194".freeze
+ VERSION = "16.0.203".freeze
end
diff --git a/chef-utils/spec/unit/dsl/architecture_spec.rb b/chef-utils/spec/unit/dsl/architecture_spec.rb
index a2ce300fe0..c43b2d0733 100644
--- a/chef-utils/spec/unit/dsl/architecture_spec.rb
+++ b/chef-utils/spec/unit/dsl/architecture_spec.rb
@@ -84,17 +84,17 @@ RSpec.describe ChefUtils::DSL::Architecture do
context "on aarch64" do
let(:arch) { "aarch64" }
- arch_reports_true_for(:_64_bit?)
+ arch_reports_true_for(:_64_bit?, :arm?)
end
context "on arch64" do
let(:arch) { "arch64" }
- arch_reports_true_for(:_64_bit?)
+ arch_reports_true_for(:_64_bit?, :arm?)
end
context "on arm64" do
let(:arch) { "arm64" }
- arch_reports_true_for(:_64_bit?)
+ arch_reports_true_for(:_64_bit?, :arm?)
end
context "on sun4v" do
let(:arch) { "sun4v" }
@@ -129,7 +129,7 @@ RSpec.describe ChefUtils::DSL::Architecture do
context "on armhf" do
let(:arch) { "armhf" }
- arch_reports_true_for(:armhf?, :_32_bit?)
+ arch_reports_true_for(:armhf?, :_32_bit?, :arm?)
end
context "on s390" do
let(:arch) { "s390" }
diff --git a/chef.gemspec b/chef.gemspec
index 427a2cfece..0bdd455ab5 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -35,7 +35,7 @@ Gem::Specification.new do |s|
s.add_dependency "net-sftp", "~> 2.1", ">= 2.1.2"
s.add_dependency "ed25519", "~> 1.2" # ed25519 ssh key support
s.add_dependency "bcrypt_pbkdf", "~> 1.0" # ed25519 ssh key support
- s.add_dependency "highline", ">= 1.6.9", "< 2"
+ s.add_dependency "highline", ">= 1.6.9", "< 3"
s.add_dependency "tty-screen", "~> 0.6" # knife list
s.add_dependency "pastel" # knife ui.color
s.add_dependency "erubis", "~> 2.7"
diff --git a/kitchen-tests/cookbooks/end_to_end/recipes/default.rb b/kitchen-tests/cookbooks/end_to_end/recipes/default.rb
index c1a335d98c..af1e516030 100644
--- a/kitchen-tests/cookbooks/end_to_end/recipes/default.rb
+++ b/kitchen-tests/cookbooks/end_to_end/recipes/default.rb
@@ -67,7 +67,6 @@ end
include_recipe "chef-client::delete_validation"
include_recipe "chef-client::config"
-include_recipe "chef-client"
include_recipe "openssh"
@@ -149,6 +148,11 @@ chef_client_cron "Run chef-client with base recipe" do
daemon_options ["--override-runlist mycorp_base::default"]
end
+chef_client_systemd_timer "Run chef-client as a systemd timer" do
+ interval "1hr"
+ only_if { systemd? }
+end
+
include_recipe "::chef-vault" unless includes_recipe?("end_to_end::chef-vault")
include_recipe "::alternatives"
include_recipe "::tests"
diff --git a/kitchen-tests/kitchen.yml b/kitchen-tests/kitchen.yml
index 8a8e749b84..b13b31125e 100644
--- a/kitchen-tests/kitchen.yml
+++ b/kitchen-tests/kitchen.yml
@@ -151,6 +151,7 @@ platforms:
intermediate_instructions:
- RUN /usr/bin/zypper --non-interactive update
- RUN /usr/bin/zypper --non-interactive install cron
+ - RUN /usr/bin/zypper --non-interactive install insserv-compat
suites:
- name: end-to-end
diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb
index d0b33628ee..3ab7773e21 100644
--- a/lib/chef/knife/bootstrap.rb
+++ b/lib/chef/knife/bootstrap.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2010-2019, Chef Software Inc.
+# Copyright:: Copyright 2010-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -149,8 +149,7 @@ class Chef
# client.rb content via chef-full/bootstrap_context
option :bootstrap_version,
long: "--bootstrap-version VERSION",
- description: "The version of #{Chef::Dist::PRODUCT} to install.",
- proc: lambda { |v| Chef::Config[:knife][:bootstrap_version] = v }
+ description: "The version of #{Chef::Dist::PRODUCT} to install."
option :channel,
long: "--channel CHANNEL",
diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb
index 8f07149ebe..f889e7b7ed 100644
--- a/lib/chef/knife/core/bootstrap_context.rb
+++ b/lib/chef/knife/core/bootstrap_context.rb
@@ -1,6 +1,6 @@
#
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2011-2016, Chef Software, Inc.
+# Copyright:: Copyright 2011-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -194,6 +194,8 @@ class Chef
s
end
+ # XXX: this reads values only out of the config file and is NOT merged with the CLI options, and it is most likely
+ # a bug to be using this accessor and we should be using config and not knife_config.
def knife_config
@chef_config.key?(:knife) ? @chef_config[:knife] : {}
end
@@ -203,7 +205,7 @@ class Chef
#
# @return [String] download version string
def version_to_install
- return knife_config[:bootstrap_version] if knife_config[:bootstrap_version]
+ return @config[:bootstrap_version] if @config[:bootstrap_version]
if @config[:channel] == "stable"
Chef::VERSION.split(".").first
diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb
index 3783bd9d5f..40bd5a48a1 100644
--- a/lib/chef/provider.rb
+++ b/lib/chef/provider.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
-# Copyright:: Copyright 2008-2016, 2009-2020, Chef Software Inc.
+# Copyright:: Copyright (c) Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -81,6 +81,20 @@ class Chef
# Chef.deprecated(:use_inline_resources, "The use_inline_resources mode is no longer optional and the line enabling it can be removed")
end
+ # Use a partial code fragment. This can be used for code sharing between multiple resources.
+ #
+ # Do not wrap the code fragment in a class or module. It also does not support the use of super
+ # to subclass any methods defined in the fragment, the methods will just be overwritten.
+ #
+ # @param partial [String] the code fragment to eval against the class
+ #
+ def self.use(partial)
+ dirname = ::File.dirname(partial)
+ basename = ::File.basename(partial, ".rb")
+ basename = basename[1..-1] if basename.start_with?("_")
+ class_eval IO.read(::File.expand_path("#{dirname}/_#{basename}.rb", ::File.dirname(caller_locations.first.absolute_path)))
+ end
+
# delegate to the resource
#
def_delegators :@new_resource, :property_is_set?
diff --git a/lib/chef/provider/launchd.rb b/lib/chef/provider/launchd.rb
index 3516cadda7..fbb9307712 100644
--- a/lib/chef/provider/launchd.rb
+++ b/lib/chef/provider/launchd.rb
@@ -161,7 +161,7 @@ class Chef
def content
plist_hash = new_resource.plist_hash || gen_hash
- Plist::Emit.dump(plist_hash) unless plist_hash.nil?
+ ::Plist::Emit.dump(plist_hash) unless plist_hash.nil?
end
def gen_hash
diff --git a/lib/chef/provider/osx_profile.rb b/lib/chef/provider/osx_profile.rb
index ba63d4b02a..07d35e633c 100644
--- a/lib/chef/provider/osx_profile.rb
+++ b/lib/chef/provider/osx_profile.rb
@@ -21,6 +21,7 @@ require_relative "../provider"
require_relative "../resource"
require_relative "../resource/file"
require "uuidtools"
+require "plist"
class Chef
class Provider
@@ -232,7 +233,7 @@ class Chef
end
def read_plist(xml_file)
- Plist.parse_xml(xml_file)
+ ::Plist.parse_xml(xml_file)
end
def profile_installed?
diff --git a/lib/chef/provider/user/dscl.rb b/lib/chef/provider/user/dscl.rb
index 687fc021da..a46ecb3a62 100644
--- a/lib/chef/provider/user/dscl.rb
+++ b/lib/chef/provider/user/dscl.rb
@@ -118,7 +118,7 @@ in 'password', with the associated 'salt' and 'iterations'.")
# Calling shell_out directly since we want to give an input stream
shadow_hash_xml = convert_binary_plist_to_xml(shadow_hash_binary.string)
- shadow_hash = Plist.parse_xml(shadow_hash_xml)
+ shadow_hash = ::Plist.parse_xml(shadow_hash_xml)
if shadow_hash["SALTED-SHA512-PBKDF2"] # 10.7+ contains this, but we retain the check in case it goes away in the future
@password_shadow_conversion_algorithm = "SALTED-SHA512-PBKDF2"
@@ -541,7 +541,7 @@ in 'password', with the associated 'salt' and 'iterations'.")
begin
user_plist_file = "#{USER_PLIST_DIRECTORY}/#{new_resource.username}.plist"
user_plist_info = run_plutil("convert", "xml1", "-o", "-", user_plist_file)
- user_info = Plist.parse_xml(user_plist_info)
+ user_info = ::Plist.parse_xml(user_plist_info)
rescue Chef::Exceptions::PlistUtilCommandFailed
end
@@ -554,7 +554,7 @@ in 'password', with the associated 'salt' and 'iterations'.")
#
def save_user_info(user_info)
user_plist_file = "#{USER_PLIST_DIRECTORY}/#{new_resource.username}.plist"
- Plist::Emit.save_plist(user_info, user_plist_file)
+ ::Plist::Emit.save_plist(user_info, user_plist_file)
run_plutil("convert", "binary1", user_plist_file)
end
diff --git a/lib/chef/provider/user/mac.rb b/lib/chef/provider/user/mac.rb
index 312d2a7b47..104cf51abe 100644
--- a/lib/chef/provider/user/mac.rb
+++ b/lib/chef/provider/user/mac.rb
@@ -22,6 +22,7 @@ require_relative "../../mixin/shell_out"
require_relative "../../mixin/which"
require_relative "../user"
require_relative "../../resource/user/mac_user"
+require "plist"
class Chef
class Provider
@@ -79,7 +80,7 @@ class Chef
admin_group_xml = run_dscl("read", "/Groups/admin")
return nil unless admin_group_xml && admin_group_xml != ""
- @admin_group_plist = Plist.new(::Plist.parse_xml(admin_group_xml))
+ @admin_group_plist = ::Plist.new(::Plist.parse_xml(admin_group_xml))
end
def reload_user_plist
@@ -94,7 +95,7 @@ class Chef
return nil if user_xml.nil? || user_xml == ""
- @user_plist = Plist.new(::Plist.parse_xml(user_xml))
+ @user_plist = ::Plist.new(::Plist.parse_xml(user_xml))
return unless user_plist[:shadow_hash]
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index bbbe714f3d..fcf22a36b1 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -1461,6 +1461,20 @@ class Chef
@default_description
end
+ # Use a partial code fragment. This can be used for code sharing between multiple resources.
+ #
+ # Do not wrap the code fragment in a class or module. It also does not support the use of super
+ # to subclass any methods defined in the fragment, the methods will just be overwritten.
+ #
+ # @param partial [String] the code fragment to eval against the class
+ #
+ def self.use(partial)
+ dirname = ::File.dirname(partial)
+ basename = ::File.basename(partial, ".rb")
+ basename = basename[1..-1] if basename.start_with?("_")
+ class_eval IO.read(::File.expand_path("#{dirname}/_#{basename}.rb", ::File.dirname(caller_locations.first.absolute_path)))
+ end
+
# The cookbook in which this Resource was defined (if any).
#
# @return Chef::CookbookVersion The cookbook in which this Resource was defined.
diff --git a/lib/chef/resource/build_essential.rb b/lib/chef/resource/build_essential.rb
index 5a41f3895b..ab1be3bcfd 100644
--- a/lib/chef/resource/build_essential.rb
+++ b/lib/chef/resource/build_essential.rb
@@ -161,7 +161,7 @@ class Chef
#
# @return [true, false]
def xcode_cli_installed?
- packages = Plist.parse_xml(::File.open("/Library/Receipts/InstallHistory.plist", "r"))
+ packages = ::Plist.parse_xml(::File.open("/Library/Receipts/InstallHistory.plist", "r"))
packages.select! { |package| package["displayName"].match? "Command Line Tools" }
!packages.empty?
end
diff --git a/lib/chef/resource/chef_client_cron.rb b/lib/chef/resource/chef_client_cron.rb
index fb30bd0538..681327bcd3 100644
--- a/lib/chef/resource/chef_client_cron.rb
+++ b/lib/chef/resource/chef_client_cron.rb
@@ -52,6 +52,13 @@ class Chef
extend Chef::ResourceHelpers::CronValidations
+ property :job_name, String,
+ default: Chef::Dist::CLIENT,
+ description: "The name of the cron job to create."
+
+ property :comment, String,
+ description: "A comment to place in the cron.d file."
+
property :user, String,
description: "The name of the user that #{Chef::Dist::PRODUCT} runs as.",
default: "root"
@@ -86,29 +93,18 @@ class Chef
"should be a valid weekday spec" => method(:validate_dow),
}
- property :mailto, String,
- description: "The e-mail address to e-mail any cron task failures to."
-
- property :accept_chef_license, [true, false],
- description: "Accept the Chef Online Master License and Services Agreement. See https://www.chef.io/online-master-agreement/",
- default: false
-
- property :job_name, String,
- default: Chef::Dist::CLIENT,
- description: "The name of the cron job to create."
-
property :splay, [Integer, String],
default: 300,
coerce: proc { |x| Integer(x) },
callbacks: { "should be a positive number" => proc { |v| v > 0 } },
description: "A random number of seconds between 0 and X to add to interval so that all #{Chef::Dist::CLIENT} commands don't execute at the same time."
- property :environment, Hash,
- default: lazy { {} },
- description: "A Hash containing additional arbitrary environment variables under which the cron job will be run in the form of ``({'ENV_VARIABLE' => 'VALUE'})``."
+ property :mailto, String,
+ description: "The e-mail address to e-mail any cron task failures to."
- property :comment, String,
- description: "A comment to place in the cron.d file."
+ property :accept_chef_license, [true, false],
+ description: "Accept the Chef Online Master License and Services Agreement. See https://www.chef.io/online-master-agreement/",
+ default: false
property :config_directory, String,
default: Chef::Dist::CONF_DIR,
@@ -134,6 +130,10 @@ class Chef
default: lazy { [] },
description: "An array of options to pass to the #{Chef::Dist::CLIENT} command."
+ property :environment, Hash,
+ default: lazy { {} },
+ description: "A Hash containing additional arbitrary environment variables under which the cron job will be run in the form of ``({'ENV_VARIABLE' => 'VALUE'})``."
+
action :add do
# TODO: Replace this with a :create_if_missing action on directory when that exists
unless ::Dir.exist?(new_resource.log_directory)
@@ -144,8 +144,8 @@ class Chef
end
end
- cron_d new_resource.job_name do
- minute new_resource.minute
+ declare_resource(cron_resource_type, new_resource.job_name) do
+ minute new_resource.minute
hour new_resource.hour
day new_resource.day
weekday new_resource.weekday
@@ -207,6 +207,17 @@ class Chef
"> #{::File.join(new_resource.log_directory, new_resource.log_file_name)} 2>&1"
end
end
+
+ #
+ # The type of cron resource to run. Linux systems all support the /etc/cron.d directory
+ # and can use the cron_d resource, but Solaris / AIX / FreeBSD need to use the crontab
+ # via the legacy cron resource.
+ #
+ # @return [Symbol]
+ #
+ def cron_resource_type
+ linux? ? :cron_d : :cron
+ end
end
end
end
diff --git a/lib/chef/resource/chef_client_scheduled_task.rb b/lib/chef/resource/chef_client_scheduled_task.rb
index c4d2bc97c6..3d9deb6ca3 100644
--- a/lib/chef/resource/chef_client_scheduled_task.rb
+++ b/lib/chef/resource/chef_client_scheduled_task.rb
@@ -49,6 +49,10 @@ class Chef
resource_name :chef_client_scheduled_task
+ property :task_name, String,
+ description: "The name of the scheduled task to create.",
+ default: Chef::Dist::CLIENT
+
property :user, String,
description: "The name of the user that #{Chef::Dist::PRODUCT} runs as.",
default: "System", sensitive: true
@@ -109,10 +113,6 @@ class Chef
description: "An array of options to pass to the #{Chef::Dist::CLIENT} command.",
default: lazy { [] }
- property :task_name, String,
- description: "The name of the scheduled task to create.",
- default: Chef::Dist::CLIENT
-
action :add do
# TODO: Replace this with a :create_if_missing action on directory when that exists
unless Dir.exist?(new_resource.log_directory)
diff --git a/lib/chef/resource/chef_client_systemd_timer.rb b/lib/chef/resource/chef_client_systemd_timer.rb
new file mode 100644
index 0000000000..359fe951a0
--- /dev/null
+++ b/lib/chef/resource/chef_client_systemd_timer.rb
@@ -0,0 +1,177 @@
+#
+# Copyright:: 2020, 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.
+# 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 "../resource"
+require_relative "../dist"
+
+class Chef
+ class Resource
+ class ChefClientSystemdTimer < Chef::Resource
+ unified_mode true
+
+ provides :chef_client_systemd_timer
+
+ description "Use the chef_client_systemd_timer resource to setup the #{Chef::Dist::PRODUCT} to run as a systemd timer."
+ introduced "16.0"
+ examples <<~DOC
+ Setup #{Chef::Dist::PRODUCT} to run using the default 30 minute cadence
+ ```ruby
+ chef_client_systemd_timer "Run chef-client as a systemd timer"
+ ```
+
+ Run #{Chef::Dist::PRODUCT} every 1 hour
+ ```ruby
+ chef_client_systemd_timer "Run chef-client every 1 hour" do
+ interval "1hr"
+ end
+ ```
+
+ Run #{Chef::Dist::PRODUCT} with extra options passed to the client
+ ```ruby
+ chef_client_systemd_timer "Run an override recipe" do
+ daemon_options ["--override-runlist mycorp_base::default"]
+ end
+ ```
+ DOC
+
+ property :job_name, String,
+ description: "The name of the system timer to create.",
+ default: Chef::Dist::CLIENT
+
+ property :description, String,
+ description: "The description to add to the systemd timer. This will be displayed when running `systemctl status` for the timer.",
+ default: "#{Chef::Dist::PRODUCT} periodic execution"
+
+ property :user, String,
+ description: "The name of the user that #{Chef::Dist::PRODUCT} runs as.",
+ default: "root"
+
+ property :delay_after_boot, String,
+ description: "The time to wait after booting before the interval starts. This is expressed as a systemd time span such as `300seconds`, `1hr`, or `1m`. See <https://www.freedesktop.org/software/systemd/man/systemd.time.html> for a complete list of allowed time span values.",
+ default: "1min"
+
+ property :interval, String,
+ description: "The interval to wait between executions. This is expressed as a systemd time span such as `300seconds`, `1hr`, or `1m`. See <https://www.freedesktop.org/software/systemd/man/systemd.time.html> for a complete list of allowed time span values.",
+ default: "30min"
+
+ property :splay, String,
+ description: "A interval between 0 and X to add to the interval so that all #{Chef::Dist::CLIENT} commands don't execute at the same time. This is expressed as a systemd time span such as `300seconds`, `1hr`, or `1m`. See <https://www.freedesktop.org/software/systemd/man/systemd.time.html> for a complete list of allowed time span values.",
+ default: "5min"
+
+ property :accept_chef_license, [true, false],
+ description: "Accept the Chef Online Master License and Services Agreement. See https://www.chef.io/online-master-agreement/",
+ default: false
+
+ property :run_on_battery, [true, false],
+ description: "Run the timer for #{Chef::Dist::PRODUCT} if the system is on battery.",
+ default: true
+
+ property :config_directory, String,
+ description: "The path of the config directory.",
+ default: Chef::Dist::CONF_DIR
+
+ property :chef_binary_path, String,
+ description: "The path to the #{Chef::Dist::CLIENT} binary.",
+ default: "/opt/#{Chef::Dist::DIR_SUFFIX}/bin/#{Chef::Dist::CLIENT}"
+
+ property :daemon_options, Array,
+ description: "An array of options to pass to the #{Chef::Dist::CLIENT} command.",
+ default: lazy { [] }
+
+ property :environment, Hash,
+ description: "A Hash containing additional arbitrary environment variables under which the systemd timer will be run in the form of ``({'ENV_VARIABLE' => 'VALUE'})``.",
+ default: lazy { {} }
+
+ action :add do
+ systemd_unit "#{new_resource.job_name}.service" do
+ content service_content
+ action :create
+ end
+
+ systemd_unit "#{new_resource.job_name}.timer" do
+ content timer_content
+ action %i{create enable start}
+ end
+ end
+
+ action :remove do
+ systemd_unit "#{new_resource.job_name}.service" do
+ action :remove
+ end
+
+ systemd_unit "#{new_resource.job_name}.timer" do
+ action :remove
+ end
+ end
+
+ action_class do
+ #
+ # The chef-client command to run in the systemd unit.
+ #
+ # @return [String]
+ #
+ def chef_client_cmd
+ cmd = "#{new_resource.chef_binary_path}"
+ cmd << " #{new_resource.daemon_options.join(" ")}" unless new_resource.daemon_options.empty?
+ cmd << " --chef-license accept" if new_resource.accept_chef_license
+ cmd << " -c #{::File.join(new_resource.config_directory, "client.rb")}"
+ cmd
+ end
+
+ #
+ # The timer content to pass to the systemd_unit
+ #
+ # @return [Hash]
+ #
+ def timer_content
+ {
+ "Unit" => { "Description" => new_resource.description },
+ "Timer" => {
+ "OnBootSec" => new_resource.delay_after_boot,
+ "OnUnitActiveSec" => new_resource.interval,
+ "RandomizedDelaySec" => new_resource.splay,
+ },
+ "Install" => { "WantedBy" => "timers.target" },
+ }
+ end
+
+ #
+ # The service content to pass to the systemd_unit
+ #
+ # @return [Hash]
+ #
+ def service_content
+ unit = {
+ "Unit" => {
+ "Description" => new_resource.description,
+ "After" => "network.target auditd.service",
+ },
+ "Service" => {
+ "Type" => "oneshot",
+ "ExecStart" => chef_client_cmd,
+ "SuccessExitStatus" => [3, 213, 35, 37, 41],
+ },
+ "Install" => { "WantedBy" => "multi-user.target" },
+ }
+
+ unit["Service"]["ConditionACPower"] = "true" unless new_resource.run_on_battery
+ unit["Service"]["Environment"] = new_resource.environment.collect { |k, v| "\"#{k}=#{v}\"" } unless new_resource.environment.empty?
+ unit
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/plist.rb b/lib/chef/resource/plist.rb
new file mode 100644
index 0000000000..d5d2ce3c6c
--- /dev/null
+++ b/lib/chef/resource/plist.rb
@@ -0,0 +1,207 @@
+#
+# Copyright:: Copyright 2017-2020, Microsoft Corporation
+# Copyright:: Copyright 2020, 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 "../resource"
+require "plist"
+
+class Chef
+ class Resource
+
+ class PlistResource < Chef::Resource # we name this PlistResource to avoid confusion with Plist from the plist gem
+ unified_mode true
+
+ provides :plist
+
+ description "Use the plist resource to set config values in plist files on macOS systems."
+ introduced "16.0"
+
+ property :path, String, name_property: true
+ property :entry, String
+ property :value, [TrueClass, FalseClass, String, Integer, Float, Hash]
+ property :encoding, String, default: "binary"
+ property :owner, String, default: "root"
+ property :group, String, default: "wheel"
+ property :mode, [String, Integer]
+
+ PLISTBUDDY_EXECUTABLE = "/usr/libexec/PlistBuddy".freeze
+ DEFAULTS_EXECUTABLE = "/usr/bin/defaults".freeze
+ PLUTIL_EXECUTABLE = "/usr/bin/plutil".freeze
+ PLUTIL_FORMAT_MAP = { "us-ascii" => "xml1",
+ "text/xml" => "xml1",
+ "utf-8" => "xml1",
+ "binary" => "binary1" }.freeze
+
+ load_current_value do |desired|
+ current_value_does_not_exist! unless ::File.exist? desired.path
+ entry desired.entry if entry_in_plist? desired.entry, desired.path
+
+ setting = setting_from_plist desired.entry, desired.path
+ value convert_to_data_type_from_string(setting[:key_type], setting[:key_value])
+
+ file_type_cmd = shell_out "/usr/bin/file", "--brief", "--mime-encoding", "--preserve-date", desired.path
+ encoding file_type_cmd.stdout.chomp
+
+ file_owner_cmd = shell_out("/usr/bin/stat", "-f", "%Su", desired.path)
+ owner file_owner_cmd.stdout.chomp
+
+ file_group_cmd = shell_out("/usr/bin/stat", "-f", "%Sg", desired.path)
+ group file_group_cmd.stdout.chomp
+ end
+
+ action :set do
+ converge_if_changed :path do
+ converge_by "create new plist: '#{new_resource.path}'" do
+ file new_resource.path do
+ content {}.to_plist
+ owner new_resource.owner
+ group new_resource.group
+ mode new_resource.mode if property_is_set?(:mode)
+ end
+ end
+ end
+
+ plist_file_name = ::File.basename(new_resource.path)
+
+ converge_if_changed :entry do
+ converge_by "add entry \"#{new_resource.entry}\" to #{plist_file_name}" do
+ shell_out!(plistbuddy_command(:add, new_resource.entry, new_resource.path, new_resource.value))
+ end
+ end
+
+ converge_if_changed :value do
+ converge_by "#{plist_file_name}: set #{new_resource.entry} to #{new_resource.value}" do
+ shell_out!(plistbuddy_command(:set, new_resource.entry, new_resource.path, new_resource.value))
+ end
+ end
+
+ converge_if_changed :encoding do
+ converge_by "change format" do
+ unless PLUTIL_FORMAT_MAP.key?(new_resource.encoding)
+ Chef::Application.fatal!(
+ "Option encoding must be equal to one of: #{PLUTIL_FORMAT_MAP.keys}! You passed \"#{new_resource.encoding}\"."
+ )
+ end
+ shell_out!(PLUTIL_EXECUTABLE, "-convert", PLUTIL_FORMAT_MAP[new_resource.encoding], new_resource.path)
+ end
+ end
+
+ converge_if_changed :owner do
+ converge_by "update owner to #{new_resource.owner}" do
+ file new_resource.path do
+ owner new_resource.owner
+ end
+ end
+ end
+
+ converge_if_changed :group do
+ converge_by "update group to #{new_resource.group}" do
+ file new_resource.path do
+ group new_resource.group
+ end
+ end
+ end
+ end
+
+ ### Question: Should I refactor these methods into an action_class?
+ ### Answer: NO
+ ### Why: We need them in both the action and in load_current_value. If you put them in the
+ ### action class then they're only in the Provider class and are not available to load_current_value
+
+ def convert_to_data_type_from_string(type, value)
+ case type
+ when "boolean"
+ # Since we've determined this is a boolean data type, we can assume that:
+ # If the value as an int is 1, return true
+ # If the value as an int is 0 (not 1), return false
+ value.to_i == 1
+ when "integer"
+ value.to_i
+ when "float"
+ value.to_f
+ when "string"
+ value
+ when "dictionary"
+ value
+ when nil
+ ""
+ else
+ raise "Unknown or unsupported data type: #{type.class}"
+ end
+ end
+
+ def type_to_commandline_string(value)
+ case value
+ when Array
+ "array"
+ when Integer
+ "integer"
+ when FalseClass
+ "bool"
+ when TrueClass
+ "bool"
+ when Hash
+ "dict"
+ when String
+ "string"
+ when Float
+ "float"
+ else
+ raise "Unknown or unsupported data type: #{value} of #{value.class}"
+ end
+ end
+
+ def entry_in_plist?(entry, path)
+ print_entry = plistbuddy_command :print, entry, path
+ cmd = shell_out print_entry
+ cmd.exitstatus == 0
+ end
+
+ def plistbuddy_command(subcommand, entry, path, value = nil)
+ sep = " "
+ arg = case subcommand.to_s
+ when "add"
+ type_to_commandline_string(value)
+ when "set"
+ if value.is_a?(Hash)
+ sep = ":"
+ value.map { |k, v| "#{k} #{v}" }
+ else
+ value
+ end
+ else
+ ""
+ end
+ entry_with_arg = ["\"#{entry}\"", arg].join(sep).strip
+ subcommand = "#{subcommand.capitalize} :#{entry_with_arg}"
+ [PLISTBUDDY_EXECUTABLE, "-c", "\'#{subcommand}\'", "\"#{path}\""].join(" ")
+ end
+
+ def setting_from_plist(entry, path)
+ defaults_read_type_output = shell_out(DEFAULTS_EXECUTABLE, "read-type", path, entry).stdout
+ data_type = defaults_read_type_output.split.last
+
+ if value.class == Hash
+ plutil_output = shell_out(PLUTIL_EXECUTABLE, "-extract", entry, "xml1", "-o", "-", path).stdout.chomp
+ { key_type: data_type, key_value: ::Plist.parse_xml(plutil_output) }
+ else
+ defaults_read_output = shell_out(DEFAULTS_EXECUTABLE, "read", path, entry).stdout
+ { key_type: data_type, key_value: defaults_read_output.strip }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/sysctl.rb b/lib/chef/resource/sysctl.rb
index 240f45e60f..82dbe61081 100644
--- a/lib/chef/resource/sysctl.rb
+++ b/lib/chef/resource/sysctl.rb
@@ -57,7 +57,6 @@ class Chef
def after_created
raise "The sysctl resource requires Linux as it needs sysctl and the sysctl.d directory functionality." unless node["os"] == "linux"
- raise "The sysctl resource does not support SLES releases less than 12 as it requires a sysctl.d directory" if platform_family?("suse") && node["platform_version"].to_i < 12
end
def coerce_value(v)
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index 66bec89658..c7191ef69f 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -29,6 +29,7 @@ require_relative "resource/build_essential"
require_relative "resource/cookbook_file"
require_relative "resource/chef_client_cron"
require_relative "resource/chef_client_scheduled_task"
+require_relative "resource/chef_client_systemd_timer"
require_relative "resource/chef_gem"
require_relative "resource/chef_handler"
require_relative "resource/chef_sleep"
@@ -86,6 +87,7 @@ require_relative "resource/package"
require_relative "resource/pacman_package"
require_relative "resource/paludis_package"
require_relative "resource/perl"
+require_relative "resource/plist"
require_relative "resource/portage_package"
require_relative "resource/powershell_package_source"
require_relative "resource/powershell_script"
diff --git a/lib/chef/run_context/cookbook_compiler.rb b/lib/chef/run_context/cookbook_compiler.rb
index 4dda6aeb2e..36ee34c62e 100644
--- a/lib/chef/run_context/cookbook_compiler.rb
+++ b/lib/chef/run_context/cookbook_compiler.rb
@@ -245,11 +245,13 @@ class Chef
def load_lwrps_from_cookbook(cookbook_name)
files_in_cookbook_by_segment(cookbook_name, :providers).each do |filename|
next unless File.extname(filename) == ".rb"
+ next if File.basename(filename).match?(/^_/)
load_lwrp_provider(cookbook_name, filename)
end
files_in_cookbook_by_segment(cookbook_name, :resources).each do |filename|
next unless File.extname(filename) == ".rb"
+ next if File.basename(filename).match?(/^_/)
load_lwrp_resource(cookbook_name, filename)
end
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index c2477c32c9..40001c4dba 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("../..", __FILE__)
- VERSION = Chef::VersionString.new("16.0.194")
+ VERSION = Chef::VersionString.new("16.0.203")
end
#
diff --git a/omnibus/omnibus-test.sh b/omnibus/omnibus-test.sh
index 0499d03b0b..2a3b6e520e 100644
--- a/omnibus/omnibus-test.sh
+++ b/omnibus/omnibus-test.sh
@@ -131,7 +131,7 @@ FORCE_FFI_YAJL=ext
export FORCE_FFI_YAJL
# chef-shell smoke tests require "rb-readline" which requires "infocmp"
-# most platforms provide "infocmp" by default via an "ncurses" package but SLES 11 and 12 provide it via "ncurses-devel" which
+# most platforms provide "infocmp" by default via an "ncurses" package but SLES 12 provide it via "ncurses-devel" which
# isn't typically installed. omnibus-toolchain has "infocmp" built-in so we add omnibus-toolchain to the PATH to ensure
# tests will function properly.
PATH="/opt/$TOOLCHAIN/bin:/usr/local/bin:/opt/$TOOLCHAIN/embedded/bin:$PATH"
diff --git a/spec/functional/assets/inittest b/spec/functional/assets/inittest
index dc542a965a..3284d27a1e 100644
--- a/spec/functional/assets/inittest
+++ b/spec/functional/assets/inittest
@@ -2,16 +2,17 @@
TMPDIR="${TMPDIR:-/tmp}"
-function create_chef_txt {
- touch $TMPDIR/inittest.txt
+create_chef_txt() {
+ touch "$TMPDIR"/inittest.txt
}
-function delete_chef_txt {
- rm $TMPDIR/inittest.txt
+
+delete_chef_txt() {
+ rm "$TMPDIR"/inittest.txt
}
-function rename_chef_txt {
- mv $TMPDIR/inittest.txt $TMPDIR/$1
+rename_chef_txt() {
+ mv "$TMPDIR"/inittest.txt "$TMPDIR"/"$1"
}
case "$1" in
@@ -22,7 +23,7 @@ stop )
delete_chef_txt
;;
status )
- [ -f $TMPDIR/inittest.txt ] || [ -f $TMPDIR/inittest_reload.txt ] || [ -f $TMPDIR/inittest_restart.txt ]
+ [ -f "$TMPDIR"/inittest.txt ] || [ -f "$TMPDIR"/inittest_reload.txt ] || [ -f "$TMPDIR"/inittest_restart.txt ]
;;
reload )
rename_chef_txt "inittest_reload.txt"
diff --git a/spec/functional/resource/insserv_spec.rb b/spec/functional/resource/insserv_spec.rb
index 55a803d431..1af33b434b 100644
--- a/spec/functional/resource/insserv_spec.rb
+++ b/spec/functional/resource/insserv_spec.rb
@@ -22,7 +22,7 @@ require "functional/resource/base"
require "chef/mixin/shell_out"
require "fileutils"
-describe Chef::Resource::Service, :requires_root, :sles11 do
+describe Chef::Resource::Service, :requires_root, :opensuse do
include Chef::Mixin::ShellOut
diff --git a/spec/integration/recipes/notifies_spec.rb b/spec/integration/recipes/notifies_spec.rb
index 6d781922f5..9767cf5de7 100644
--- a/spec/integration/recipes/notifies_spec.rb
+++ b/spec/integration/recipes/notifies_spec.rb
@@ -1,3 +1,19 @@
+#
+# Copyright:: Copyright 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 "support/shared/integration/integration_helper"
require "chef/mixin/shell_out"
diff --git a/spec/integration/recipes/use_partial_spec.rb b/spec/integration/recipes/use_partial_spec.rb
new file mode 100644
index 0000000000..b8e8a27635
--- /dev/null
+++ b/spec/integration/recipes/use_partial_spec.rb
@@ -0,0 +1,112 @@
+#
+# Copyright:: Copyright 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 "support/shared/integration/integration_helper"
+require "chef/mixin/shell_out"
+
+describe "notifying_block" do
+ include IntegrationSupport
+ include Chef::Mixin::ShellOut
+
+ let(:chef_dir) { File.expand_path("../../../../bin", __FILE__) }
+ let(:chef_client) { "bundle exec chef-client --minimal-ohai" }
+
+ when_the_repository "has a cookbook with partial resources" do
+ before do
+ directory "cookbooks/x" do
+ file "resources/_shared_properties.rb", <<-EOM
+ property :content, String
+ EOM
+ file "resources/_action_helpers.rb", <<-EOM
+ def printit(string)
+ puts "DIDIT: \#{string}"
+ end
+ EOM
+ file "resources/thing.rb", <<-EOM
+ provides :thing
+ use "shared_properties"
+ action_class do
+ use "action_helpers"
+ end
+ action :run do
+ printit(new_resource.content)
+ end
+ EOM
+ file "recipes/default.rb", <<~EOM
+ thing "whatever" do
+ content "stuff"
+ end
+ EOM
+ end
+ file "config/client.rb", <<-EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ always_dump_stacktrace true
+ EOM
+ end
+
+ it "should run cleanly and print the output" do
+ 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(/DIDIT: stuff/)
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with partial resources done differently" do
+ before do
+ directory "cookbooks/x" do
+ file "partials/_shared_properties.rb", <<-EOM
+ property :content, String
+ EOM
+ file "partials/_action_partials.rb", <<-EOM
+ def printit(string)
+ puts "DIDIT: \#{string}"
+ end
+ EOM
+ # this tests relative pathing, including the underscore and including the trailing .rb all work
+ file "resources/thing.rb", <<-EOM
+ provides :thing
+ use "../partials/_shared_properties.rb"
+ action_class do
+ use "../partials/_action_partials.rb"
+ end
+ action :run do
+ printit(new_resource.content)
+ end
+ EOM
+ file "recipes/default.rb", <<~EOM
+ thing "whatever" do
+ content "stuff"
+ end
+ EOM
+ end
+ file "config/client.rb", <<-EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ always_dump_stacktrace true
+ EOM
+ end
+
+ it "should run cleanly and print the output" do
+ 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(/DIDIT: stuff/)
+ result.error!
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 49e8d2f8f5..c6fd27d271 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -169,7 +169,7 @@ RSpec.configure do |config|
config.filter_run_excluding linux_only: true unless linux?
config.filter_run_excluding aix_only: true unless aix?
config.filter_run_excluding suse_only: true unless suse?
- config.filter_run_excluding sles11: true unless sles11?
+ config.filter_run_excluding opensuse: true unless opensuse?
config.filter_run_excluding debian_family_only: true unless debian_family?
config.filter_run_excluding supports_cloexec: true unless supports_cloexec?
config.filter_run_excluding selinux_only: true unless selinux_enabled?
diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb
index e92da37043..0e98fce621 100644
--- a/spec/support/platform_helpers.rb
+++ b/spec/support/platform_helpers.rb
@@ -174,8 +174,8 @@ def rhel6?
rhel? && !!(ohai[:platform_version].to_i == 6)
end
-def sles11?
- suse? && !!(ohai[:platform_version].to_i == 11)
+def opensuse?
+ suse? && !!(ohai[:platform_version].to_i >= 15)
end
def rhel7?
diff --git a/spec/unit/knife/core/bootstrap_context_spec.rb b/spec/unit/knife/core/bootstrap_context_spec.rb
index 99035eff4e..7ddb981aba 100644
--- a/spec/unit/knife/core/bootstrap_context_spec.rb
+++ b/spec/unit/knife/core/bootstrap_context_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2011-2016, Chef Software Inc.
+# Copyright:: Copyright 2011-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -297,7 +297,7 @@ describe Chef::Knife::Core::BootstrapContext do
describe "#version_to_install" do
context "when bootstrap_version is provided" do
- let(:chef_config) { { knife: { bootstrap_version: "awesome" } } }
+ let(:config) { { bootstrap_version: "awesome" } }
it "returns bootstrap_version" do
expect(bootstrap_context.version_to_install).to eq "awesome"
diff --git a/spec/unit/resource/chef_client_systemd_timer_spec.rb b/spec/unit/resource/chef_client_systemd_timer_spec.rb
new file mode 100644
index 0000000000..139d4c6ba3
--- /dev/null
+++ b/spec/unit/resource/chef_client_systemd_timer_spec.rb
@@ -0,0 +1,70 @@
+#
+# Author:: Tim Smith (<tsmith@chef.io>)
+# Copyright:: 2020, 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"
+
+describe Chef::Resource::ChefClientSystemdTimer do
+ let(:node) { Chef::Node.new }
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:resource) { Chef::Resource::ChefClientSystemdTimer.new("fakey_fakerton", run_context) }
+ let(:provider) { resource.provider_for_action(:add) }
+
+ it "sets the default action as :add" do
+ expect(resource.action).to eql([:add])
+ end
+
+ it "user defaults to root" do
+ expect(resource.user).to eql("root")
+ end
+
+ it "builds a default value for chef_binary_path dist values" do
+ expect(resource.chef_binary_path).to eql("/opt/chef/bin/chef-client")
+ end
+
+ it "supports :add and :remove actions" do
+ expect { resource.action :add }.not_to raise_error
+ expect { resource.action :remove }.not_to raise_error
+ end
+
+ describe "#chef_client_cmd" do
+ it "creates a valid command if using all default properties" do
+ expect(provider.chef_client_cmd).to eql("/opt/chef/bin/chef-client -c /etc/chef/client.rb")
+ end
+
+ it "uses daemon_options if set" do
+ resource.daemon_options ["--foo 1", "--bar 2"]
+ expect(provider.chef_client_cmd).to eql("/opt/chef/bin/chef-client --foo 1 --bar 2 -c /etc/chef/client.rb")
+ end
+
+ it "uses custom config dir if set" do
+ resource.config_directory "/etc/some_other_dir"
+ expect(provider.chef_client_cmd).to eql("/opt/chef/bin/chef-client -c /etc/some_other_dir/client.rb")
+ end
+
+ it "uses custom chef-client binary if set" do
+ resource.chef_binary_path "/usr/local/bin/chef-client"
+ expect(provider.chef_client_cmd).to eql("/usr/local/bin/chef-client -c /etc/chef/client.rb")
+ end
+
+ it "sets the license acceptance flag if set" do
+ resource.accept_chef_license true
+ expect(provider.chef_client_cmd).to eql("/opt/chef/bin/chef-client --chef-license accept -c /etc/chef/client.rb")
+ end
+ end
+end
diff --git a/spec/unit/resource/plist_spec.rb b/spec/unit/resource/plist_spec.rb
new file mode 100644
index 0000000000..ab5b35b6c3
--- /dev/null
+++ b/spec/unit/resource/plist_spec.rb
@@ -0,0 +1,130 @@
+#
+# Author:: Tim Smith (<tsmith@chef.io>)
+# Copyright:: 2020, Chef Software Inc.
+# Copyright:: 2017-2020, Microsoft Corporation
+# 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"
+
+describe Chef::Resource::PlistResource do
+ let(:resource) { Chef::Resource::PlistResource.new("fakey_fakerton") }
+
+ it "sets the default action as :set" do
+ expect(resource.action).to eql([:set])
+ end
+
+ it "path is the name property" do
+ expect(resource.path).to eql("fakey_fakerton")
+ end
+
+ describe "#plistbuddy_command" do
+ it "the bool arguments contain the data type" do
+ expect(resource.plistbuddy_command(:add, "FooEntry", "path/to/file.plist", true)).to eq "/usr/libexec/PlistBuddy -c 'Add :\"FooEntry\" bool' \"path/to/file.plist\""
+ end
+
+ it "the add command only adds the data type" do
+ expect(resource.plistbuddy_command(:add, "QuuxEntry", "path/to/file.plist", 50)).to eq "/usr/libexec/PlistBuddy -c 'Add :\"QuuxEntry\" integer' \"path/to/file.plist\""
+ end
+
+ it "the delete command is formatted properly" do
+ expect(resource.plistbuddy_command(:delete, "BarEntry", "path/to/file.plist")).to eq "/usr/libexec/PlistBuddy -c 'Delete :\"BarEntry\"' \"path/to/file.plist\""
+ end
+
+ it "the set command is formatted properly" do
+ expect(resource.plistbuddy_command(:set, "BazEntry", "path/to/file.plist", false)).to eq "/usr/libexec/PlistBuddy -c 'Set :\"BazEntry\" false' \"path/to/file.plist\""
+ end
+
+ it "the print command is formatted properly" do
+ expect(resource.plistbuddy_command(:print, "QuxEntry", "path/to/file.plist")).to eq "/usr/libexec/PlistBuddy -c 'Print :\"QuxEntry\"' \"path/to/file.plist\""
+ end
+
+ it "the command to set a dictionary data type is formatted properly" do
+ expect(resource.plistbuddy_command(:set, "AppleFirstWeekday", "path/to/file.plist", gregorian: 4)).to eq "/usr/libexec/PlistBuddy -c 'Set :\"AppleFirstWeekday\":gregorian 4' \"path/to/file.plist\""
+ end
+
+ it "returns the value properly formatted with double quotes when the value has spaces" do
+ expect(resource.plistbuddy_command(:print, "Foo Bar Baz", "path/to/file.plist")).to eq "/usr/libexec/PlistBuddy -c 'Print :\"Foo Bar Baz\"' \"path/to/file.plist\""
+ end
+
+ it "returns the value properly formatted with double quotes when The value to be added contains spaces" do
+ expect(resource.plistbuddy_command(:add, "Foo Bar Baz", "path/to/file.plist", true)).to eq "/usr/libexec/PlistBuddy -c 'Add :\"Foo Bar Baz\" bool' \"path/to/file.plist\""
+ end
+
+ it "returns the value properly formatted with double quotes when the plist itself contains spaces" do
+ expect(resource.plistbuddy_command(:print, "Foo Bar Baz", "Library/Preferences/com.parallels.Parallels Desktop.plist")).to eq "/usr/libexec/PlistBuddy -c 'Print :\"Foo Bar Baz\"' \"Library/Preferences/com.parallels.Parallels Desktop.plist\""
+ end
+ end
+
+ describe "#convert_to_data_type_from_string" do
+ it "returns true if entry is 1 and the type is boolean" do
+ expect(resource.convert_to_data_type_from_string("boolean", "1")).to eq true
+ end
+
+ it "returns false if entry is 0 and the type is boolean" do
+ expect(resource.convert_to_data_type_from_string("boolean", "0")).to eq false
+ end
+
+ it "returns the value as an integer when the type is integer and the value is 1" do
+ expect(resource.convert_to_data_type_from_string("integer", "1")).to eq 1
+ end
+
+ it "returns the value as an integer when the type is integer and the value is 0" do
+ expect(resource.convert_to_data_type_from_string("integer", "0")).to eq 0
+ end
+
+ it "returns the correct value as an integer when the type is integer and the value is 950224" do
+ expect(resource.convert_to_data_type_from_string("integer", "950224")).to eq 950224
+ end
+
+ it "returns the correct value still as a string when the type is string and the value is also a string" do
+ expect(resource.convert_to_data_type_from_string("string", "corge")).to eq "corge"
+ end
+
+ it "returns the correct value as a float when the type is float and the value is 3.14159265359" do
+ expect(resource.convert_to_data_type_from_string("float", "3.14159265359")).to eq 3.14159265359
+ end
+
+ it "returns an empty string when the type nor the value is given" do
+ expect(resource.convert_to_data_type_from_string(nil, "")).to eq ""
+ end
+ end
+
+ describe "#type_to_commandline_string" do
+ it "returns the required boolean entry type as a string" do
+ expect(resource.type_to_commandline_string(true)).to eq "bool"
+ end
+
+ it "returns the required array entry type as a string" do
+ expect(resource.type_to_commandline_string(%w{foo bar})).to eq "array"
+ end
+
+ it "returns the required dictionary entry type as a string" do
+ expect(resource.type_to_commandline_string("baz" => "qux")).to eq "dict"
+ end
+
+ it "returns the required string entry type as a string" do
+ expect(resource.type_to_commandline_string("quux")).to eq "string"
+ end
+
+ it "returns the required integer entry type as a string" do
+ expect(resource.type_to_commandline_string(1)).to eq "integer"
+ end
+
+ it "returns the required float entry type as a string" do
+ expect(resource.type_to_commandline_string(1.0)).to eq "float"
+ end
+ end
+end