diff options
225 files changed, 1319 insertions, 448 deletions
diff --git a/.gitignore b/.gitignore index ddd269bd56..732589b2e3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ tags # You should check in your Gemfile.lock in applications, and not in gems # This also matches Berksfile.lock +Gemfile.lock +Berksfile.lock external_tests/*.lock acceptance/Gemfile.lock omnibus/Gemfile.lock diff --git a/.travis.yml b/.travis.yml index ea58b9b8d2..5504f4aa21 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,7 +68,6 @@ matrix: env: "GEMFILE_MOD=\"gem 'foodcritic', github: 'acrmp/foodcritic', branch: 'v5.0.0'\"" script: bundle exec rake foodcritic_spec - rvm: 2.2 - before_install: env: "GEMFILE_MOD=\"gem 'halite', github: 'poise/halite'\"" script: bundle exec rake halite_spec - rvm: 2.2 @@ -78,6 +77,8 @@ matrix: - rvm: 2.2 gemfile: kitchen-tests/Gemfile before_install: + - gem update --system + - gem install bundler - echo -n $DO_KEY_CHUNK_{0..30} >> ~/.ssh/id_aws.base64 - cat ~/.ssh/id_aws.base64 | tr -d ' ' | base64 --decode > ~/.ssh/id_aws.pem before_script: @@ -128,6 +129,7 @@ matrix: sudo: required dist: trusty before_install: + - gem update --system - gem install bundler - sudo apt-get update - sudo apt-get -y install squid3 git curl @@ -145,6 +147,10 @@ matrix: allow_failures: - rvm: rbx + - rvm: 2.2 + env: "GEMFILE_MOD=\"gem 'halite', github: 'poise/halite'\"" + script: bundle exec rake halite_spec + notifications: on_change: true on_failure: true diff --git a/CHANGELOG.md b/CHANGELOG.md index f2068a9b3c..2e39a2af49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,28 +1,33 @@ # Change Log -## [12.8.0](https://github.com/chef/chef/tree/12.8.0) (2016-03-02) -[Full Changelog](https://github.com/chef/chef/compare/12.7.2...12.8.0) +## [12.8.1](https://github.com/chef/chef/tree/12.8.1) (2016-03-07) +[Full Changelog](https://github.com/chef/chef/compare/12.7.2...12.8.1) **Implemented enhancements:** - Clarify the probable cause of tempfile creation failure during cookbook sync [\#2171](https://github.com/chef/chef/issues/2171) +- Remove static libraries from Chef package [\#4654](https://github.com/chef/chef/pull/4654) ([chefsalim](https://github.com/chefsalim)) - Have client.rb verify that FIPS mode can be enforced [\#4630](https://github.com/chef/chef/pull/4630) ([ksubrama](https://github.com/ksubrama)) - List all of the unignored files when loading a cookbook [\#4629](https://github.com/chef/chef/pull/4629) ([danielsdeleo](https://github.com/danielsdeleo)) - adding pry and pry-byebug to dev dependencies [\#4601](https://github.com/chef/chef/pull/4601) ([mwrock](https://github.com/mwrock)) -- add an issue template [\#4590](https://github.com/chef/chef/pull/4590) ([lamont-granquist](https://github.com/lamont-granquist)) - Split group members on commas [\#4583](https://github.com/chef/chef/pull/4583) ([thommay](https://github.com/thommay)) - Make tempfiles easier to read \(prepend chef to the name\) [\#4582](https://github.com/chef/chef/pull/4582) ([thommay](https://github.com/thommay)) - Extend cookbook shadowing deprecation warnings more broadly [\#4574](https://github.com/chef/chef/pull/4574) ([lamont-granquist](https://github.com/lamont-granquist)) - tell knife's edit\_data what the object is [\#4548](https://github.com/chef/chef/pull/4548) ([thommay](https://github.com/thommay)) - Implement knife bootstrap client.d RFC [\#4529](https://github.com/chef/chef/pull/4529) ([jaym](https://github.com/jaym)) - Update to Log Level when showing unencrypted databag [\#4524](https://github.com/chef/chef/pull/4524) ([PatrickWalker](https://github.com/PatrickWalker)) +- RFC-060 gem metadata MVP [\#4478](https://github.com/chef/chef/pull/4478) ([lamont-granquist](https://github.com/lamont-granquist)) - chef-client: add --\[no\]skip-cookbook-sync option [\#4316](https://github.com/chef/chef/pull/4316) ([josb](https://github.com/josb)) +- Extend service resource to support masking [\#4307](https://github.com/chef/chef/pull/4307) ([davide125](https://github.com/davide125)) - launchd for osx [\#4111](https://github.com/chef/chef/pull/4111) ([mikedodge04](https://github.com/mikedodge04)) **Fixed bugs:** - Chef::DataBagItem.to\_hash is modifying Chef::DataBagItem.raw\_data [\#4614](https://github.com/chef/chef/issues/4614) - Chef 12 seeing a ton of these in debug mode [\#2396](https://github.com/chef/chef/issues/2396) +- Data bag item hash can have name key [\#4664](https://github.com/chef/chef/pull/4664) ([chefsalim](https://github.com/chefsalim)) +- Clearer exception for loading non-existent data bag items in solo mode. [\#4655](https://github.com/chef/chef/pull/4655) ([coderanger](https://github.com/coderanger)) +- Always rehash from gem source and not existing hash file [\#4651](https://github.com/chef/chef/pull/4651) ([tyler-ball](https://github.com/tyler-ball)) - Handle negative content length headers too. [\#4646](https://github.com/chef/chef/pull/4646) ([coderanger](https://github.com/coderanger)) - if no module name is found for a valid dsc resource default to PSDesiredStateConfiguration [\#4638](https://github.com/chef/chef/pull/4638) ([mwrock](https://github.com/mwrock)) - removing disabling of readline in chef-shell [\#4635](https://github.com/chef/chef/pull/4635) ([mwrock](https://github.com/mwrock)) @@ -5,6 +5,9 @@ gem "activesupport", "< 4.0.0", group: :compat_testing, platform: "ruby" gem "chef-config", path: "chef-config" if File.exist?(__FILE__ + "../chef-config") +# Ensure that we can always install rake, regardless of gem groups +gem "rake" + group(:docgen) do gem "yard" end @@ -17,6 +20,12 @@ group(:maintenance) do gem "netrc" end +group(:pry) do + gem "pry" + gem "pry-byebug" + gem "pry-stack_explorer" +end + group(:ruby_prof) do # may need to disable this in insolation on fussy builds like AIX, RHEL4, etc gem "ruby-prof" @@ -30,11 +39,7 @@ group(:development, :test) do # gem 'chefstyle', github: 'chef/chefstyle' gem "chefstyle", git: "https://github.com/chef/chefstyle.git", branch: "master" - gem "ruby-shadow", platforms: :ruby unless RUBY_PLATFORM.downcase.match(/(aix|cygwin)/) - - gem "pry" - gem "pry-byebug" - gem "pry-stack_explorer" + gem "ruby-shadow", platforms: :ruby unless RUBY_PLATFORM.downcase =~ /(aix|cygwin)/ end group(:travis) do diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 0023cb91bf..244f2ed1ad 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -46,7 +46,7 @@ To mention the team, use @chef/client-core ## Dev Tools -Chef Zero, Knife, Chef Apply and Chef Shell. +ChefDK, Chef Zero, Knife, Chef Apply and Chef Shell. To mention the team, use @chef/client-dev-tools ### Maintainers @@ -197,7 +197,7 @@ To mention the team, use @chef/client-freebsd * [Cory Stephenson](https://github.com/Aevin1387) * [David Aronsohn](https://github.com/tbunnyman) -* [Bryant Lippert](https://github.com/agentmeerkat) +* [Bryant Lippert](https://github.com/AgentMeerkat) ## OpenBSD diff --git a/MAINTAINERS.toml b/MAINTAINERS.toml index e2548d37b8..3b9507938c 100644 --- a/MAINTAINERS.toml +++ b/MAINTAINERS.toml @@ -54,7 +54,7 @@ another component. [Org.Components.DevTools] title = "Dev Tools" team = "client-dev-tools" - text = "Chef Zero, Knife, Chef Apply and Chef Shell." + text = "ChefDK, Chef Zero, Knife, Chef Apply and Chef Shell." paths = [ "lib/chef/knife.rb", @@ -161,6 +161,26 @@ The specific components of Chef related to a given platform - including (but not "lamont-granquist" ] + [Org.Components.Subsystems.CiscoNXOS] + title = "Cisco NX-OS" + team = "client-nxos" + + lieutenant = "cperry" + + maintainers = [ + "cperry" + ] + + [Org.Components.Subsystems.CiscoIOSXR] + title = "Cisco IOS XR" + team = "client-iosxr" + + lieutenant = "cperry" + + maintainers = [ + "cperry" + ] + [Org.Components.Subsystems.Fedora] title = "Fedora" team = "client-fedora" @@ -336,3 +356,7 @@ The specific components of Chef related to a given platform - including (but not [people.mwrock] Name = "Matt Wrock" GitHub = "mwrock" + + [people.cperry] + Name = "Carl Perry" + GitHub = "edolnx" @@ -72,11 +72,15 @@ rescue LoadError puts "yard is not available. (sudo) gem install yard to generate yard documentation." end -require "github_changelog_generator/task" +begin + require "github_changelog_generator/task" -GitHubChangelogGenerator::RakeTask.new :changelog do |config| - config.future_release = Chef::VERSION - config.enhancement_labels = "enhancement,Enhancement,New Feature,Feature".split(",") - config.bug_labels = "bug,Bug,Improvement,Upstream Bug".split(",") - config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog,Exclude From Changelog,Question,Discussion".split(",") + GitHubChangelogGenerator::RakeTask.new :changelog do |config| + config.future_release = Chef::VERSION + config.enhancement_labels = "enhancement,Enhancement,New Feature,Feature".split(",") + config.bug_labels = "bug,Bug,Improvement,Upstream Bug".split(",") + config.exclude_labels = "duplicate,question,invalid,wontfix,no_changelog,Exclude From Changelog,Question,Discussion".split(",") + end +rescue LoadError + puts "github_changelog_generator is not available. gem install github_changelog_generator to generate changelogs" end @@ -1 +1 @@ -12.8.0 +12.9.0 diff --git a/acceptance/.gitignore b/acceptance/.gitignore index 66f8ed35a4..0d2aa76a44 100644 --- a/acceptance/.gitignore +++ b/acceptance/.gitignore @@ -1 +1,2 @@ /Gemfile.lock +.acceptance_logs diff --git a/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb b/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb index aed81f073b..203ea9809a 100644 --- a/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb +++ b/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb @@ -4,6 +4,9 @@ class TopCookbooks < Chef::Resource property :command, String, name_property: true action :run do + cookbook_kitchen "#{command} docker" do + end + cookbook_kitchen "#{command} git" do end @@ -16,5 +19,27 @@ class TopCookbooks < Chef::Resource repository "learn-chef/learn-chef-acceptance" cookbook_relative_dir "cookbooks/learn-the-basics-windows" end + + cookbook_kitchen "#{command} powershell" do + end + + cookbook_kitchen "#{command} iis" do + end + + cookbook_kitchen "#{command} sql_server" do + end + + cookbook_kitchen "#{command} winbox" do + repository "adamedx/winbox" + end + + # Temporarily disabling windows and chocolatey to eliminate + # transient errors on the builders + # cookbook_kitchen "#{command} windows" do + # end + + # cookbook_kitchen "#{command} chocolatey" do + # repository "chocolatey/chocolatey-cookbook" + # end end end diff --git a/acceptance/top-cookbooks/.kitchen.chocolatey.yml b/acceptance/top-cookbooks/.kitchen.chocolatey.yml new file mode 100644 index 0000000000..7d7529d69f --- /dev/null +++ b/acceptance/top-cookbooks/.kitchen.chocolatey.yml @@ -0,0 +1,6 @@ +suites: + - name: default + run_list: + - recipe[chocolatey::default] + - recipe[chocolatey_test::default] + includes: [windows-2012r2] diff --git a/acceptance/top-cookbooks/.kitchen.docker.yml b/acceptance/top-cookbooks/.kitchen.docker.yml new file mode 100644 index 0000000000..74a238495a --- /dev/null +++ b/acceptance/top-cookbooks/.kitchen.docker.yml @@ -0,0 +1,12 @@ +suites: + - name: docker-default + attributes: + docker: + version: 1.10.0 + run_list: + - recipe[apt] + - recipe[apt-docker] + - recipe[docker_test::installation_package] + - recipe[docker_test::service_upstart] + - recipe[docker_test::auto] + includes: [ubuntu-14.04] diff --git a/acceptance/top-cookbooks/.kitchen.iis.yml b/acceptance/top-cookbooks/.kitchen.iis.yml new file mode 100644 index 0000000000..ffbc23caba --- /dev/null +++ b/acceptance/top-cookbooks/.kitchen.iis.yml @@ -0,0 +1,4 @@ +suites: + - name: iis + run_list: ["recipe[iis::default]"] + includes: [windows-2012r2] diff --git a/acceptance/top-cookbooks/.kitchen.powershell.yml b/acceptance/top-cookbooks/.kitchen.powershell.yml new file mode 100644 index 0000000000..6fad2364bb --- /dev/null +++ b/acceptance/top-cookbooks/.kitchen.powershell.yml @@ -0,0 +1,4 @@ +suites: + - name: powershell + run_list: ["recipe[powershell::powershell2]"] + includes: [windows-2012r2] diff --git a/acceptance/top-cookbooks/.kitchen.sql_server.yml b/acceptance/top-cookbooks/.kitchen.sql_server.yml new file mode 100644 index 0000000000..51a6bd6616 --- /dev/null +++ b/acceptance/top-cookbooks/.kitchen.sql_server.yml @@ -0,0 +1,5 @@ +suites: + - name: sql_server + run_list: ["recipe[sql_server::default]"] + attributes: { sql_server: { accept_eula: true } } + includes: [windows-2012r2] diff --git a/acceptance/top-cookbooks/.kitchen.winbox.yml b/acceptance/top-cookbooks/.kitchen.winbox.yml new file mode 100644 index 0000000000..9cf39a0d5b --- /dev/null +++ b/acceptance/top-cookbooks/.kitchen.winbox.yml @@ -0,0 +1,8 @@ +suites: + - name: default + run_list: + - recipe[winbox::default] + includes: [windows-2012r2] + +verifier: + name: dummy diff --git a/acceptance/top-cookbooks/.kitchen.windows.yml b/acceptance/top-cookbooks/.kitchen.windows.yml new file mode 100644 index 0000000000..38c86ff322 --- /dev/null +++ b/acceptance/top-cookbooks/.kitchen.windows.yml @@ -0,0 +1,38 @@ +suites: + # Waiting on https://github.com/chef-cookbooks/windows/pull/350 + # - name: tasks + # run_list: + # - recipe[windows::default] + # - recipe[minimal::tasks] + # includes: [windows-2012r2] + - name: path + run_list: + - recipe[windows::default] + - recipe[minimal::path] + includes: [windows-2012r2] + - name: certificate + run_list: + - recipe[windows::default] + - recipe[minimal::certificate] + includes: [windows-2012r2] + # Package is deprecated + # - name: package + # run_list: + # - recipe[windows::default] + # - recipe[minimal::package] + # includes: [windows-2012r2] + - name: feature + run_list: + - recipe[windows::default] + - recipe[minimal::feature] + includes: [windows-2012r2] + - name: http_acl + run_list: + - recipe[windows::default] + - recipe[minimal::http_acl] + includes: [windows-2012r2] + - name: font + run_list: + - recipe[windows::default] + - recipe[minimal::font] + includes: [windows-2012r2] diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb index 8161cd9ea7..d7a8a1b997 100644 --- a/chef-config/lib/chef-config/config.rb +++ b/chef-config/lib/chef-config/config.rb @@ -476,8 +476,8 @@ module ChefConfig # Path to the default CA bundle files. default :ssl_ca_path, nil default(:ssl_ca_file) do - if ChefConfig.windows? and embedded_path = embedded_dir - cacert_path = File.join(embedded_path, "ssl/certs/cacert.pem") + if ChefConfig.windows? && embedded_dir + cacert_path = File.join(embedded_dir, "ssl/certs/cacert.pem") cacert_path if File.exist?(cacert_path) else nil @@ -703,6 +703,9 @@ module ChefConfig # Use atomic updates (i.e. move operation) while updating contents # of the files resources. When set to false copy operation is # used to update files. + # + # NOTE: CHANGING THIS SETTING MAY CAUSE CORRUPTION, DATA LOSS AND + # INSTABILITY. default :file_atomic_update, true # There are 3 possible values for this configuration setting. @@ -900,6 +903,8 @@ module ChefConfig # break Chef community cookbooks and is very highly discouraged. default :ruby_encoding, Encoding::UTF_8 + default :rubygems_url, "https://rubygems.org" + # If installed via an omnibus installer, this gives the path to the # "embedded" directory which contains all of the software packaged with # omnibus. This is used to locate the cacert.pem file on windows. diff --git a/chef-config/lib/chef-config/package_task.rb b/chef-config/lib/chef-config/package_task.rb index 4f75af9c6c..1860335854 100644 --- a/chef-config/lib/chef-config/package_task.rb +++ b/chef-config/lib/chef-config/package_task.rb @@ -99,7 +99,7 @@ module ChefConfig if defined?(Bundler) Bundler.with_clean_env(&block) else - block.call + yield end end diff --git a/chef-config/lib/chef-config/path_helper.rb b/chef-config/lib/chef-config/path_helper.rb index 42047b5e22..0304694516 100644 --- a/chef-config/lib/chef-config/path_helper.rb +++ b/chef-config/lib/chef-config/path_helper.rb @@ -66,7 +66,7 @@ module ChefConfig args.flatten.inject() do |joined_path, component| joined_path = joined_path.sub(trailing_slashes, "") component = component.sub(leading_slashes, "") - joined_path += "#{path_separator}#{component}" + joined_path + "#{path_separator}#{component}" end end @@ -128,6 +128,17 @@ module ChefConfig abs_path end + # This is the INVERSE of Pathname#cleanpath, it converts forward + # slashes to backwhacks for Windows. Since the Ruby API and the + # Windows APIs all consume forward slashes, this helper function + # should only be used for *DISPLAY* logic to send strings back + # to the user with backwhacks. Internally, filename paths should + # generally be stored with forward slashes for consistency. It is + # not necessary or desired to blindly convert pathnames to have + # backwhacks on Windows. + # + # Generally, if the user isn't going to be seeing it, you should be + # using Pathname#cleanpath intead of this function. def self.cleanpath(path) path = Pathname.new(path).cleanpath.to_s # ensure all forward slashes are backslashes @@ -239,7 +250,7 @@ module ChefConfig # Determine if the given path is protected by OS X System Integrity Protection. def self.is_sip_path?(path, node) - if node["platform"] == "mac_os_x" and Gem::Version.new(node["platform_version"]) >= Gem::Version.new("10.11") + if node["platform"] == "mac_os_x" && Gem::Version.new(node["platform_version"]) >= Gem::Version.new("10.11") # todo: parse rootless.conf for this? sip_paths = [ "/System", "/bin", "/sbin", "/usr" diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb index 3840ff0319..2c15eb1693 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.dirname(File.expand_path(File.dirname(__FILE__))) - VERSION = "12.8.0" + VERSION = "12.9.0" end # diff --git a/chef.gemspec b/chef.gemspec index 0e6f7e0234..2e6f635279 100644 --- a/chef.gemspec +++ b/chef.gemspec @@ -45,6 +45,10 @@ Gem::Specification.new do |s| s.add_dependency "proxifier", "~> 1.0" + # v1.10 is needed as a runtime dep now for 'bundler/inline' + # very deliberately avoiding putting a ceiling on this to avoid depsolver conflicts. + s.add_dependency "bundler", ">= 1.10" + s.add_development_dependency "rack" s.add_development_dependency "cheffish", ">= 1.1", "< 3.0" s.add_development_dependency "github_changelog_generator", "1.11.3" diff --git a/kitchen-tests/.kitchen.travis.yml b/kitchen-tests/.kitchen.travis.yml index 3fcbcf6f78..100891bdf5 100644 --- a/kitchen-tests/.kitchen.travis.yml +++ b/kitchen-tests/.kitchen.travis.yml @@ -9,6 +9,8 @@ driver: provisioner: name: chef_github + chef_omnibus_url: "https://omnitruck.chef.io/current/install.sh" + chef_omnibus_install_options: "-n" github_owner: "chef" github_repo: "chef" refname: <%= ENV['TRAVIS_COMMIT'] %> diff --git a/lib/chef/api_client/registration.rb b/lib/chef/api_client/registration.rb index b05bdcac31..e8ab0149e8 100644 --- a/lib/chef/api_client/registration.rb +++ b/lib/chef/api_client/registration.rb @@ -69,7 +69,7 @@ class Chef end def assert_destination_writable! - if (File.exists?(destination) && !File.writable?(destination)) or !File.writable?(File.dirname(destination)) + if (File.exists?(destination) && !File.writable?(destination)) || !File.writable?(File.dirname(destination)) abs_path = File.expand_path(destination) raise Chef::Exceptions::CannotWritePrivateKey, "I can't write your private key to #{abs_path} - check permissions?" end diff --git a/lib/chef/application/apply.rb b/lib/chef/application/apply.rb index 38b00f293c..03c86b86f2 100644 --- a/lib/chef/application/apply.rb +++ b/lib/chef/application/apply.rb @@ -204,7 +204,7 @@ class Chef::Application::Apply < Chef::Application parse_options run_chef_recipe Chef::Application.exit! "Exiting", 0 - rescue SystemExit => e + rescue SystemExit raise rescue Exception => e Chef::Application.debug_stacktrace(e) diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb index 8f30037ac7..500aa8ac59 100644 --- a/lib/chef/application/client.rb +++ b/lib/chef/application/client.rb @@ -265,7 +265,7 @@ class Chef::Application::Client < Chef::Application option :audit_mode, :long => "--audit-mode MODE", :description => "Enable audit-mode with `enabled`. Disable audit-mode with `disabled`. Skip converge and only perform audits with `audit-only`", - :proc => lambda { |mo| mo.gsub("-", "_").to_sym } + :proc => lambda { |mo| mo.tr("-", "_").to_sym } option :minimal_ohai, :long => "--minimal-ohai", @@ -480,7 +480,7 @@ class Chef::Application::Client < Chef::Application end def client_sleep(sec) - IO.select([ SELF_PIPE[0] ], nil, nil, sec) or return + return unless IO.select([ SELF_PIPE[0] ], nil, nil, sec) @signal = SELF_PIPE[0].getc.chr end diff --git a/lib/chef/application/windows_service.rb b/lib/chef/application/windows_service.rb index 0328a65487..fca1ed3689 100644 --- a/lib/chef/application/windows_service.rb +++ b/lib/chef/application/windows_service.rb @@ -312,13 +312,13 @@ class Chef else ::File.open(config[:config_file]) { |f| apply_config(f.path) } end - rescue Errno::ENOENT => error + rescue Errno::ENOENT Chef::Log.warn("*****************************************") Chef::Log.warn("Did not find config file: #{config[:config_file]}, using command line options.") Chef::Log.warn("*****************************************") Chef::Config.merge!(config) - rescue SocketError => error + rescue SocketError Chef::Application.fatal!("Error getting config file #{Chef::Config[:config_file]}", 2) rescue Chef::Exceptions::ConfigurationError => error Chef::Application.fatal!("Error processing config file #{Chef::Config[:config_file]} with error #{error.message}", 2) diff --git a/lib/chef/chef_fs/config.rb b/lib/chef/chef_fs/config.rb index 1dbbe1a508..6e3cc50ac1 100644 --- a/lib/chef/chef_fs/config.rb +++ b/lib/chef/chef_fs/config.rb @@ -270,7 +270,8 @@ class Chef end object_names.each do |object_name| # cookbooks -> cookbook_path - singular_name = INFLECTIONS[object_name] or raise "Unknown object name #{object_name}" + singular_name = INFLECTIONS[object_name] + raise "Unknown object name #{object_name}" unless singular_name variable_name = "#{singular_name}_path" paths = Array(@chef_config[variable_name]).flatten result[object_name] = paths.map { |path| File.expand_path(path) } diff --git a/lib/chef/chef_fs/data_handler/container_data_handler.rb b/lib/chef/chef_fs/data_handler/container_data_handler.rb index a2e277fc7a..04973b5135 100644 --- a/lib/chef/chef_fs/data_handler/container_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/container_data_handler.rb @@ -15,10 +15,16 @@ class Chef return key == "containername" end - def verify_integrity(object, entry, &on_error) + # Verify that the JSON hash for this type has a key that matches its name. + # + # @param object [Object] JSON hash of the object + # @param entry [Chef::ChefFS::FileSystem::BaseFSObject] filesystem object we are verifying + # @yield [s] callback to handle errors + # @yieldparam [s<string>] error message + def verify_integrity(object, entry) base_name = remove_dot_json(entry.name) if object["containername"] != base_name - on_error.call("Name in #{entry.path_for_printing} must be '#{base_name}' (is '#{object['name']}')") + yield("Name in #{entry.path_for_printing} must be '#{base_name}' (is '#{object['containername']}')") end end diff --git a/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb b/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb index 8ac9a520a4..c6b6449d52 100644 --- a/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb @@ -42,10 +42,16 @@ class Chef Chef::DataBagItem end - def verify_integrity(object, entry, &on_error) + # Verify that the JSON hash for this type has a key that matches its name. + # + # @param object [Object] JSON hash of the object + # @param entry [Chef::ChefFS::FileSystem::BaseFSObject] filesystem object we are verifying + # @yield [s] callback to handle errors + # @yieldparam [s<string>] error message + def verify_integrity(object, entry) base_name = remove_dot_json(entry.name) if object["raw_data"]["id"] != base_name - on_error.call("ID in #{entry.path_for_printing} must be '#{base_name}' (is '#{object['raw_data']['id']}')") + yield("ID in #{entry.path_for_printing} must be '#{base_name}' (is '#{object['raw_data']['id']}')") end end diff --git a/lib/chef/chef_fs/data_handler/data_handler_base.rb b/lib/chef/chef_fs/data_handler/data_handler_base.rb index 83f56ed16d..b30ae9c708 100644 --- a/lib/chef/chef_fs/data_handler/data_handler_base.rb +++ b/lib/chef/chef_fs/data_handler/data_handler_base.rb @@ -185,14 +185,16 @@ class Chef result end - # # Verify that the JSON hash for this type has a key that matches its name. - # Calls the on_error block with the error, if there is one. # - def verify_integrity(object, entry, &on_error) + # @param object [Object] JSON hash of the object + # @param entry [Chef::ChefFS::FileSystem::BaseFSObject] filesystem object we are verifying + # @yield [s] callback to handle errors + # @yieldparam [s<string>] error message + def verify_integrity(object, entry) base_name = remove_dot_json(entry.name) if object["name"] != base_name - on_error.call("Name must be '#{base_name}' (is '#{object['name']}')") + yield("Name must be '#{base_name}' (is '#{object['name']}')") end end diff --git a/lib/chef/chef_fs/data_handler/organization_data_handler.rb b/lib/chef/chef_fs/data_handler/organization_data_handler.rb index 3e5528cc49..0facd5d55d 100644 --- a/lib/chef/chef_fs/data_handler/organization_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/organization_data_handler.rb @@ -19,9 +19,15 @@ class Chef return key == "name" end - def verify_integrity(object, entry, &on_error) + # Verify that the JSON hash for this type has a key that matches its name. + # + # @param object [Object] JSON hash of the object + # @param entry [Chef::ChefFS::FileSystem::BaseFSObject] filesystem object we are verifying + # @yield [s] callback to handle errors + # @yieldparam [s<string>] error message + def verify_integrity(object, entry) if entry.org != object["name"] - on_error.call("Name must be '#{entry.org}' (is '#{object['name']}')") + yield("Name must be '#{entry.org}' (is '#{object['name']}')") end end end diff --git a/lib/chef/chef_fs/data_handler/policy_data_handler.rb b/lib/chef/chef_fs/data_handler/policy_data_handler.rb index 477d2bf637..fa7bbe9101 100644 --- a/lib/chef/chef_fs/data_handler/policy_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/policy_data_handler.rb @@ -26,14 +26,20 @@ class Chef normalize_hash(policy, defaults) end - def verify_integrity(object_data, entry, &on_error) + # Verify that the JSON hash for this type has a key that matches its name. + # + # @param object [Object] JSON hash of the object + # @param entry [Chef::ChefFS::FileSystem::BaseFSObject] filesystem object we are verifying + # @yield [s] callback to handle errors + # @yieldparam [s<string>] error message + def verify_integrity(object_data, entry) name, revision = name_and_revision(entry.name) if object_data["name"] != name - on_error.call("Object name '#{object_data['name']}' doesn't match entry '#{entry.name}'.") + yield("Object name '#{object_data['name']}' doesn't match entry '#{name}'.") end if object_data["revision_id"] != revision - on_error.call("Object revision ID '#{object_data['revision']}' doesn't match entry '#{entry.name}'.") + yield("Object revision ID '#{object_data['revision_id']}' doesn't match entry '#{revision}'.") end end end diff --git a/lib/chef/chef_fs/data_handler/policy_group_data_handler.rb b/lib/chef/chef_fs/data_handler/policy_group_data_handler.rb index e5c430ab64..f7aa92373c 100644 --- a/lib/chef/chef_fs/data_handler/policy_group_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/policy_group_data_handler.rb @@ -15,9 +15,15 @@ class Chef result end - def verify_integrity(object_data, entry, &on_error) + # Verify that the JSON hash for this type has a key that matches its name. + # + # @param object [Object] JSON hash of the object + # @param entry [Chef::ChefFS::FileSystem::BaseFSObject] filesystem object we are verifying + # @yield [s] callback to handle errors + # @yieldparam [s<string>] error message + def verify_integrity(object_data, entry) if object_data["policies"].empty? - on_error.call("Policy group #{object_data["name"]} does not have any policies in it.") + yield("Policy group #{object_data["name"]} does not have any policies in it.") end end diff --git a/lib/chef/chef_fs/file_system.rb b/lib/chef/chef_fs/file_system.rb index 415556300c..e6cf735971 100644 --- a/lib/chef/chef_fs/file_system.rb +++ b/lib/chef/chef_fs/file_system.rb @@ -55,7 +55,7 @@ class Chef def list_from(entry, &block) # Include self in results if it matches if pattern.match?(entry.path) - block.call(entry) + yield(entry) end if pattern.could_match_children?(entry.path) diff --git a/lib/chef/chef_fs/file_system/chef_server/acl_dir.rb b/lib/chef/chef_fs/file_system/chef_server/acl_dir.rb index 9943aaeca7..58a32d3860 100644 --- a/lib/chef/chef_fs/file_system/chef_server/acl_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/acl_dir.rb @@ -30,7 +30,7 @@ class Chef end def make_child_entry(name, exists = nil) - result = @children.select { |child| child.name == name }.first if @children + result = @children.find { |child| child.name == name } if @children result || AclEntry.new(name, self, exists) end diff --git a/lib/chef/chef_fs/file_system/chef_server/acls_dir.rb b/lib/chef/chef_fs/file_system/chef_server/acls_dir.rb index d03164023f..b9af486203 100644 --- a/lib/chef/chef_fs/file_system/chef_server/acls_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/acls_dir.rb @@ -39,7 +39,7 @@ class Chef end def make_child_entry(name) - children.select { |child| child.name == name }.first + children.find { |child| child.name == name } end def can_have_child?(name, is_dir) diff --git a/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb b/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb index 6c99d6de73..5030a0733f 100644 --- a/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/chef_server_root_dir.rb @@ -119,7 +119,7 @@ class Chef end def can_have_child?(name, is_dir) - result = children.select { |child| child.name == name }.first + result = children.find { |child| child.name == name } result && !!result.dir? == !!is_dir end @@ -136,7 +136,7 @@ class Chef end def make_child_entry(name) - children.select { |child| child.name == name }.first + children.find { |child| child.name == name } end def children diff --git a/lib/chef/chef_fs/file_system/chef_server/cookbook_artifacts_dir.rb b/lib/chef/chef_fs/file_system/chef_server/cookbook_artifacts_dir.rb index 020f8510b7..0b82a64a0a 100644 --- a/lib/chef/chef_fs/file_system/chef_server/cookbook_artifacts_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/cookbook_artifacts_dir.rb @@ -35,7 +35,7 @@ class Chef class CookbookArtifactsDir < CookbooksDir def make_child_entry(name) - result = @children.select { |child| child.name == name }.first if @children + result = @children.find { |child| child.name == name } if @children result || CookbookArtifactDir.new(name, self) end diff --git a/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb b/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb index 92295b4fe8..f7e5f058be 100644 --- a/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb @@ -74,7 +74,7 @@ class Chef # we need to make sure we don't rethrow the exception. (child(name) # is not supposed to fail.) begin - children.select { |child| child.name == name }.first + children.find { |child| child.name == name } rescue Chef::ChefFS::FileSystem::NotFoundError nil end @@ -101,7 +101,7 @@ class Chef container = self parts[0, parts.length - 1].each do |part| old_container = container - container = old_container.children.select { |child| part == child.name }.first + container = old_container.children.find { |child| part == child.name } if !container container = CookbookSubdir.new(part, old_container, segment_info[:ruby_only], segment_info[:recursive]) old_container.add_child(container) diff --git a/lib/chef/chef_fs/file_system/chef_server/cookbook_subdir.rb b/lib/chef/chef_fs/file_system/chef_server/cookbook_subdir.rb index 913cf1a5e2..01297a39ba 100644 --- a/lib/chef/chef_fs/file_system/chef_server/cookbook_subdir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/cookbook_subdir.rb @@ -47,7 +47,7 @@ class Chef end def make_child_entry(name) - result = @children.select { |child| child.name == name }.first if @children + result = @children.find { |child| child.name == name } if @children result || NonexistentFSObject.new(name, self) end diff --git a/lib/chef/chef_fs/file_system/chef_server/cookbooks_dir.rb b/lib/chef/chef_fs/file_system/chef_server/cookbooks_dir.rb index 75d7150f8e..72cefe44eb 100644 --- a/lib/chef/chef_fs/file_system/chef_server/cookbooks_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/cookbooks_dir.rb @@ -41,7 +41,7 @@ class Chef include Chef::Mixin::FileClass def make_child_entry(name) - result = @children.select { |child| child.name == name }.first if @children + result = @children.find { |child| child.name == name } if @children result || CookbookDir.new(name, self) end diff --git a/lib/chef/chef_fs/file_system/chef_server/data_bags_dir.rb b/lib/chef/chef_fs/file_system/chef_server/data_bags_dir.rb index 9246d8e2b7..ec382e60ef 100644 --- a/lib/chef/chef_fs/file_system/chef_server/data_bags_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/data_bags_dir.rb @@ -25,7 +25,7 @@ class Chef module ChefServer class DataBagsDir < RestListDir def make_child_entry(name, exists = false) - result = @children.select { |child| child.name == name }.first if @children + result = @children.find { |child| child.name == name } if @children result || DataBagDir.new(name, self, exists) end diff --git a/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb b/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb index ebb274a9eb..4a4be19fe4 100644 --- a/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb @@ -47,7 +47,7 @@ class Chef # } def make_child_entry(name, exists = nil) - @children.select { |child| child.name == name }.first if @children + @children.find { |child| child.name == name } if @children PolicyRevisionEntry.new(name, self, exists) end diff --git a/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb b/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb index 488e9c0ed0..b5b602a208 100644 --- a/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/rest_list_dir.rb @@ -168,7 +168,7 @@ class Chef end def make_child_entry(name, exists = nil) - @children.select { |child| child.name == name }.first if @children + @children.find { |child| child.name == name } if @children RestListEntry.new(name, self, exists) end end diff --git a/lib/chef/chef_fs/file_system/chef_server/versioned_cookbooks_dir.rb b/lib/chef/chef_fs/file_system/chef_server/versioned_cookbooks_dir.rb index 9abafed5e7..172405763a 100644 --- a/lib/chef/chef_fs/file_system/chef_server/versioned_cookbooks_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/versioned_cookbooks_dir.rb @@ -41,7 +41,7 @@ class Chef class VersionedCookbooksDir < CookbooksDir def make_child_entry(name) - result = @children.select { |child| child.name == name }.first if @children + result = @children.find { |child| child.name == name } if @children result || VersionedCookbookDir.new(name, self) end diff --git a/lib/chef/chef_fs/file_system/memory/memory_dir.rb b/lib/chef/chef_fs/file_system/memory/memory_dir.rb index beb661448d..6049f404b1 100644 --- a/lib/chef/chef_fs/file_system/memory/memory_dir.rb +++ b/lib/chef/chef_fs/file_system/memory/memory_dir.rb @@ -14,7 +14,7 @@ class Chef attr_reader :children def make_child_entry(name) - @children.select { |child| child.name == name }.first + @children.find { |child| child.name == name } end def add_child(child) diff --git a/lib/chef/chef_fs/parallelizer/flatten_enumerable.rb b/lib/chef/chef_fs/parallelizer/flatten_enumerable.rb index 6094fab493..84db2c2053 100644 --- a/lib/chef/chef_fs/parallelizer/flatten_enumerable.rb +++ b/lib/chef/chef_fs/parallelizer/flatten_enumerable.rb @@ -26,7 +26,7 @@ class Chef flatten(child, levels.nil? ? levels : levels - 1, &block) end else - block.call(value) + yield(value) end end end diff --git a/lib/chef/client.rb b/lib/chef/client.rb index 7d2dcf8057..8ca0fd5e89 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -312,9 +312,7 @@ class Chef events.run_failed(run_error) ensure Chef::RequestID.instance.reset_request_id - request_id = nil @run_status = nil - run_context = nil runlock.release end diff --git a/lib/chef/config_fetcher.rb b/lib/chef/config_fetcher.rb index 13f9fc3825..acd2f07f5e 100644 --- a/lib/chef/config_fetcher.rb +++ b/lib/chef/config_fetcher.rb @@ -45,9 +45,9 @@ class Chef def read_local_config ::File.read(config_location) - rescue Errno::ENOENT => error + rescue Errno::ENOENT Chef::Application.fatal!("Cannot load configuration from #{config_location}", 2) - rescue Errno::EACCES => error + rescue Errno::EACCES Chef::Application.fatal!("Permissions are incorrect on #{config_location}. Please chmod a+r #{config_location}", 2) end diff --git a/lib/chef/cookbook/cookbook_collection.rb b/lib/chef/cookbook/cookbook_collection.rb index 81e7bb92b4..d06b8fd042 100644 --- a/lib/chef/cookbook/cookbook_collection.rb +++ b/lib/chef/cookbook/cookbook_collection.rb @@ -1,7 +1,7 @@ #-- # Author:: Tim Hinderliter (<tim@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) -# Copyright:: Copyright 2010-2016, Chef Software, Inc. +# Copyright:: Copyright 2010-2016 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ # require "chef/mash" +require "chef/cookbook/gem_installer" class Chef # == Chef::CookbookCollection @@ -54,5 +55,9 @@ class Chef cookbook_version.metadata.validate_ohai_version! end end + + def install_gems(events) + Cookbook::GemInstaller.new(self, events).install + end end end diff --git a/lib/chef/cookbook/gem_installer.rb b/lib/chef/cookbook/gem_installer.rb new file mode 100644 index 0000000000..a85868ccfd --- /dev/null +++ b/lib/chef/cookbook/gem_installer.rb @@ -0,0 +1,118 @@ +#-- +# Copyright:: Copyright (c) 2010-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. +# + +require "bundler" +require "bundler/inline" + +class Chef + class Cookbook + class GemInstaller + + # @return [Chef::EventDispatch::Dispatcher] the client event dispatcher + attr_accessor :events + # @return [Chef::CookbookCollection] the cookbook collection + attr_accessor :cookbook_collection + + def initialize(cookbook_collection, events) + @cookbook_collection = cookbook_collection + @events = events + end + + # Installs the gems into the omnibus gemset. + # + def install + cookbook_gems = [] + + cookbook_collection.each do |cookbook_name, cookbook_version| + cookbook_gems += cookbook_version.metadata.gems + end + + events.cookbook_gem_start(cookbook_gems) + + unless cookbook_gems.empty? + begin + inline_gemfile do + source Chef::Config[:rubygems_url] + cookbook_gems.each do |args| + gem(*args) + end + end + rescue Exception => e + events.cookbook_gem_failed(e) + raise + end + end + + events.cookbook_gem_finished + end + + # Bundler::UI object so that we can intercept and log the output + # of the in-memory bundle install that we are going to do. + # + class ChefBundlerUI < Bundler::UI::Silent + attr_accessor :events + + def initialize(events) + @events = events + super() + end + + def confirm(msg, newline = nil) + # looks like "Installing time_ago_in_words 0.1.1" when installing + if msg =~ /Installing\s+(\S+)\s+(\S+)/ + events.cookbook_gem_installing($1, $2) + end + Chef::Log.info(msg) + end + + def error(msg, newline = nil) + Chef::Log.error(msg) + end + + def debug(msg, newline = nil) + Chef::Log.debug(msg) + end + + def info(msg, newline = nil) + # looks like "Using time_ago_in_words 0.1.1" when using, plus other misc output + if msg =~ /Using\s+(\S+)\s+(\S+)/ + events.cookbook_gem_using($1, $2) + end + Chef::Log.info(msg) + end + + def warn(msg, newline = nil) + Chef::Log.warn(msg) + end + end + + private + + # Helper to handle older bundler versions that do not support injecting the UI + # object. On older bundler versions, we work, but you get no output other than + # on STDOUT. + # + def inline_gemfile(&block) + # requires https://github.com/bundler/bundler/pull/4245 + gemfile(true, ui: ChefBundlerUI.new(events), &block) + rescue ArgumentError # Method#arity doesn't inspect optional arguments, so we rescue + # requires bundler 1.10.0 + gemfile(true, &block) + end + end + end +end diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb index 1cad526b65..603f80748c 100644 --- a/lib/chef/cookbook/metadata.rb +++ b/lib/chef/cookbook/metadata.rb @@ -58,12 +58,14 @@ class Chef PRIVACY = "privacy".freeze CHEF_VERSIONS = "chef_versions".freeze OHAI_VERSIONS = "ohai_versions".freeze + GEMS = "gems".freeze COMPARISON_FIELDS = [ :name, :description, :long_description, :maintainer, :maintainer_email, :license, :platforms, :dependencies, :recommendations, :suggestions, :conflicting, :providing, :replacing, :attributes, :groupings, :recipes, :version, - :source_url, :issues_url, :privacy, :chef_versions, :ohai_versions ] + :source_url, :issues_url, :privacy, :chef_versions, :ohai_versions, + :gems ] VERSION_CONSTRAINTS = { :depends => DEPENDENCIES, :recommends => RECOMMENDATIONS, @@ -93,6 +95,8 @@ class Chef attr_reader :chef_versions # @return [Array<Gem::Dependency>] Array of supported Ohai versions attr_reader :ohai_versions + # @return [Array<Array>] Array of gems to install with *args as an Array + attr_reader :gems # Builds a new Chef::Cookbook::Metadata object. # @@ -130,6 +134,7 @@ class Chef @privacy = false @chef_versions = [] @ohai_versions = [] + @gems = [] @errors = [] end @@ -420,6 +425,17 @@ class Chef @ohai_versions end + # Metadata DSL to set a gem to install from the cookbook metadata. May be declared + # multiple times. All the gems from all the cookbooks are combined into one Gemfile + # and depsolved together. Uses Bundler's DSL for its implementation. + # + # @param args [Array<String>] Gem name and options to pass to Bundler's DSL + # @return [Array<Array>] Array of gem statements as args + def gem(*args) + @gems << args unless args.empty? + @gems + end + # Adds a description for a recipe. # # === Parameters @@ -573,6 +589,7 @@ class Chef PRIVACY => self.privacy, CHEF_VERSIONS => gem_requirements_to_array(*self.chef_versions), OHAI_VERSIONS => gem_requirements_to_array(*self.ohai_versions), + GEMS => self.gems, } end @@ -609,6 +626,7 @@ class Chef @privacy = o[PRIVACY] if o.has_key?(PRIVACY) @chef_versions = gem_requirements_from_array("chef", o[CHEF_VERSIONS]) if o.has_key?(CHEF_VERSIONS) @ohai_versions = gem_requirements_from_array("ohai", o[OHAI_VERSIONS]) if o.has_key?(OHAI_VERSIONS) + @gems = o[GEMS] if o.has_key?(GEMS) self end diff --git a/lib/chef/cookbook/syntax_check.rb b/lib/chef/cookbook/syntax_check.rb index fd7835db96..f8559433dc 100644 --- a/lib/chef/cookbook/syntax_check.rb +++ b/lib/chef/cookbook/syntax_check.rb @@ -114,7 +114,7 @@ class Chef end def ruby_files - path = Chef::Util::PathHelper.escape_glob(cookbook_path) + path = Chef::Util::PathHelper.escape_glob_dir(cookbook_path) files = Dir[File.join(path, "**", "*.rb")] files = remove_ignored_files(files) files = remove_uninteresting_ruby_files(files) @@ -133,7 +133,7 @@ class Chef end def template_files - remove_ignored_files Dir[File.join(Chef::Util::PathHelper.escape_glob(cookbook_path), "**/templates/**", "*.erb")] + remove_ignored_files Dir[File.join(Chef::Util::PathHelper.escape_glob_dir(cookbook_path), "**/templates/**", "*.erb")] end def untested_template_files diff --git a/lib/chef/cookbook_loader.rb b/lib/chef/cookbook_loader.rb index 9367936c32..bff77fa13b 100644 --- a/lib/chef/cookbook_loader.rb +++ b/lib/chef/cookbook_loader.rb @@ -47,7 +47,7 @@ class Chef @cookbooks_paths = Hash.new { |h, k| h[k] = [] } # for deprecation warnings @chefignores = {} @repo_paths = repo_paths.map do |repo_path| - repo_path = File.expand_path(repo_path) + File.expand_path(repo_path) end @preloaded_cookbooks = false @@ -121,7 +121,7 @@ class Chef end def [](cookbook) - if @cookbooks_by_name.has_key?(cookbook.to_sym) or load_cookbook(cookbook.to_sym) + if @cookbooks_by_name.has_key?(cookbook.to_sym) || load_cookbook(cookbook.to_sym) @cookbooks_by_name[cookbook.to_sym] else raise Exceptions::CookbookNotFoundInRepo, "Cannot find a cookbook named #{cookbook}; did you forget to add metadata to a cookbook? (https://docs.chef.io/config_rb_metadata.html)" @@ -179,7 +179,7 @@ class Chef @all_files_in_repo_paths ||= begin @repo_paths.inject([]) do |all_children, repo_path| - all_children += Dir[File.join(Chef::Util::PathHelper.escape_glob(repo_path), "*")] + all_children + Dir[File.join(Chef::Util::PathHelper.escape_glob_dir(repo_path), "*")] end end end diff --git a/lib/chef/cookbook_site_streaming_uploader.rb b/lib/chef/cookbook_site_streaming_uploader.rb index d6a270b033..9fb8d0d4bc 100644 --- a/lib/chef/cookbook_site_streaming_uploader.rb +++ b/lib/chef/cookbook_site_streaming_uploader.rb @@ -77,7 +77,6 @@ class Chef parts = [] content_file = nil - timestamp = Time.now.utc.iso8601 secret_key = OpenSSL::PKey::RSA.new(File.read(secret_key_filename)) unless params.nil? || params.empty? diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb index 2857d8098e..1e903608b5 100644 --- a/lib/chef/cookbook_version.rb +++ b/lib/chef/cookbook_version.rb @@ -316,11 +316,17 @@ class Chef error_message << error_locations.join("\n") existing_files = segment_filenames(segment) # Strip the root_dir prefix off all files for readability - existing_files.map! { |path| path[root_dir.length + 1..-1] } if root_dir + pretty_existing_files = existing_files.map { |path| + if root_dir + path[root_dir.length + 1..-1] + else + path + end + } # Show the files that the cookbook does have. If the user made a typo, # hopefully they'll see it here. - unless existing_files.empty? - error_message << "\n\nThis cookbook _does_ contain: ['#{existing_files.join("','")}']" + unless pretty_existing_files.empty? + error_message << "\n\nThis cookbook _does_ contain: ['#{pretty_existing_files.join("','")}']" end raise Chef::Exceptions::FileNotFound, error_message else @@ -489,7 +495,7 @@ class Chef # @deprecated This method was used by the Ruby Chef Server and is no longer # needed. There is no replacement. - def generate_manifest_with_urls(&url_generator) + def generate_manifest_with_urls Chef.log_deprecation("Deprecated method #generate_manifest_with_urls.") rendered_manifest = manifest.dup @@ -497,7 +503,7 @@ class Chef if rendered_manifest.has_key?(segment) rendered_manifest[segment].each do |manifest_record| url_options = { :cookbook_name => name.to_s, :cookbook_version => version, :checksum => manifest_record["checksum"] } - manifest_record["url"] = url_generator.call(url_options) + manifest_record["url"] = yield(url_options) end end end diff --git a/lib/chef/daemon.rb b/lib/chef/daemon.rb index 242419890c..70bdddf457 100644 --- a/lib/chef/daemon.rb +++ b/lib/chef/daemon.rb @@ -61,7 +61,7 @@ class Chef # String:: # Location of the pid file for @name def pid_file - Chef::Config[:pid_file] or "/tmp/#{@name}.pid" + Chef::Config[:pid_file] || "/tmp/#{@name}.pid" end # Suck the pid out of pid_file @@ -82,7 +82,7 @@ class Chef def change_privilege Dir.chdir("/") - if Chef::Config[:user] and Chef::Config[:group] + if Chef::Config[:user] && Chef::Config[:group] Chef::Log.info("About to change privilege to #{Chef::Config[:user]}:#{Chef::Config[:group]}") _change_privilege(Chef::Config[:user], Chef::Config[:group]) elsif Chef::Config[:user] @@ -117,7 +117,7 @@ class Chef return false end - if (uid != target_uid) or (gid != target_gid) + if (uid != target_uid) || (gid != target_gid) Process.initgroups(user, target_gid) Process::GID.change_privilege(target_gid) Process::UID.change_privilege(target_uid) diff --git a/lib/chef/data_bag_item.rb b/lib/chef/data_bag_item.rb index 6ac863a47d..d9ad771202 100644 --- a/lib/chef/data_bag_item.rb +++ b/lib/chef/data_bag_item.rb @@ -128,7 +128,6 @@ class Chef def self.from_hash(h) h.delete("chef_type") h.delete("json_class") - h.delete("name") item = new item.data_bag(h.delete("data_bag")) if h.key?("data_bag") @@ -150,6 +149,7 @@ class Chef def self.load(data_bag, name) if Chef::Config[:solo] bag = Chef::DataBag.load(data_bag) + raise Exceptions::InvalidDataBagItemID, "Item #{name} not found in data bag #{data_bag}. Other items found: #{bag.keys.join(", ")}" unless bag.include?(name) item = bag[name] else item = Chef::ServerAPI.new(Chef::Config[:chef_server_url]).get("data/#{data_bag}/#{name}") diff --git a/lib/chef/deprecation/provider/file.rb b/lib/chef/deprecation/provider/file.rb index 4db9101d8d..edb0052fdf 100644 --- a/lib/chef/deprecation/provider/file.rb +++ b/lib/chef/deprecation/provider/file.rb @@ -181,7 +181,7 @@ class Chef # Clean up after the number of backups slice_number = @new_resource.backup - backup_files = Dir[Chef::Util::PathHelper.escape_glob(prefix, ".#{@new_resource.path}") + ".chef-*"].sort { |a, b| b <=> a } + backup_files = Dir[Chef::Util::PathHelper.escape_glob_dir(prefix, ".#{@new_resource.path}") + ".chef-*"].sort { |a, b| b <=> a } if backup_files.length >= @new_resource.backup remainder = backup_files.slice(slice_number..-1) remainder.each do |backup_to_delete| diff --git a/lib/chef/deprecation/provider/remote_directory.rb b/lib/chef/deprecation/provider/remote_directory.rb index 4e28fdc3fa..5e5188f28b 100644 --- a/lib/chef/deprecation/provider/remote_directory.rb +++ b/lib/chef/deprecation/provider/remote_directory.rb @@ -33,7 +33,7 @@ class Chef # List all excluding . and .. def ls(path) - files = Dir.glob(::File.join(Chef::Util::PathHelper.escape_glob(path), "**", "*"), + files = Dir.glob(::File.join(Chef::Util::PathHelper.escape_glob_dir(path), "**", "*"), ::File::FNM_DOTMATCH) # Remove current directory and previous directory diff --git a/lib/chef/deprecation/provider/remote_file.rb b/lib/chef/deprecation/provider/remote_file.rb index 9f115a2565..b469609ffe 100644 --- a/lib/chef/deprecation/provider/remote_file.rb +++ b/lib/chef/deprecation/provider/remote_file.rb @@ -73,7 +73,7 @@ class Chef # which tricks Chef::REST into decompressing the response body. In this # case you'd end up with a tar archive (no gzip) named, e.g., foo.tgz, # which is not what you wanted. - if @new_resource.path =~ /gz$/ or source =~ /gz$/ + if @new_resource.path =~ /gz$/ || source =~ /gz$/ opts[:disable_gzip] = true end opts diff --git a/lib/chef/deprecation/warnings.rb b/lib/chef/deprecation/warnings.rb index b015669625..411e95ea39 100644 --- a/lib/chef/deprecation/warnings.rb +++ b/lib/chef/deprecation/warnings.rb @@ -22,7 +22,6 @@ class Chef def add_deprecation_warnings_for(method_names) method_names.each do |name| - m = instance_method(name) define_method(name) do |*args| message = [] message << "Method '#{name}' of '#{self.class}' is deprecated. It will be removed in Chef 13." diff --git a/lib/chef/dsl/declare_resource.rb b/lib/chef/dsl/declare_resource.rb index 9a59859d5a..e57bc0f4c4 100644 --- a/lib/chef/dsl/declare_resource.rb +++ b/lib/chef/dsl/declare_resource.rb @@ -88,9 +88,7 @@ class Chef # def build_resource(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block) created_at ||= caller[0] - Thread.exclusive do - require "chef/resource_builder" unless defined?(Chef::ResourceBuilder) - end + require "chef/resource_builder" unless defined?(Chef::ResourceBuilder) Chef::ResourceBuilder.new( type: type, diff --git a/lib/chef/encrypted_data_bag_item/assertions.rb b/lib/chef/encrypted_data_bag_item/assertions.rb index bbdcf7a721..e8f8bfcbf2 100644 --- a/lib/chef/encrypted_data_bag_item/assertions.rb +++ b/lib/chef/encrypted_data_bag_item/assertions.rb @@ -27,7 +27,7 @@ class Chef::EncryptedDataBagItem module Assertions def assert_format_version_acceptable!(format_version) - unless format_version.kind_of?(Integer) and format_version >= Chef::Config[:data_bag_decrypt_minimum_version] + unless format_version.kind_of?(Integer) && format_version >= Chef::Config[:data_bag_decrypt_minimum_version] raise UnacceptableEncryptedDataBagItemFormat, "The encrypted data bag item has format version `#{format_version}', " + "but the config setting 'data_bag_decrypt_minimum_version' requires version `#{Chef::Config[:data_bag_decrypt_minimum_version]}'" diff --git a/lib/chef/encrypted_data_bag_item/decryptor.rb b/lib/chef/encrypted_data_bag_item/decryptor.rb index a002a98a79..773ff4e154 100644 --- a/lib/chef/encrypted_data_bag_item/decryptor.rb +++ b/lib/chef/encrypted_data_bag_item/decryptor.rb @@ -92,8 +92,8 @@ class Chef::EncryptedDataBagItem plaintext = openssl_decryptor.update(encrypted_bytes) plaintext << openssl_decryptor.final rescue OpenSSL::Cipher::CipherError => e - # if the key length is less than 150 characters, and it contains slashes, we think it may be a path. - raise DecryptionFailure, "Error decrypting data bag value: '#{e.message}'. Most likely the provided key is incorrect. #{ @key.length < 255 and @key.include?('/') ? 'You may need to use --secret-file rather than --secret.' : '' }" + # if the key length is less than 255 characters, and it contains slashes, we think it may be a path. + raise DecryptionFailure, "Error decrypting data bag value: '#{e.message}'. Most likely the provided key is incorrect. #{ (@key.length < 255 && @key.include?('/')) ? 'You may need to use --secret-file rather than --secret.' : '' }" end end @@ -143,8 +143,8 @@ class Chef::EncryptedDataBagItem plaintext = openssl_decryptor.update(encrypted_bytes) plaintext << openssl_decryptor.final rescue OpenSSL::Cipher::CipherError => e - # if the key length is less than 150 characters, and it contains slashes, we think it may be a path. - raise DecryptionFailure, "Error decrypting data bag value: '#{e.message}'. Most likely the provided key is incorrect. #{ @key.length < 255 and @key.include?('/') ? 'You may need to use --secret-file rather than --secret.' : '' }" + # if the key length is less than 255 characters, and it contains slashes, we think it may be a path. + raise DecryptionFailure, "Error decrypting data bag value: '#{e.message}'. Most likely the provided key is incorrect. #{ ( @key.length < 255 && @key.include?('/')) ? 'You may need to use --secret-file rather than --secret.' : '' }" end end diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb index a6a18718c2..b3271a139a 100644 --- a/lib/chef/event_dispatch/base.rb +++ b/lib/chef/event_dispatch/base.rb @@ -139,6 +139,26 @@ class Chef def cookbook_sync_complete end + # Called when starting to collect gems from the cookbooks + def cookbook_gem_start(gems) + end + + # Called when the result of installing the bundle is to install the gem + def cookbook_gem_installing(gem, version) + end + + # Called when the result of installing the bundle is to use the gem + def cookbook_gem_using(gem, version) + end + + # Called when finished installing cookbook gems + def cookbook_gem_finished + end + + # Called when cookbook gem installation fails + def cookbook_gem_failed(exception) + end + ## TODO: add cookbook name to the API for file load callbacks ## TODO: add callbacks for overall cookbook eval start and complete. diff --git a/lib/chef/event_loggers/base.rb b/lib/chef/event_loggers/base.rb index c34ed2267d..3c11e809f6 100644 --- a/lib/chef/event_loggers/base.rb +++ b/lib/chef/event_loggers/base.rb @@ -42,8 +42,8 @@ class Chef end def self.new(name) - event_logger_class = by_name(name.to_s) or - raise UnknownEventLogger, "No event logger found for #{name} (available: #{available_event_loggers.join(', ')})" + event_logger_class = by_name(name.to_s) + raise UnknownEventLogger, "No event logger found for #{name} (available: #{available_event_loggers.join(', ')})" unless event_logger_class raise UnavailableEventLogger unless available_event_loggers.include? name.to_s event_logger_class.new end diff --git a/lib/chef/file_access_control/unix.rb b/lib/chef/file_access_control/unix.rb index eec9c62701..1746db44d3 100644 --- a/lib/chef/file_access_control/unix.rb +++ b/lib/chef/file_access_control/unix.rb @@ -117,7 +117,7 @@ class Chef end def gid_from_resource(resource) - return nil if resource == nil or resource.group.nil? + return nil if resource == nil || resource.group.nil? if resource.group.kind_of?(String) diminished_radix_complement( Etc.getgrnam(resource.group).gid ) elsif resource.group.kind_of?(Integer) @@ -168,7 +168,7 @@ class Chef end def mode_from_resource(res) - return nil if res == nil or res.mode.nil? + return nil if res == nil || res.mode.nil? (res.mode.respond_to?(:oct) ? res.mode.oct : res.mode.to_i) & 007777 end @@ -197,7 +197,7 @@ class Chef # the user has specified a permission, and it does not match the file, so fix the permission Chef::Log.debug("Found target_mode != current_mode, updating mode") return true - elsif suid_bit_set? and (should_update_group? or should_update_owner?) + elsif suid_bit_set? && (should_update_group? || should_update_owner?) return true else Chef::Log.debug("Found target_mode == current_mode, not updating mode") @@ -264,7 +264,7 @@ class Chef end def uid_from_resource(resource) - return nil if resource == nil or resource.owner.nil? + return nil if resource == nil || resource.owner.nil? if resource.owner.kind_of?(String) diminished_radix_complement( Etc.getpwnam(resource.owner).uid ) elsif resource.owner.kind_of?(Integer) diff --git a/lib/chef/file_access_control/windows.rb b/lib/chef/file_access_control/windows.rb index 7f27ef8df0..6b7184bbd3 100644 --- a/lib/chef/file_access_control/windows.rb +++ b/lib/chef/file_access_control/windows.rb @@ -319,7 +319,7 @@ class Chef def target_group return nil if resource.group.nil? - sid = get_sid(resource.group) + get_sid(resource.group) end def target_inherits @@ -328,7 +328,7 @@ class Chef def target_owner return nil if resource.owner.nil? - sid = get_sid(resource.owner) + get_sid(resource.owner) end end end diff --git a/lib/chef/file_cache.rb b/lib/chef/file_cache.rb index b4beee4a66..cefc9da1eb 100644 --- a/lib/chef/file_cache.rb +++ b/lib/chef/file_cache.rb @@ -158,9 +158,9 @@ class Chef # [String] - An array of file cache keys matching the glob def find(glob_pattern) keys = Array.new - Dir[File.join(Chef::Util::PathHelper.escape_glob(file_cache_path), glob_pattern)].each do |f| + Dir[File.join(Chef::Util::PathHelper.escape_glob_dir(file_cache_path), glob_pattern)].each do |f| if File.file?(f) - keys << f[/^#{Regexp.escape(Dir[Chef::Util::PathHelper.escape_glob(file_cache_path)].first) + File::Separator}(.+)/, 1] + keys << f[/^#{Regexp.escape(Dir[Chef::Util::PathHelper.escape_glob_dir(file_cache_path)].first) + File::Separator}(.+)/, 1] end end keys diff --git a/lib/chef/formatters/base.rb b/lib/chef/formatters/base.rb index b2a8c8099b..90925ffdb4 100644 --- a/lib/chef/formatters/base.rb +++ b/lib/chef/formatters/base.rb @@ -51,8 +51,8 @@ class Chef #-- # TODO: is it too clever to be defining new() on a module like this? def self.new(name, out, err) - formatter_class = by_name(name.to_s) or - raise UnknownFormatter, "No output formatter found for #{name} (available: #{available_formatters.join(', ')})" + formatter_class = by_name(name.to_s) + raise UnknownFormatter, "No output formatter found for #{name} (available: #{available_formatters.join(', ')})" unless formatter_class formatter_class.new(out, err) end diff --git a/lib/chef/formatters/doc.rb b/lib/chef/formatters/doc.rb index 5462241049..3f832f1e92 100644 --- a/lib/chef/formatters/doc.rb +++ b/lib/chef/formatters/doc.rb @@ -180,6 +180,32 @@ class Chef unindent end + # Called when starting to collect gems from the cookbooks + def cookbook_gem_start(gems) + puts_line "Installing Cookbook Gems:" + indent + end + + # Called when the result of installing the bundle is to install the gem + def cookbook_gem_installing(gem, version) + puts_line "- Installing #{gem} #{version}", :green + end + + # Called when the result of installing the bundle is to use the gem + def cookbook_gem_using(gem, version) + puts_line "- Using #{gem} #{version}" + end + + # Called when finished installing cookbook gems + def cookbook_gem_finished + unindent + end + + # Called when cookbook gem installation fails + def cookbook_gem_failed(exception) + unindent + end + # Called when cookbook loading starts. def library_load_start(file_count) puts_line "Compiling Cookbooks..." diff --git a/lib/chef/formatters/error_descriptor.rb b/lib/chef/formatters/error_descriptor.rb index 0f14e6e783..1a40f785cb 100644 --- a/lib/chef/formatters/error_descriptor.rb +++ b/lib/chef/formatters/error_descriptor.rb @@ -31,7 +31,7 @@ class Chef end def section(heading, text) - @sections << { heading => (text or "") } + @sections << { heading => (text || "") } end def display(out) diff --git a/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb b/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb index f5936285be..94ecce88de 100644 --- a/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb +++ b/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb @@ -63,7 +63,7 @@ class Chef def recipe_snippet return nil if dynamic_resource? @snippet ||= begin - if file = parse_source and line = parse_line(file) + if (file = parse_source) && (line = parse_line(file)) return nil unless ::File.exists?(file) lines = IO.readlines(file) diff --git a/lib/chef/guard_interpreter/resource_guard_interpreter.rb b/lib/chef/guard_interpreter/resource_guard_interpreter.rb index c21961479c..6df60aec89 100644 --- a/lib/chef/guard_interpreter/resource_guard_interpreter.rb +++ b/lib/chef/guard_interpreter/resource_guard_interpreter.rb @@ -22,7 +22,7 @@ class Chef class GuardInterpreter class ResourceGuardInterpreter < DefaultGuardInterpreter - def initialize(parent_resource, command, opts, &block) + def initialize(parent_resource, command, opts) super(command, opts) @parent_resource = parent_resource @resource = get_interpreter_resource(parent_resource) diff --git a/lib/chef/http.rb b/lib/chef/http.rb index a3673ce281..15fb20d588 100644 --- a/lib/chef/http.rb +++ b/lib/chef/http.rb @@ -159,7 +159,10 @@ class Chef # # If no block is given, the tempfile is returned, which means it's up to # you to unlink the tempfile when you're done with it. - def streaming_request(path, headers = {}, &block) + # + # @yield [tempfile] block to process the tempfile + # @yieldparams [tempfile<Tempfile>] tempfile + def streaming_request(path, headers = {}) url = create_url(path) response, rest_request, return_value = nil, nil, nil tempfile = nil @@ -218,7 +221,7 @@ class Chef return path if path.is_a?(URI) if path =~ /^(http|https|chefzero):\/\//i URI.parse(path) - elsif path.nil? or path.empty? + elsif path.nil? || path.empty? URI.parse(@url) else # The regular expressions used here are to make sure '@url' does not have diff --git a/lib/chef/http/authenticator.rb b/lib/chef/http/authenticator.rb index b5e28cf54d..84065bf816 100644 --- a/lib/chef/http/authenticator.rb +++ b/lib/chef/http/authenticator.rb @@ -47,7 +47,7 @@ class Chef end def handle_request(method, url, headers = {}, data = false) - headers.merge!({ "X-Ops-Server-API-Version" => @api_version }) + headers["X-Ops-Server-API-Version"] = @api_version headers.merge!(authentication_headers(method, url, data, headers)) if sign_requests? [method, url, headers, data] end diff --git a/lib/chef/http/basic_client.rb b/lib/chef/http/basic_client.rb index e0a02a05cf..58ae496418 100644 --- a/lib/chef/http/basic_client.rb +++ b/lib/chef/http/basic_client.rb @@ -104,7 +104,7 @@ class Chef # proxy before parsing. The regex /^.*:\/\// matches, for example, http://. Reusing proxy # here since we are really just trying to get the string built correctly. if String === proxy && !proxy.strip.empty? - if proxy.match(/^.*:\/\//) + if proxy =~ /^.*:\/\// proxy = URI.parse(proxy.strip) else proxy = URI.parse("#{url.scheme}://#{proxy.strip}") diff --git a/lib/chef/http/remote_request_id.rb b/lib/chef/http/remote_request_id.rb index ef8a18a1e3..a779df805e 100644 --- a/lib/chef/http/remote_request_id.rb +++ b/lib/chef/http/remote_request_id.rb @@ -25,7 +25,7 @@ class Chef end def handle_request(method, url, headers = {}, data = false) - headers.merge!({ "X-REMOTE-REQUEST-ID" => Chef::RequestID.instance.request_id }) + headers["X-REMOTE-REQUEST-ID"] = Chef::RequestID.instance.request_id [method, url, headers, data] end diff --git a/lib/chef/http/socketless_chef_zero_client.rb b/lib/chef/http/socketless_chef_zero_client.rb index c8590903f6..1acac5e758 100644 --- a/lib/chef/http/socketless_chef_zero_client.rb +++ b/lib/chef/http/socketless_chef_zero_client.rb @@ -67,7 +67,7 @@ class Chef end if block_given? - block.call(@body) + yield(@body) else super end @@ -148,7 +148,8 @@ class Chef @url.port end - def request(method, url, body, headers, &handler_block) + # FIXME: yard with @yield + def request(method, url, body, headers) request = req_to_rack(method, url, body, headers) res = ChefZero::SocketlessServerMap.request(port, request) @@ -176,7 +177,8 @@ class Chef def to_net_http(code, headers, chunked_body) body = chunked_body.join("") - msg = STATUS_MESSAGE[code] or raise "Cannot determine HTTP status message for code #{code}" + msg = STATUS_MESSAGE[code] + raise "Cannot determine HTTP status message for code #{code}" unless msg response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg) response.instance_variable_set(:@body, body) headers.each do |name, value| diff --git a/lib/chef/http/ssl_policies.rb b/lib/chef/http/ssl_policies.rb index 51db01c232..a3692b81b6 100644 --- a/lib/chef/http/ssl_policies.rb +++ b/lib/chef/http/ssl_policies.rb @@ -77,7 +77,7 @@ class Chef http_client.cert_store.set_default_paths end if config.trusted_certs_dir - certs = Dir.glob(File.join(Chef::Util::PathHelper.escape_glob(config.trusted_certs_dir), "*.{crt,pem}")) + certs = Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(config.trusted_certs_dir), "*.{crt,pem}")) certs.each do |cert_file| cert = OpenSSL::X509::Certificate.new(File.read(cert_file)) add_trusted_cert(cert) @@ -118,7 +118,7 @@ class Chef class APISSLPolicy < DefaultSSLPolicy def set_verify_mode - if config[:ssl_verify_mode] == :verify_peer or config[:verify_api_cert] + if config[:ssl_verify_mode] == :verify_peer || config[:verify_api_cert] http_client.verify_mode = OpenSSL::SSL::VERIFY_PEER elsif config[:ssl_verify_mode] == :verify_none http_client.verify_mode = OpenSSL::SSL::VERIFY_NONE diff --git a/lib/chef/http/validate_content_length.rb b/lib/chef/http/validate_content_length.rb index 81d3b0fb74..c1073867d3 100644 --- a/lib/chef/http/validate_content_length.rb +++ b/lib/chef/http/validate_content_length.rb @@ -84,7 +84,6 @@ class Chef def validate(http_response, response_length) content_length = response_content_length(http_response) transfer_encoding = http_response["transfer-encoding"] - content_encoding = http_response["content-encoding"] if content_length.nil? Chef::Log.debug "HTTP server did not include a Content-Length header in response, cannot identify truncated downloads." diff --git a/lib/chef/json_compat.rb b/lib/chef/json_compat.rb index 26d3751897..f8f05a0074 100644 --- a/lib/chef/json_compat.rb +++ b/lib/chef/json_compat.rb @@ -61,7 +61,7 @@ class Chef # JSON gem requires top level object to be a Hash or Array (otherwise # you get the "must contain two octets" error). Yajl doesn't impose the # same limitation. For compatibility, we re-impose this condition. - unless obj.kind_of?(Hash) or obj.kind_of?(Array) + unless obj.kind_of?(Hash) || obj.kind_of?(Array) raise Chef::Exceptions::JSON::ParseError, "Top level JSON object must be a Hash or Array. (actual: #{obj.class})" end diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb index 657216bcf0..a27a3b332b 100644 --- a/lib/chef/knife.rb +++ b/lib/chef/knife.rb @@ -145,6 +145,11 @@ class Chef end def self.subcommand_class_from(args) + if args.size == 1 && args[0].strip.downcase == "rehash" + # To prevent issues with the rehash file not pointing to the correct plugins, + # we always use the glob loader when regenerating the rehash file + @subcommand_loader = Chef::Knife::SubcommandLoader.gem_glob_loader(chef_config_dir) + end subcommand_loader.command_class_from(args) || subcommand_not_found!(args) end @@ -510,11 +515,12 @@ class Chef response.body end - def create_object(object, pretty_name = nil, object_class: nil, &block) + # FIXME: yard with @yield + def create_object(object, pretty_name = nil, object_class: nil) output = edit_data(object, object_class: object_class) if Kernel.block_given? - output = block.call(output) + output = yield(output) else output.save end @@ -526,11 +532,12 @@ class Chef output(output) if config[:print_after] end - def delete_object(klass, name, delete_name = nil, &block) + # FIXME: yard with @yield + def delete_object(klass, name, delete_name = nil) confirm("Do you really want to delete #{name}") if Kernel.block_given? - object = block.call + object = yield else object = klass.load(name) object.destroy diff --git a/lib/chef/knife/cookbook_bulk_delete.rb b/lib/chef/knife/cookbook_bulk_delete.rb index 6c2ad5a53f..bd1c8a22cc 100644 --- a/lib/chef/knife/cookbook_bulk_delete.rb +++ b/lib/chef/knife/cookbook_bulk_delete.rb @@ -61,7 +61,7 @@ class Chef cookbooks_names.each do |cookbook_name| versions = rest.get("cookbooks/#{cookbook_name}")[cookbook_name]["versions"].map { |v| v["version"] }.flatten versions.each do |version| - object = rest.delete("cookbooks/#{cookbook_name}/#{version}#{config[:purge] ? "?purge=true" : ""}") + rest.delete("cookbooks/#{cookbook_name}/#{version}#{config[:purge] ? "?purge=true" : ""}") ui.info("Deleted cookbook #{cookbook_name.ljust(25)} [#{version}]") end end diff --git a/lib/chef/knife/cookbook_metadata.rb b/lib/chef/knife/cookbook_metadata.rb index bfae9d8814..29eba6a36a 100644 --- a/lib/chef/knife/cookbook_metadata.rb +++ b/lib/chef/knife/cookbook_metadata.rb @@ -80,7 +80,6 @@ class Chef File.open(json_file, "w") do |f| f.write(Chef::JSONCompat.to_json_pretty(md)) end - generated = true Chef::Log.debug("Generated #{json_file}") rescue Exceptions::ObsoleteDependencySyntax, Exceptions::InvalidVersionConstraint => e ui.stderr.puts "ERROR: The cookbook '#{cookbook}' contains invalid or obsolete metadata syntax." diff --git a/lib/chef/knife/cookbook_site_download.rb b/lib/chef/knife/cookbook_site_download.rb index 2bdeea9781..7d0e21791d 100644 --- a/lib/chef/knife/cookbook_site_download.rb +++ b/lib/chef/knife/cookbook_site_download.rb @@ -98,11 +98,11 @@ class Chef end def replacement_cookbook - replacement = File.basename(current_cookbook_data["replacement"]) + File.basename(current_cookbook_data["replacement"]) end def specific_cookbook_version_url - "#{cookbooks_api_url}/#{@name_args[0]}/versions/#{@name_args[1].gsub('.', '_')}" + "#{cookbooks_api_url}/#{@name_args[0]}/versions/#{@name_args[1].tr('.', '_')}" end end end diff --git a/lib/chef/knife/cookbook_site_install.rb b/lib/chef/knife/cookbook_site_install.rb index 01374b9b36..802fdd792b 100644 --- a/lib/chef/knife/cookbook_site_install.rb +++ b/lib/chef/knife/cookbook_site_install.rb @@ -123,7 +123,7 @@ class Chef ui.error("Please specify a cookbook to download and install.") exit 1 elsif name_args.size >= 2 - unless name_args.last.match(/^(\d+)(\.\d+){1,2}$/) and name_args.size == 2 + unless name_args.last.match(/^(\d+)(\.\d+){1,2}$/) && name_args.size == 2 ui.error("Installing multiple cookbooks at once is not supported.") exit 1 end diff --git a/lib/chef/knife/cookbook_site_show.rb b/lib/chef/knife/cookbook_site_show.rb index a6a4c82c85..c0280cb318 100644 --- a/lib/chef/knife/cookbook_site_show.rb +++ b/lib/chef/knife/cookbook_site_show.rb @@ -33,7 +33,7 @@ class Chef when 1 noauth_rest.get("https://supermarket.chef.io/api/v1/cookbooks/#{@name_args[0]}") when 2 - noauth_rest.get("https://supermarket.chef.io/api/v1/cookbooks/#{@name_args[0]}/versions/#{name_args[1].gsub('.', '_')}") + noauth_rest.get("https://supermarket.chef.io/api/v1/cookbooks/#{@name_args[0]}/versions/#{name_args[1].tr('.', '_')}") end end diff --git a/lib/chef/knife/cookbook_upload.rb b/lib/chef/knife/cookbook_upload.rb index 72f7d9d2d9..6938ac280d 100644 --- a/lib/chef/knife/cookbook_upload.rb +++ b/lib/chef/knife/cookbook_upload.rb @@ -86,7 +86,7 @@ class Chef config[:cookbook_path] ||= Chef::Config[:cookbook_path] - if @name_args.empty? and ! config[:all] + if @name_args.empty? && ! config[:all] show_usage ui.fatal("You must specify the --all flag or at least one cookbook name") exit 1 diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb index 7ad70bc627..48d2cb9e77 100644 --- a/lib/chef/knife/core/bootstrap_context.rb +++ b/lib/chef/knife/core/bootstrap_context.rb @@ -143,7 +143,7 @@ CONFIG # If the user doesn't have a client path configure, let bash use the PATH for what it was designed for client_path = @chef_config[:chef_client_path] || "chef-client" s = "#{client_path} -j /etc/chef/first-boot.json" - s << " -l debug" if @config[:verbosity] and @config[:verbosity] >= 2 + s << " -l debug" if @config[:verbosity] && @config[:verbosity] >= 2 s << " -E #{bootstrap_environment}" unless bootstrap_environment.nil? s << " --no-color" unless @config[:color] s @@ -182,9 +182,10 @@ CONFIG def first_boot (@config[:first_boot_attributes] || {}).tap do |attributes| if @config[:policy_name] && @config[:policy_group] - attributes.merge!(:policy_name => @config[:policy_name], :policy_group => @config[:policy_group]) + attributes[:policy_name] = @config[:policy_name] + attributes[:policy_group] = @config[:policy_group] else - attributes.merge!(:run_list => @run_list) + attributes[:run_list] = @run_list end attributes.merge!(:tags => @config[:tags]) if @config[:tags] && !@config[:tags].empty? @@ -198,7 +199,7 @@ CONFIG def trusted_certs_content content = "" if @chef_config[:trusted_certs_dir] - Dir.glob(File.join(Chef::Util::PathHelper.escape_glob(@chef_config[:trusted_certs_dir]), "*.{crt,pem}")).each do |cert| + Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(@chef_config[:trusted_certs_dir]), "*.{crt,pem}")).each do |cert| content << "cat > /etc/chef/trusted_certs/#{File.basename(cert)} <<'EOP'\n" + IO.read(File.expand_path(cert)) + "\nEOP\n" end diff --git a/lib/chef/knife/core/custom_manifest_loader.rb b/lib/chef/knife/core/custom_manifest_loader.rb index e5ebce2585..9fe51599af 100644 --- a/lib/chef/knife/core/custom_manifest_loader.rb +++ b/lib/chef/knife/core/custom_manifest_loader.rb @@ -61,7 +61,7 @@ class Chef end def subcommand_files - subcommand_files ||= (find_subcommands_via_manifest.values + site_subcommands).flatten.uniq + @subcommand_files ||= (find_subcommands_via_manifest.values + site_subcommands).flatten.uniq end end end diff --git a/lib/chef/knife/core/gem_glob_loader.rb b/lib/chef/knife/core/gem_glob_loader.rb index 78726feee7..f5eff26903 100644 --- a/lib/chef/knife/core/gem_glob_loader.rb +++ b/lib/chef/knife/core/gem_glob_loader.rb @@ -47,7 +47,7 @@ class Chef def find_subcommands_via_dirglob # The "require paths" of the core knife subcommands bundled with chef - files = Dir[File.join(Chef::Util::PathHelper.escape_glob(File.expand_path("../../../knife", __FILE__)), "*.rb")] + files = Dir[File.join(Chef::Util::PathHelper.escape_glob_dir(File.expand_path("../../../knife", __FILE__)), "*.rb")] subcommand_files = {} files.each do |knife_file| rel_path = knife_file[/#{CHEF_ROOT}#{Regexp.escape(File::SEPARATOR)}(.*)\.rb/, 1] @@ -82,7 +82,7 @@ class Chef if check_load_path files = $LOAD_PATH.map { |load_path| - Dir["#{File.expand_path glob, Chef::Util::PathHelper.escape_glob(load_path)}#{Gem.suffix_pattern}"] + Dir["#{File.expand_path glob, Chef::Util::PathHelper.escape_glob_dir(load_path)}#{Gem.suffix_pattern}"] }.flatten.select { |file| File.file? file.untaint } end @@ -116,7 +116,7 @@ class Chef spec.require_paths.first end - glob = File.join(Chef::Util::PathHelper.escape_glob(spec.full_gem_path, dirs), glob) + glob = File.join(Chef::Util::PathHelper.escape_glob_dir(spec.full_gem_path, dirs), glob) Dir[glob].map { |f| f.untaint } end diff --git a/lib/chef/knife/core/generic_presenter.rb b/lib/chef/knife/core/generic_presenter.rb index 61069cff48..f273cb5bca 100644 --- a/lib/chef/knife/core/generic_presenter.rb +++ b/lib/chef/knife/core/generic_presenter.rb @@ -86,7 +86,7 @@ class Chef require "stringio" # If you were looking for some attribute and there is only one match # just dump the attribute value - if config[:attribute] and data.length == 1 + if config[:attribute] && data.length == 1 data.values[0] else out = StringIO.new diff --git a/lib/chef/knife/core/hashed_command_loader.rb b/lib/chef/knife/core/hashed_command_loader.rb index 7b6c1c4c08..1165af6eb2 100644 --- a/lib/chef/knife/core/hashed_command_loader.rb +++ b/lib/chef/knife/core/hashed_command_loader.rb @@ -40,9 +40,29 @@ class Chef def list_commands(pref_category = nil) if pref_category || manifest[KEY]["plugins_by_category"].key?(pref_category) - { pref_category => manifest[KEY]["plugins_by_category"][pref_category] } + commands = { pref_category => manifest[KEY]["plugins_by_category"][pref_category] } else - manifest[KEY]["plugins_by_category"] + commands = manifest[KEY]["plugins_by_category"] + end + # If any of the specified plugins in the manifest dont have a valid path we will + # eventually get an error and the user will need to rehash - instead, lets just + # print out 1 error here telling them to rehash + errors = {} + commands.collect { |k, v| v }.flatten.each do |command| + paths = manifest[KEY]["plugins_paths"][command] + if paths && paths.is_a?(Array) + # It is only an error if all the paths don't exist + if paths.all? { |sc| !File.exists?(sc) } + errors[command] = paths + end + end + end + if errors.empty? + commands + else + Chef::Log.error "There are files specified in the manifest that are missing. Please rehash to update the subcommands cache. If you see this error after rehashing delete the cache at #{Chef::Knife::SubcommandLoader.plugin_manifest_path}" + Chef::Log.error "Missing files:\n\t#{errors.values.flatten.join("\n\t")}" + {} end end @@ -59,7 +79,6 @@ class Chef if File.exists?(sc) Kernel.load sc else - Chef::Log.error "The file #{sc} is missing for subcommand '#{subcommand_for_args(args)}'. Please rehash to update the subcommands cache." return false end end diff --git a/lib/chef/knife/core/node_editor.rb b/lib/chef/knife/core/node_editor.rb index 0f7e51cdf3..b009bf8652 100644 --- a/lib/chef/knife/core/node_editor.rb +++ b/lib/chef/knife/core/node_editor.rb @@ -96,7 +96,7 @@ class Chef # @api private def apply_updates(updated_data) - if node.name and node.name != updated_data["name"] + if node.name && node.name != updated_data["name"] ui.warn "Changing the name of a node results in a new node being created, #{node.name} will not be modified or removed." ui.confirm "Proceed with creation of new node" end diff --git a/lib/chef/knife/core/object_loader.rb b/lib/chef/knife/core/object_loader.rb index 04496933e4..b08483f9a2 100644 --- a/lib/chef/knife/core/object_loader.rb +++ b/lib/chef/knife/core/object_loader.rb @@ -71,14 +71,14 @@ class Chef # # @api public def find_all_objects(path) - path = File.join(Chef::Util::PathHelper.escape_glob(File.expand_path(path)), "*") + path = File.join(Chef::Util::PathHelper.escape_glob_dir(File.expand_path(path)), "*") path << ".{json,rb}" objects = Dir.glob(path) objects.map { |o| File.basename(o) } end def find_all_object_dirs(path) - path = File.join(Chef::Util::PathHelper.escape_glob(File.expand_path(path)), "*") + path = File.join(Chef::Util::PathHelper.escape_glob_dir(File.expand_path(path)), "*") objects = Dir.glob(path) objects.delete_if { |o| !File.directory?(o) } objects.map { |o| File.basename(o) } diff --git a/lib/chef/knife/core/subcommand_loader.rb b/lib/chef/knife/core/subcommand_loader.rb index 95ab219c80..0dcb54fc0d 100644 --- a/lib/chef/knife/core/subcommand_loader.rb +++ b/lib/chef/knife/core/subcommand_loader.rb @@ -58,6 +58,12 @@ class Chef end end + # There are certain situations where we want to shortcut the loader selection + # in self.for_config and force using the GemGlobLoader + def self.gem_glob_loader(chef_config_dir) + Knife::SubcommandLoader::GemGlobLoader.new(chef_config_dir) + end + def self.plugin_manifest? plugin_manifest_path && File.exist?(plugin_manifest_path) end @@ -118,7 +124,7 @@ class Chef load_command(cmd_words) result = Chef::Knife.subcommands[find_longest_key(Chef::Knife.subcommands, cmd_words, "_")] - result || Chef::Knife.subcommands[args.first.gsub("-", "_")] + result || Chef::Knife.subcommands[args.first.tr("-", "_")] end def guess_category(args) @@ -133,7 +139,7 @@ class Chef # def find_subcommands_via_dirglob # The "require paths" of the core knife subcommands bundled with chef - files = Dir[File.join(Chef::Util::PathHelper.escape_glob(File.expand_path("../../../knife", __FILE__)), "*.rb")] + files = Dir[File.join(Chef::Util::PathHelper.escape_glob_dir(File.expand_path("../../../knife", __FILE__)), "*.rb")] subcommand_files = {} files.each do |knife_file| rel_path = knife_file[/#{CHEF_ROOT}#{Regexp.escape(File::SEPARATOR)}(.*)\.rb/, 1] @@ -191,12 +197,12 @@ Please use Chef::Knife::SubcommandLoader.for_config(chef_config_dir, env)" user_specific_files = [] if chef_config_dir - user_specific_files.concat Dir.glob(File.expand_path("plugins/knife/*.rb", Chef::Util::PathHelper.escape_glob(chef_config_dir))) + user_specific_files.concat Dir.glob(File.expand_path("plugins/knife/*.rb", Chef::Util::PathHelper.escape_glob_dir(chef_config_dir))) end # finally search ~/.chef/plugins/knife/*.rb Chef::Util::PathHelper.home(".chef", "plugins", "knife") do |p| - user_specific_files.concat Dir.glob(File.join(Chef::Util::PathHelper.escape_glob(p), "*.rb")) + user_specific_files.concat Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(p), "*.rb")) end user_specific_files diff --git a/lib/chef/knife/core/ui.rb b/lib/chef/knife/core/ui.rb index 938942c173..67e431f1a7 100644 --- a/lib/chef/knife/core/ui.rb +++ b/lib/chef/knife/core/ui.rb @@ -140,7 +140,7 @@ class Chef def ask_question(question, opts = {}) question = question + "[#{opts[:default]}] " if opts[:default] - if opts[:default] and config[:defaults] + if opts[:default] && config[:defaults] opts[:default] else stdout.print question diff --git a/lib/chef/knife/data_bag_from_file.rb b/lib/chef/knife/data_bag_from_file.rb index e029ec4b22..30b9de3386 100644 --- a/lib/chef/knife/data_bag_from_file.rb +++ b/lib/chef/knife/data_bag_from_file.rb @@ -102,7 +102,7 @@ class Chef paths = Array.new args.each do |path| if File.directory?(path) - paths.concat(Dir.glob(File.join(Chef::Util::PathHelper.escape_glob(path), "*.json"))) + paths.concat(Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(path), "*.json"))) else paths << path end diff --git a/lib/chef/knife/rehash.rb b/lib/chef/knife/rehash.rb index 3e7bab7e0f..79286368f8 100644 --- a/lib/chef/knife/rehash.rb +++ b/lib/chef/knife/rehash.rb @@ -35,7 +35,10 @@ class Chef end def reload_plugins - Chef::Knife::SubcommandLoader::GemGlobLoader.new(@@chef_config_dir).load_commands + # The subcommand_loader for this knife command should _always_ be the GemGlobLoader. The GemGlobLoader loads + # plugins from disc and ensures the hash we write is always correct. By this point it should also already have + # loaded plugins and `load_commands` shouldn't have an effect. + Chef::Knife.subcommand_loader.load_commands end def generate_hash diff --git a/lib/chef/knife/search.rb b/lib/chef/knife/search.rb index 30a3db3cf2..520c9273af 100644 --- a/lib/chef/knife/search.rb +++ b/lib/chef/knife/search.rb @@ -177,7 +177,7 @@ class Chef # See lib/chef/search/query.rb for more examples of this. def create_result_filter(filter_string) final_filter = Hash.new - filter_string.gsub!(" ", "") + filter_string.delete!(" ") filters = filter_string.split(",") filters.each do |f| return_id, attr_path = f.split("=") diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb index 4184171a4e..9c0f8936f0 100644 --- a/lib/chef/knife/ssh.rb +++ b/lib/chef/knife/ssh.rb @@ -424,7 +424,7 @@ class Chef end.join(" \\; ") end - tmux_name = "'knife ssh #{@name_args[0].gsub(/:/, '=')}'" + tmux_name = "'knife ssh #{@name_args[0].tr(':', '=')}'" begin server = session.servers_for.first cmd = ["tmux new-session -d -s #{tmux_name}", diff --git a/lib/chef/knife/ssl_check.rb b/lib/chef/knife/ssl_check.rb index 6dac06b27b..0995fc8a54 100644 --- a/lib/chef/knife/ssl_check.rb +++ b/lib/chef/knife/ssl_check.rb @@ -50,7 +50,7 @@ class Chef end def given_uri - (name_args[0] or Chef::Config.chef_server_url) + (name_args[0] || Chef::Config.chef_server_url) end def host diff --git a/lib/chef/knife/ssl_fetch.rb b/lib/chef/knife/ssl_fetch.rb index f694a46ac6..5af1a905d5 100644 --- a/lib/chef/knife/ssl_fetch.rb +++ b/lib/chef/knife/ssl_fetch.rb @@ -47,7 +47,7 @@ class Chef end def given_uri - (name_args[0] or Chef::Config.chef_server_url) + (name_args[0] || Chef::Config.chef_server_url) end def host diff --git a/lib/chef/knife/status.rb b/lib/chef/knife/status.rb index e7a7165faa..551d5addfc 100644 --- a/lib/chef/knife/status.rb +++ b/lib/chef/knife/status.rb @@ -98,9 +98,9 @@ class Chef output(all_nodes.sort { |n1, n2| if config[:sort_reverse] || Chef::Config[:knife][:sort_status_reverse] - (n2["ohai_time"] or 0) <=> (n1["ohai_time"] or 0) + (n2["ohai_time"] || 0) <=> (n1["ohai_time"] || 0) else - (n1["ohai_time"] or 0) <=> (n2["ohai_time"] or 0) + (n1["ohai_time"] || 0) <=> (n2["ohai_time"] || 0) end }) end diff --git a/lib/chef/log.rb b/lib/chef/log.rb index bfb5829be6..ac2baeb9d1 100644 --- a/lib/chef/log.rb +++ b/lib/chef/log.rb @@ -48,7 +48,7 @@ class Chef # Pick the first caller that is *not* part of the Chef gem, that's the # thing the user wrote. chef_gem_path = File.expand_path("../..", __FILE__) - caller(0..20).select { |c| !c.start_with?(chef_gem_path) }.first + caller(0..20).find { |c| !c.start_with?(chef_gem_path) } end def self.deprecation(msg = nil, location = caller(2..2)[0], &block) diff --git a/lib/chef/mixin/command.rb b/lib/chef/mixin/command.rb index 257ed11221..0cc3143ec7 100644 --- a/lib/chef/mixin/command.rb +++ b/lib/chef/mixin/command.rb @@ -177,13 +177,14 @@ class Chef # module_function :popen4 - def chdir_or_tmpdir(dir, &block) + # FIXME: yard with @yield + def chdir_or_tmpdir(dir) dir ||= Dir.tmpdir unless File.directory?(dir) raise Chef::Exceptions::Exec, "#{dir} does not exist or is not a directory" end Dir.chdir(dir) do - block.call + yield end end diff --git a/lib/chef/mixin/params_validate.rb b/lib/chef/mixin/params_validate.rb index 598c6c3c23..b16df41c8e 100644 --- a/lib/chef/mixin/params_validate.rb +++ b/lib/chef/mixin/params_validate.rb @@ -466,7 +466,7 @@ class Chef # "value nil" and to keep default stickiness working exactly the same # @api private class SetOrReturnProperty < Chef::Property - def get(resource) + def get(resource, nil_set: false) value = super # All values are sticky, frozen or not if !is_set?(resource) @@ -478,7 +478,7 @@ class Chef def call(resource, value = NOT_PASSED) # setting to nil does a get if value.nil? && !explicitly_accepts_nil?(resource) - get(resource) + get(resource, nil_set: true) else super end diff --git a/lib/chef/mixin/properties.rb b/lib/chef/mixin/properties.rb index 2e33d2d0e7..ae2406f1ae 100644 --- a/lib/chef/mixin/properties.rb +++ b/lib/chef/mixin/properties.rb @@ -95,10 +95,11 @@ class Chef def property(name, type = NOT_PASSED, **options) name = name.to_sym - options.each { |k, v| options[k.to_sym] = v if k.is_a?(String) } + options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo } options[:instance_variable_name] = :"@#{name}" if !options.has_key?(:instance_variable_name) - options.merge!(name: name, declared_in: self) + options[:name] = name + options[:declared_in] = self if type == NOT_PASSED # If a type is not passed, the property derives from the diff --git a/lib/chef/mixin/provides.rb b/lib/chef/mixin/provides.rb index 34a078c010..43a726de8c 100644 --- a/lib/chef/mixin/provides.rb +++ b/lib/chef/mixin/provides.rb @@ -7,12 +7,13 @@ class Chef # TODO no longer needed, remove or deprecate? include Chef::Mixin::DescendantsTracker - def provides(short_name, opts = {}, &block) + def provides(short_name, opts = {}) raise NotImplementedError, :provides end # Check whether this resource provides the resource_name DSL for the given # node. TODO remove this when we stop checking unregistered things. + # FIXME: yard with @yield def provides?(node, resource) raise NotImplementedError, :provides? end diff --git a/lib/chef/mixin/template.rb b/lib/chef/mixin/template.rb index c423ccaa42..b10e036c4e 100644 --- a/lib/chef/mixin/template.rb +++ b/lib/chef/mixin/template.rb @@ -186,7 +186,7 @@ class Chef module_names.each do |mod| context_methods = [:node, :render, :render_template, :render_template_from_string] context_methods.each do |core_method| - if mod.method_defined?(core_method) or mod.private_method_defined?(core_method) + if mod.method_defined?(core_method) || mod.private_method_defined?(core_method) Chef::Log.warn("Core template method `#{core_method}' overridden by extension module #{mod}") end end diff --git a/lib/chef/mixin/why_run.rb b/lib/chef/mixin/why_run.rb index b2aa5949c0..ea62527bdd 100644 --- a/lib/chef/mixin/why_run.rb +++ b/lib/chef/mixin/why_run.rb @@ -49,7 +49,7 @@ class Chef def add_action(descriptions, &block) @actions << [descriptions, block] if (@resource.respond_to?(:is_guard_interpreter) && @resource.is_guard_interpreter) || !Chef::Config[:why_run] - block.call + yield end events.resource_update_applied(@resource, @action, descriptions) end @@ -319,7 +319,7 @@ class Chef def run(action) @assertions[action.to_sym].each do |a| a.run(action, events, @resource) - if a.assertion_failed? and a.block_action? + if a.assertion_failed? && a.block_action? @blocked_actions << action break end diff --git a/lib/chef/mixin/wide_string.rb b/lib/chef/mixin/wide_string.rb index 4566bdd382..4342ef1650 100644 --- a/lib/chef/mixin/wide_string.rb +++ b/lib/chef/mixin/wide_string.rb @@ -34,7 +34,7 @@ class Chef ustring = (ustring + "").force_encoding("UTF-8") if ustring.respond_to?(:force_encoding) && ustring.encoding.name != "UTF-8" # ensure we have the double-null termination Windows Wide likes - ustring = ustring + "\000\000" if ustring.length == 0 or ustring[-1].chr != "\000" + ustring = ustring + "\000\000" if ustring.length == 0 || ustring[-1].chr != "\000" # encode it all as UTF-16LE AKA Windows Wide Character AKA Windows Unicode ustring = begin diff --git a/lib/chef/monkey_patches/net-ssh-multi.rb b/lib/chef/monkey_patches/net-ssh-multi.rb index b0d05a0b27..7b7b1bbf7f 100644 --- a/lib/chef/monkey_patches/net-ssh-multi.rb +++ b/lib/chef/monkey_patches/net-ssh-multi.rb @@ -119,7 +119,8 @@ if Net::SSH::Multi::Version::STRING == "1.1.0" || Net::SSH::Multi::Version::STRI count = concurrent_connections ? (concurrent_connections - open_connections) : @pending_sessions.length count.times do - session = @pending_sessions.pop or break + session = @pending_sessions.pop + break unless session # ===== PATCH START # Increment the open_connections count here to prevent # creation of connection thread again before that is diff --git a/lib/chef/monologger.rb b/lib/chef/monologger.rb index 49f744e314..8bcdae1293 100644 --- a/lib/chef/monologger.rb +++ b/lib/chef/monologger.rb @@ -42,7 +42,7 @@ class MonoLogger < Logger def initialize(log = nil) @dev = @filename = @shift_age = @shift_size = nil - if log.respond_to?(:write) and log.respond_to?(:close) + if log.respond_to?(:write) && log.respond_to?(:close) @dev = log else @dev = open_logfile(log) diff --git a/lib/chef/policy_builder/dynamic.rb b/lib/chef/policy_builder/dynamic.rb index c6c7deeee6..389f124f84 100644 --- a/lib/chef/policy_builder/dynamic.rb +++ b/lib/chef/policy_builder/dynamic.rb @@ -139,7 +139,7 @@ class Chef # # @return [PolicyBuilder::Policyfile, PolicyBuilder::ExpandNodeObject] def implementation - @implementation or raise Exceptions::InvalidPolicybuilderCall, "#load_node must be called before other policy builder methods" + @implementation || raise(Exceptions::InvalidPolicybuilderCall, "#load_node must be called before other policy builder methods") end # @api private diff --git a/lib/chef/policy_builder/expand_node_object.rb b/lib/chef/policy_builder/expand_node_object.rb index 6a006ec992..980de60dd5 100644 --- a/lib/chef/policy_builder/expand_node_object.rb +++ b/lib/chef/policy_builder/expand_node_object.rb @@ -3,7 +3,7 @@ # Author:: Tim Hinderliter (<tim@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) # Author:: Daniel DeLeo (<dan@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software, Inc. +# Copyright:: Copyright 2008-2016 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -75,12 +75,16 @@ class Chef cl.load_cookbooks cookbook_collection = Chef::CookbookCollection.new(cl) cookbook_collection.validate! + cookbook_collection.install_gems(events) + run_context = Chef::RunContext.new(node, cookbook_collection, @events) else Chef::Cookbook::FileVendor.fetch_from_remote(api_service) cookbook_hash = sync_cookbooks cookbook_collection = Chef::CookbookCollection.new(cookbook_hash) cookbook_collection.validate! + cookbook_collection.install_gems(events) + run_context = Chef::RunContext.new(node, cookbook_collection, @events) end diff --git a/lib/chef/policy_builder/policyfile.rb b/lib/chef/policy_builder/policyfile.rb index 679e3cfe47..05e5c2f3ef 100644 --- a/lib/chef/policy_builder/policyfile.rb +++ b/lib/chef/policy_builder/policyfile.rb @@ -3,7 +3,7 @@ # Author:: Tim Hinderliter (<tim@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) # Author:: Daniel DeLeo (<dan@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software, Inc. +# Copyright:: Copyright 2008-2016 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -153,6 +153,8 @@ class Chef sync_cookbooks cookbook_collection = Chef::CookbookCollection.new(cookbooks_to_sync) cookbook_collection.validate! + cookbook_collection.install_gems(events) + run_context = Chef::RunContext.new(node, cookbook_collection, events) setup_chef_class(run_context) @@ -254,10 +256,9 @@ class Chef # @api private def run_list if named_run_list_requested? - named_run_list or - raise ConfigurationError, + named_run_list || raise(ConfigurationError, "Policy '#{retrieved_policy_name}' revision '#{revision_id}' does not have named_run_list '#{named_run_list_name}'" + - "(available named_run_lists: [#{available_named_run_lists.join(', ')}])" + "(available named_run_lists: [#{available_named_run_lists.join(', ')}])") else policy["run_list"] end @@ -319,17 +320,14 @@ class Chef # @api private def deployment_group - Chef::Config[:deployment_group] or - raise ConfigurationError, "Setting `deployment_group` is not configured." + Chef::Config[:deployment_group] || raise(ConfigurationError, "Setting `deployment_group` is not configured.") end # @api private def validate_policy_config! - policy_group or - raise ConfigurationError, "Setting `policy_group` is not configured." + raise ConfigurationError, "Setting `policy_group` is not configured." unless policy_group - policy_name or - raise ConfigurationError, "Setting `policy_name` is not configured." + raise ConfigurationError, "Setting `policy_name` is not configured." unless policy_name end # @api private diff --git a/lib/chef/property.rb b/lib/chef/property.rb index 0230c8b23b..c36daa821a 100644 --- a/lib/chef/property.rb +++ b/lib/chef/property.rb @@ -87,7 +87,7 @@ class Chef # is fully initialized. # def initialize(**options) - options.each { |k, v| options[k.to_sym] = v; options.delete(k) if k.is_a?(String) } + options = options.inject({}) { |memo, (key, value)| memo[key.to_sym] = value; memo } @options = options options[:name] = options[:name].to_sym if options[:name] options[:instance_variable_name] = options[:instance_variable_name].to_sym if options[:instance_variable_name] @@ -266,7 +266,7 @@ class Chef # In Chef 12, value(nil) does a *get* instead of a set, so we # warn if the value would have been changed. In Chef 13, it will be # equivalent to value = nil. - result = get(resource) + result = get(resource, nil_set: true) # Warn about this becoming a set in Chef 13. begin @@ -311,7 +311,7 @@ class Chef # @raise Chef::Exceptions::ValidationFailed If the value is invalid for # this property, or if the value is required and not set. # - def get(resource) + def get(resource, nil_set: false) # If it's set, return it (and evaluate any lazy values) if is_set?(resource) value = get_value(resource) @@ -335,7 +335,8 @@ class Chef # # It won't do what they expect. This checks whether you try to *read* # `content` while we are compiling the resource. - if resource.respond_to?(:resource_initializing) && + if !nil_set && + resource.respond_to?(:resource_initializing) && resource.resource_initializing && resource.respond_to?(:enclosing_provider) && resource.enclosing_provider && diff --git a/lib/chef/provider/deploy.rb b/lib/chef/provider/deploy.rb index 7274ab2e8f..4c758033ac 100644 --- a/lib/chef/provider/deploy.rb +++ b/lib/chef/provider/deploy.rb @@ -242,7 +242,7 @@ class Chef end def all_releases - Dir.glob(Chef::Util::PathHelper.escape_glob(@new_resource.deploy_to) + "/releases/*").sort + Dir.glob(Chef::Util::PathHelper.escape_glob_dir(@new_resource.deploy_to) + "/releases/*").sort end def update_cached_repo diff --git a/lib/chef/provider/deploy/revision.rb b/lib/chef/provider/deploy/revision.rb index 9e2bb94f5b..f61e439486 100644 --- a/lib/chef/provider/deploy/revision.rb +++ b/lib/chef/provider/deploy/revision.rb @@ -44,7 +44,7 @@ class Chef known_releases = sorted_releases - Dir["#{Chef::Util::PathHelper.escape_glob(new_resource.deploy_to)}/releases/*"].each do |release_dir| + Dir["#{Chef::Util::PathHelper.escape_glob_dir(new_resource.deploy_to)}/releases/*"].each do |release_dir| unless known_releases.include?(release_dir) converge_by("Remove unknown release in #{release_dir}") do FileUtils.rm_rf(release_dir) @@ -87,7 +87,7 @@ class Chef end def sorted_releases_from_filesystem - Dir.glob(Chef::Util::PathHelper.escape_glob(new_resource.deploy_to) + "/releases/*").sort_by { |d| ::File.ctime(d) } + Dir.glob(Chef::Util::PathHelper.escape_glob_dir(new_resource.deploy_to) + "/releases/*").sort_by { |d| ::File.ctime(d) } end def load_cache diff --git a/lib/chef/provider/git.rb b/lib/chef/provider/git.rb index 4f17da0288..82f5ca2ba5 100644 --- a/lib/chef/provider/git.rb +++ b/lib/chef/provider/git.rb @@ -143,7 +143,7 @@ class Chef args = [] args << "-o #{remote}" unless remote == "origin" args << "--depth #{@new_resource.depth}" if @new_resource.depth - args << "--no-single-branch" if @new_resource.depth and git_minor_version >= Gem::Version.new("1.7.10") + args << "--no-single-branch" if @new_resource.depth && git_minor_version >= Gem::Version.new("1.7.10") Chef::Log.info "#{@new_resource} cloning repo #{@new_resource.repository} to #{@new_resource.destination}" diff --git a/lib/chef/provider/ifconfig.rb b/lib/chef/provider/ifconfig.rb index e73869d829..4cfb257bb9 100644 --- a/lib/chef/provider/ifconfig.rb +++ b/lib/chef/provider/ifconfig.rb @@ -168,7 +168,7 @@ class Chef end def can_generate_config? - ! @config_template.nil? and ! @config_path.nil? + ! @config_template.nil? && ! @config_path.nil? end def resource_for_config(path) diff --git a/lib/chef/provider/link.rb b/lib/chef/provider/link.rb index d184094bbb..5fce97e5b3 100644 --- a/lib/chef/provider/link.rb +++ b/lib/chef/provider/link.rb @@ -74,8 +74,8 @@ class Chef requirements.assert(:delete) do |a| a.assertion do if @current_resource.to - @current_resource.link_type == @new_resource.link_type and - (@current_resource.link_type == :symbolic or @current_resource.to != "") + @current_resource.link_type == @new_resource.link_type && + (@current_resource.link_type == :symbolic || @current_resource.to != "") else true end @@ -86,7 +86,7 @@ class Chef end def canonicalize(path) - Chef::Platform.windows? ? path.gsub("/", '\\') : path + Chef::Platform.windows? ? path.tr("/", '\\') : path end def action_create diff --git a/lib/chef/provider/mount/mount.rb b/lib/chef/provider/mount/mount.rb index 265911b54c..07da6ac361 100644 --- a/lib/chef/provider/mount/mount.rb +++ b/lib/chef/provider/mount/mount.rb @@ -133,7 +133,7 @@ class Chef end def remount_fs - if @current_resource.mounted and @new_resource.supports[:remount] + if @current_resource.mounted && @new_resource.supports[:remount] shell_out!(remount_command) @new_resource.updated_by_last_action(true) Chef::Log.debug("#{@new_resource} is remounted at #{@new_resource.mount_point}") @@ -193,7 +193,7 @@ class Chef def device_should_exist? ( @new_resource.device != "none" ) && ( not network_device? ) && - ( not %w{ cgroup tmpfs fuse }.include? @new_resource.fstype ) + ( not %w{ cgroup tmpfs fuse vboxsf }.include? @new_resource.fstype ) end private @@ -258,9 +258,9 @@ class Chef end def mount_options_unchanged? - @current_resource.fstype == @new_resource.fstype and - @current_resource.options == @new_resource.options and - @current_resource.dump == @new_resource.dump and + @current_resource.fstype == @new_resource.fstype && + @current_resource.options == @new_resource.options && + @current_resource.dump == @new_resource.dump && @current_resource.pass == @new_resource.pass end diff --git a/lib/chef/provider/mount/windows.rb b/lib/chef/provider/mount/windows.rb index 3ffe326cac..0fb5aa7645 100644 --- a/lib/chef/provider/mount/windows.rb +++ b/lib/chef/provider/mount/windows.rb @@ -80,6 +80,12 @@ class Chef end end + private + + def mount_options_unchanged? + @current_resource.device == @new_resource.device + end + end end end diff --git a/lib/chef/provider/osx_profile.rb b/lib/chef/provider/osx_profile.rb index 3e37cbc9a5..6ac67e0560 100644 --- a/lib/chef/provider/osx_profile.rb +++ b/lib/chef/provider/osx_profile.rb @@ -68,15 +68,15 @@ class Chef requirements.assert(:remove) do |a| if @new_profile_identifier a.assertion { - !@new_profile_identifier.nil? and - !@new_profile_identifier.end_with?(".mobileconfig") and + !@new_profile_identifier.nil? && + !@new_profile_identifier.end_with?(".mobileconfig") && /^\w+(?:\.\w+)+$/.match(@new_profile_identifier) } a.failure_message RuntimeError, "when removing using the identifier attribute, it must match the profile identifier" else new_profile_name = @new_resource.profile_name a.assertion { - !new_profile_name.end_with?(".mobileconfig") and + !new_profile_name.end_with?(".mobileconfig") && /^\w+(?:\.\w+)+$/.match(new_profile_name) } a.failure_message RuntimeError, "When removing by resource name, it must match the profile identifier " @@ -239,7 +239,7 @@ class Chef def profile_installed? # Profile Identifier and UUID must match a currently installed profile - if @current_resource.profile.nil? or @current_resource.profile.empty? + if @current_resource.profile.nil? || @current_resource.profile.empty? false else if @new_resource.action.include?(:remove) diff --git a/lib/chef/provider/package/freebsd/pkg.rb b/lib/chef/provider/package/freebsd/pkg.rb index b42bd62c61..78d9449454 100644 --- a/lib/chef/provider/package/freebsd/pkg.rb +++ b/lib/chef/provider/package/freebsd/pkg.rb @@ -88,7 +88,7 @@ class Chef end def file_candidate_version_path - Dir[Chef::Util::PathHelper.escape_glob("#{@new_resource.source}/#{@current_resource.package_name}") + "*"][-1].to_s + Dir[Chef::Util::PathHelper.escape_glob_dir("#{@new_resource.source}/#{@current_resource.package_name}") + "*"][-1].to_s end def file_candidate_version diff --git a/lib/chef/provider/package/homebrew.rb b/lib/chef/provider/package/homebrew.rb index c032881e70..853a354b28 100644 --- a/lib/chef/provider/package/homebrew.rb +++ b/lib/chef/provider/package/homebrew.rb @@ -53,7 +53,7 @@ class Chef def upgrade_package(name, version) current_version = current_resource.version - if current_version.nil? or current_version.empty? + if current_version.nil? || current_version.empty? install_package(name, version) elsif current_version != version brew("upgrade", new_resource.options, name) diff --git a/lib/chef/provider/package/ips.rb b/lib/chef/provider/package/ips.rb index dc83e4aa08..85053d47f2 100644 --- a/lib/chef/provider/package/ips.rb +++ b/lib/chef/provider/package/ips.rb @@ -69,7 +69,7 @@ class Chef package_name = "#{name}@#{version}" normal_command = "pkg#{expand_options(@new_resource.options)} install -q #{package_name}" command = - if @new_resource.respond_to?(:accept_license) and @new_resource.accept_license + if @new_resource.respond_to?(:accept_license) && @new_resource.accept_license normal_command.gsub("-q", "-q --accept") else normal_command diff --git a/lib/chef/provider/package/macports.rb b/lib/chef/provider/package/macports.rb index b110207d8a..7bbc68aba8 100644 --- a/lib/chef/provider/package/macports.rb +++ b/lib/chef/provider/package/macports.rb @@ -15,7 +15,7 @@ class Chef @candidate_version = macports_candidate_version - if !@new_resource.version and !@candidate_version + if !@new_resource.version && !@candidate_version raise Chef::Exceptions::Package, "Could not get a candidate version for this package -- #{@new_resource.name} does not seem to be a valid package!" end @@ -48,20 +48,20 @@ class Chef def install_package(name, version) unless @current_resource.version == version command = "port#{expand_options(@new_resource.options)} install #{name}" - command << " @#{version}" if version and !version.empty? + command << " @#{version}" if version && !version.empty? shell_out_with_timeout!(command) end end def purge_package(name, version) command = "port#{expand_options(@new_resource.options)} uninstall #{name}" - command << " @#{version}" if version and !version.empty? + command << " @#{version}" if version && !version.empty? shell_out_with_timeout!(command) end def remove_package(name, version) command = "port#{expand_options(@new_resource.options)} deactivate #{name}" - command << " @#{version}" if version and !version.empty? + command << " @#{version}" if version && !version.empty? shell_out_with_timeout!(command) end @@ -71,7 +71,7 @@ class Chef # happens otherwise... current_version = @current_resource.version - if current_version.nil? or current_version.empty? + if current_version.nil? || current_version.empty? # Macports doesn't like when you upgrade a package # that hasn't been installed. install_package(name, version) diff --git a/lib/chef/provider/package/portage.rb b/lib/chef/provider/package/portage.rb index a514dcc66c..7c52e43bff 100644 --- a/lib/chef/provider/package/portage.rb +++ b/lib/chef/provider/package/portage.rb @@ -37,8 +37,8 @@ class Chef category, pkg = %r{^#{PACKAGE_NAME_PATTERN}$}.match(@new_resource.package_name)[1, 2] - globsafe_category = category ? Chef::Util::PathHelper.escape_glob(category) : nil - globsafe_pkg = Chef::Util::PathHelper.escape_glob(pkg) + globsafe_category = category ? Chef::Util::PathHelper.escape_glob_dir(category) : nil + globsafe_pkg = Chef::Util::PathHelper.escape_glob_dir(pkg) possibilities = Dir["/var/db/pkg/#{globsafe_category || "*"}/#{globsafe_pkg}-*"].map { |d| d.sub(%r{/var/db/pkg/}, "") } versions = possibilities.map do |entry| if entry =~ %r{[^/]+/#{Regexp.escape(pkg)}\-(\d[\.\d]*((_(alpha|beta|pre|rc|p)\d*)*)?(-r\d+)?)} @@ -66,7 +66,7 @@ class Chef txt.each_line do |line| if line =~ /\*\s+#{PACKAGE_NAME_PATTERN}/ - found_package_name = $&.gsub(/\*/, "").strip + found_package_name = $&.delete("*").strip if package =~ /\// #the category is specified if found_package_name == package availables[found_package_name] = nil diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb index 7a2db6b32b..39eff19bd0 100644 --- a/lib/chef/provider/package/rubygems.rb +++ b/lib/chef/provider/package/rubygems.rb @@ -115,7 +115,7 @@ class Chef # Compatibility note: Rubygems 1.x uses Gem::Format, 2.0 moved this # code into Gem::Package. def spec_from_file(file) - if defined?(Gem::Format) and Gem::Package.respond_to?(:open) + if defined?(Gem::Format) && Gem::Package.respond_to?(:open) Gem::Format.from_file_by_path(file).spec else Gem::Package.new(file).spec @@ -410,7 +410,7 @@ class Chef def find_gem_by_path Chef::Log.debug("#{@new_resource} searching for 'gem' binary in path: #{ENV['PATH']}") separator = ::File::ALT_SEPARATOR ? ::File::ALT_SEPARATOR : ::File::SEPARATOR - path_to_first_gem = ENV["PATH"].split(::File::PATH_SEPARATOR).select { |path| ::File.exists?(path + separator + "gem") }.first + path_to_first_gem = ENV["PATH"].split(::File::PATH_SEPARATOR).find { |path| ::File.exists?(path + separator + "gem") } raise Chef::Exceptions::FileNotFound, "Unable to find 'gem' binary in path: #{ENV['PATH']}" if path_to_first_gem.nil? path_to_first_gem + separator + "gem" end @@ -535,7 +535,7 @@ class Chef src = " --clear-sources" src << (@new_resource.source && " --source=#{@new_resource.source}" || "") else - src = @new_resource.source && " --source=#{@new_resource.source} --source=https://rubygems.org" + src = @new_resource.source && " --source=#{@new_resource.source} --source=#{Chef::Config[:rubygems_url]}" end if !version.nil? && version.length > 0 shell_out_with_timeout!("#{gem_binary_path} install #{name} -q --no-rdoc --no-ri -v \"#{version}\"#{src}#{opts}", :env => nil) diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb index 858b430abe..dfd32fde55 100644 --- a/lib/chef/provider/package/yum.rb +++ b/lib/chef/provider/package/yum.rb @@ -73,17 +73,17 @@ class Chef # verify def isalnum(x) - isalpha(x) or isdigit(x) + isalpha(x) || isdigit(x) end def isalpha(x) v = x.ord - (v >= 65 and v <= 90) or (v >= 97 and v <= 122) + (v >= 65 && v <= 90) || (v >= 97 && v <= 122) end def isdigit(x) v = x.ord - v >= 48 and v <= 57 + v >= 48 && v <= 57 end # based on the reference spec in lib/rpmvercmp.c in rpm 4.9.0 @@ -128,17 +128,17 @@ class Chef y_pos_max = y.length - 1 y_comp = nil - while x_pos <= x_pos_max and y_pos <= y_pos_max + while x_pos <= x_pos_max && y_pos <= y_pos_max # first we skip over anything non alphanumeric - while (x_pos <= x_pos_max) and (isalnum(x[x_pos]) == false) + while (x_pos <= x_pos_max) && (isalnum(x[x_pos]) == false) x_pos += 1 # +1 over pos_max if end of string end - while (y_pos <= y_pos_max) and (isalnum(y[y_pos]) == false) + while (y_pos <= y_pos_max) && (isalnum(y[y_pos]) == false) y_pos += 1 end # if we hit the end of either we are done matching segments - if (x_pos == x_pos_max + 1) or (y_pos == y_pos_max + 1) + if (x_pos == x_pos_max + 1) || (y_pos == y_pos_max + 1) break end @@ -154,14 +154,14 @@ class Chef x_seg_pos += 1 # gather up our digits - while (x_seg_pos <= x_pos_max) and isdigit(x[x_seg_pos]) + while (x_seg_pos <= x_pos_max) && isdigit(x[x_seg_pos]) x_seg_pos += 1 end # copy the segment but not the unmatched character that x_seg_pos will # refer to x_comp = x[x_pos, x_seg_pos - x_pos] - while (y_seg_pos <= y_pos_max) and isdigit(y[y_seg_pos]) + while (y_seg_pos <= y_pos_max) && isdigit(y[y_seg_pos]) y_seg_pos += 1 end y_comp = y[y_pos, y_seg_pos - y_pos] @@ -169,12 +169,12 @@ class Chef # we are comparing strings x_seg_is_num = false - while (x_seg_pos <= x_pos_max) and isalpha(x[x_seg_pos]) + while (x_seg_pos <= x_pos_max) && isalpha(x[x_seg_pos]) x_seg_pos += 1 end x_comp = x[x_pos, x_seg_pos - x_pos] - while (y_seg_pos <= y_pos_max) and isalpha(y[y_seg_pos]) + while (y_seg_pos <= y_pos_max) && isalpha(y[y_seg_pos]) y_seg_pos += 1 end y_comp = y[y_pos, y_seg_pos - y_pos] @@ -213,7 +213,7 @@ class Chef # segments matched completely but the segment separators were different - # rpm reference code treats these as equal. - if (x_pos == x_pos_max + 1) and (y_pos == y_pos_max + 1) + if (x_pos == x_pos_max + 1) && (y_pos == y_pos_max + 1) return 0 end @@ -290,11 +290,11 @@ class Chef x = self # compare epoch - if (x.e.nil? == false and x.e > 0) and y.e.nil? + if (x.e.nil? == false && x.e > 0) && y.e.nil? return 1 - elsif x.e.nil? and (y.e.nil? == false and y.e > 0) + elsif x.e.nil? && (y.e.nil? == false && y.e > 0) return -1 - elsif x.e.nil? == false and y.e.nil? == false + elsif x.e.nil? == false && y.e.nil? == false if x.e < y.e return -1 elsif x.e > y.e @@ -303,25 +303,25 @@ class Chef end # compare version - if partial and (x.v.nil? or y.v.nil?) + if partial && (x.v.nil? || y.v.nil?) return 0 - elsif x.v.nil? == false and y.v.nil? + elsif x.v.nil? == false && y.v.nil? return 1 - elsif x.v.nil? and y.v.nil? == false + elsif x.v.nil? && y.v.nil? == false return -1 - elsif x.v.nil? == false and y.v.nil? == false + elsif x.v.nil? == false && y.v.nil? == false cmp = RPMUtils.rpmvercmp(x.v, y.v) return cmp if cmp != 0 end # compare release - if partial and (x.r.nil? or y.r.nil?) + if partial && (x.r.nil? || y.r.nil?) return 0 - elsif x.r.nil? == false and y.r.nil? + elsif x.r.nil? == false && y.r.nil? return 1 - elsif x.r.nil? and y.r.nil? == false + elsif x.r.nil? && y.r.nil? == false return -1 - elsif x.r.nil? == false and y.r.nil? == false + elsif x.r.nil? == false && y.r.nil? == false cmp = RPMUtils.rpmvercmp(x.r, y.r) return cmp end @@ -372,11 +372,11 @@ class Chef return 0 if x.nevra == y.nevra # compare name - if x.n.nil? == false and y.n.nil? + if x.n.nil? == false && y.n.nil? return 1 - elsif x.n.nil? and y.n.nil? == false + elsif x.n.nil? && y.n.nil? == false return -1 - elsif x.n.nil? == false and y.n.nil? == false + elsif x.n.nil? == false && y.n.nil? == false if x.n < y.n return -1 elsif x.n > y.n @@ -392,11 +392,11 @@ class Chef end # compare arch - if x.a.nil? == false and y.a.nil? + if x.a.nil? == false && y.a.nil? return 1 - elsif x.a.nil? and y.a.nil? == false + elsif x.a.nil? && y.a.nil? == false return -1 - elsif x.a.nil? == false and y.a.nil? == false + elsif x.a.nil? == false && y.a.nil? == false if x.a < y.a return -1 elsif x.a > y.a @@ -478,14 +478,14 @@ class Chef sense = x.version.partial_compare(y.version) # Thanks to rpmdsCompare() rpmds.c - if sense < 0 and (x.flag == :> || x.flag == :>=) || (y.flag == :<= || y.flag == :<) + if (sense < 0) && ((x.flag == :> || x.flag == :>=) || (y.flag == :<= || y.flag == :<)) return true - elsif sense > 0 and (x.flag == :< || x.flag == :<=) || (y.flag == :>= || y.flag == :>) + elsif (sense > 0) && ((x.flag == :< || x.flag == :<=) || (y.flag == :>= || y.flag == :>)) return true - elsif sense == 0 and ( - ((x.flag == :== or x.flag == :<= or x.flag == :>=) and (y.flag == :== or y.flag == :<= or y.flag == :>=)) or - (x.flag == :< and y.flag == :<) or - (x.flag == :> and y.flag == :>) + elsif sense == 0 && ( + ((x.flag == :== || x.flag == :<= || x.flag == :>=) && (y.flag == :== || y.flag == :<= || y.flag == :>=)) || + (x.flag == :< && y.flag == :<) || + (x.flag == :> && y.flag == :>) ) return true end @@ -1340,7 +1340,7 @@ class Chef old_candidate = @yum.candidate_version(package_name) new_installed = @yum.installed_version(new_package_name, new_arch) new_candidate = @yum.candidate_version(new_package_name, new_arch) - if (old_installed.nil? and old_candidate.nil?) and (new_installed or new_candidate) + if (old_installed.nil? && old_candidate.nil?) && (new_installed || new_candidate) Chef::Log.debug("Parsed out arch #{new_arch}, new package name is #{new_package_name}") return new_package_name, new_arch end @@ -1378,7 +1378,7 @@ class Chef if packages.empty? # Don't bother if we are just ensuring a package is removed - we don't need Provides data actions = Array(@new_resource.action) - unless actions.size == 1 and (actions[0] == :remove || actions[0] == :purge) + unless actions.size == 1 && (actions[0] == :remove || actions[0] == :purge) Chef::Log.debug("#{@new_resource} couldn't match #{@new_resource.package_name} in " + "installed Provides, loading available Provides - this may take a moment") @yum.reload_provides diff --git a/lib/chef/provider/registry_key.rb b/lib/chef/provider/registry_key.rb index 2e00fd08e1..e516433ac8 100644 --- a/lib/chef/provider/registry_key.rb +++ b/lib/chef/provider/registry_key.rb @@ -83,7 +83,7 @@ class Chef #If keys missing in the path and recursive == false a.assertion { !registry.keys_missing?(@current_resource.key) || @new_resource.recursive } a.failure_message(Chef::Exceptions::Win32RegNoRecursive, "Intermediate keys missing but recursive is set to false") - a.whyrun("Intermediate keys in #{@new_resource.key} go not exist. Unless they would have been created earlier, attempt to modify them would fail.") + a.whyrun("Intermediate keys in #{@new_resource.key} do not exist. Unless they would have been created earlier, attempt to modify them would fail.") end requirements.assert(:delete_key) do |a| #If key to be deleted has subkeys but recurssive == false diff --git a/lib/chef/provider/remote_directory.rb b/lib/chef/provider/remote_directory.rb index b592b13ccf..e3bc579107 100644 --- a/lib/chef/provider/remote_directory.rb +++ b/lib/chef/provider/remote_directory.rb @@ -104,7 +104,7 @@ class Chef # def purge_unmanaged_files if purge - Dir.glob(::File.join(Chef::Util::PathHelper.escape_glob(path), "**", "*"), ::File::FNM_DOTMATCH).sort!.reverse!.each do |file| + Dir.glob(::File.join(Chef::Util::PathHelper.escape_glob_dir(path), "**", "*"), ::File::FNM_DOTMATCH).sort!.reverse!.each do |file| # skip '.' and '..' next if [".", ".."].include?(Pathname.new(file).basename().to_s) diff --git a/lib/chef/provider/remote_file/cache_control_data.rb b/lib/chef/provider/remote_file/cache_control_data.rb index 7aa059f4cb..8d7de5c370 100644 --- a/lib/chef/provider/remote_file/cache_control_data.rb +++ b/lib/chef/provider/remote_file/cache_control_data.rb @@ -96,7 +96,7 @@ class Chef end def validate!(current_copy_checksum) - if current_copy_checksum.nil? or checksum != current_copy_checksum + if current_copy_checksum.nil? || checksum != current_copy_checksum reset! false else diff --git a/lib/chef/provider/remote_file/ftp.rb b/lib/chef/provider/remote_file/ftp.rb index 448acdb018..b49e84fa69 100644 --- a/lib/chef/provider/remote_file/ftp.rb +++ b/lib/chef/provider/remote_file/ftp.rb @@ -112,7 +112,7 @@ class Chef def validate_typecode! # Only support ascii and binary types - if typecode and /\A[ai]\z/ !~ typecode + if typecode && /\A[ai]\z/ !~ typecode raise ArgumentError, "invalid typecode: #{typecode.inspect}" end end diff --git a/lib/chef/provider/remote_file/http.rb b/lib/chef/provider/remote_file/http.rb index 6fa574e777..6a9738c02b 100644 --- a/lib/chef/provider/remote_file/http.rb +++ b/lib/chef/provider/remote_file/http.rb @@ -45,10 +45,10 @@ class Chef def conditional_get_headers cache_control_headers = {} - if last_modified = cache_control_data.mtime and want_mtime_cache_control? + if (last_modified = cache_control_data.mtime) && want_mtime_cache_control? cache_control_headers["if-modified-since"] = last_modified end - if etag = cache_control_data.etag and want_etag_cache_control? + if (etag = cache_control_data.etag) && want_etag_cache_control? cache_control_headers["if-none-match"] = etag end Chef::Log.debug("Cache control headers: #{cache_control_headers.inspect}") diff --git a/lib/chef/provider/service.rb b/lib/chef/provider/service.rb index d716e44342..e693bd2eed 100644 --- a/lib/chef/provider/service.rb +++ b/lib/chef/provider/service.rb @@ -1,5 +1,6 @@ # # Author:: AJ Christensen (<aj@hjksolutions.com>) +# Author:: Davide Cavalca (<dcavalca@fb.com>) # Copyright:: Copyright 2008-2016, Chef Software, Inc. # License:: Apache License, Version 2.0 # @@ -56,9 +57,21 @@ class Chef if @new_resource.running.nil? @new_resource.running(@current_resource.running) end + if @new_resource.masked.nil? + @new_resource.masked(@current_resource.masked) + end + end + + # subclasses should override this if they do implement user services + def user_services_requirements + requirements.assert(:all_actions) do |a| + a.assertion { @new_resource.user.nil? } + a.failure_message Chef::Exceptions::UnsupportedAction, "#{self} does not support user services" + end end def shared_resource_requirements + user_services_requirements end def define_resource_requirements @@ -97,6 +110,32 @@ class Chef @new_resource.enabled(false) end + def action_mask + if @current_resource.masked + Chef::Log.debug("#{@new_resource} already masked - nothing to do") + else + converge_by("mask service #{@new_resource}") do + mask_service + Chef::Log.info("#{@new_resource} masked") + end + end + load_new_resource_state + @new_resource.masked(true) + end + + def action_unmask + if @current_resource.masked + converge_by("unmask service #{@new_resource}") do + unmask_service + Chef::Log.info("#{@new_resource} unmasked") + end + else + Chef::Log.debug("#{@new_resource} already unmasked - nothing to do") + end + load_new_resource_state + @new_resource.masked(false) + end + def action_start unless @current_resource.running converge_by("start service #{@new_resource}") do @@ -150,6 +189,14 @@ class Chef raise Chef::Exceptions::UnsupportedAction, "#{self} does not support :disable" end + def mask_service + raise Chef::Exceptions::UnsupportedAction, "#{self} does not support :mask" + end + + def unmask_service + raise Chef::Exceptions::UnsupportedAction, "#{self} does not support :unmask" + end + def start_service raise Chef::Exceptions::UnsupportedAction, "#{self} does not support :start" end diff --git a/lib/chef/provider/service/aixinit.rb b/lib/chef/provider/service/aixinit.rb index 0234673474..73c5e07715 100644 --- a/lib/chef/provider/service/aixinit.rb +++ b/lib/chef/provider/service/aixinit.rb @@ -44,7 +44,7 @@ class Chef else priority_ok = @current_resource.priority == @new_resource.priority end - if @current_resource.enabled and priority_ok + if @current_resource.enabled && priority_ok Chef::Log.debug("#{@new_resource} already enabled - nothing to do") else converge_by("enable service #{@new_resource}") do diff --git a/lib/chef/provider/service/arch.rb b/lib/chef/provider/service/arch.rb index 9c66fb4098..2fd32e37aa 100644 --- a/lib/chef/provider/service/arch.rb +++ b/lib/chef/provider/service/arch.rb @@ -33,7 +33,7 @@ class Chef::Provider::Service::Arch < Chef::Provider::Service::Init def load_current_resource raise Chef::Exceptions::Service, "Could not find /etc/rc.conf" unless ::File.exists?("/etc/rc.conf") - raise Chef::Exceptions::Service, "No DAEMONS found in /etc/rc.conf" unless ::File.read("/etc/rc.conf").match(/DAEMONS=\((.*)\)/m) + raise Chef::Exceptions::Service, "No DAEMONS found in /etc/rc.conf" unless ::File.read("/etc/rc.conf") =~ /DAEMONS=\((.*)\)/m super @current_resource.enabled(daemons.include?(@current_resource.service_name)) @@ -49,7 +49,7 @@ class Chef::Provider::Service::Arch < Chef::Provider::Service::Init # ) def daemons entries = [] - if ::File.read("/etc/rc.conf").match(/DAEMONS=\((.*)\)/m) + if ::File.read("/etc/rc.conf") =~ /DAEMONS=\((.*)\)/m entries += $1.gsub(/\\?[\r\n]/, " ").gsub(/# *[^ ]+/, " ").split(" ") if $1.length > 0 end @@ -70,7 +70,7 @@ class Chef::Provider::Service::Arch < Chef::Provider::Service::Init new_daemons = [] entries = daemons - if entries.include?(new_resource.service_name) or entries.include?("@#{new_resource.service_name}") + if entries.include?(new_resource.service_name) || entries.include?("@#{new_resource.service_name}") # exists and already enabled (or already enabled as a background service) # new_daemons += entries else @@ -100,7 +100,7 @@ class Chef::Provider::Service::Arch < Chef::Provider::Service::Init # exists and disabled # new_daemons += entries else - if entries.include?(new_resource.service_name) or entries.include?("@#{new_resource.service_name}") + if entries.include?(new_resource.service_name) || entries.include?("@#{new_resource.service_name}") # exists but enabled (or enabled as a back-ground service) # FIXME: Does arch support !@foobar ? entries.each do |daemon| diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb index 6550c85b2a..67b71953f7 100644 --- a/lib/chef/provider/service/debian.rb +++ b/lib/chef/provider/service/debian.rb @@ -124,7 +124,7 @@ class Chef else priority_ok = @current_resource.priority == new_resource.priority end - if current_resource.enabled and priority_ok + if current_resource.enabled && priority_ok Chef::Log.debug("#{new_resource} already enabled - nothing to do") else converge_by("enable service #{new_resource}") do diff --git a/lib/chef/provider/service/gentoo.rb b/lib/chef/provider/service/gentoo.rb index 66f2f10f23..8fb6d1f9af 100644 --- a/lib/chef/provider/service/gentoo.rb +++ b/lib/chef/provider/service/gentoo.rb @@ -33,12 +33,12 @@ class Chef::Provider::Service::Gentoo < Chef::Provider::Service::Init super @current_resource.enabled( - Dir.glob("/etc/runlevels/**/#{Chef::Util::PathHelper.escape_glob(@current_resource.service_name)}").any? do |file| + Dir.glob("/etc/runlevels/**/#{Chef::Util::PathHelper.escape_glob_dir(@current_resource.service_name)}").any? do |file| @found_script = true exists = ::File.exists? file readable = ::File.readable? file Chef::Log.debug "#{@new_resource} exists: #{exists}, readable: #{readable}" - exists and readable + exists && readable end ) Chef::Log.debug "#{@new_resource} enabled: #{@current_resource.enabled}" diff --git a/lib/chef/provider/service/insserv.rb b/lib/chef/provider/service/insserv.rb index 7f92ef1eb4..76b2ee7477 100644 --- a/lib/chef/provider/service/insserv.rb +++ b/lib/chef/provider/service/insserv.rb @@ -36,7 +36,7 @@ class Chef super # Look for a /etc/rc.*/SnnSERVICE link to signify that the service would be started in a runlevel - if Dir.glob("/etc/rc**/S*#{Chef::Util::PathHelper.escape_glob(current_resource.service_name)}").empty? + if Dir.glob("/etc/rc**/S*#{Chef::Util::PathHelper.escape_glob_dir(current_resource.service_name)}").empty? current_resource.enabled false else current_resource.enabled true diff --git a/lib/chef/provider/service/macosx.rb b/lib/chef/provider/service/macosx.rb index 63485903c3..648cd9748b 100644 --- a/lib/chef/provider/service/macosx.rb +++ b/lib/chef/provider/service/macosx.rb @@ -181,7 +181,7 @@ class Chef end def set_service_status - return if @plist == nil or @service_label.to_s.empty? + return if @plist == nil || @service_label.to_s.empty? cmd = "launchctl list #{@service_label}" res = shell_out_as_user(cmd) @@ -236,7 +236,7 @@ class Chef plists = PLIST_DIRS.inject([]) do |results, dir| edir = ::File.expand_path(dir) entries = Dir.glob( - "#{edir}/*#{Chef::Util::PathHelper.escape_glob(@current_resource.service_name)}*.plist" + "#{edir}/*#{Chef::Util::PathHelper.escape_glob_dir(@current_resource.service_name)}*.plist" ) entries.any? ? results << entries : results end diff --git a/lib/chef/provider/service/openbsd.rb b/lib/chef/provider/service/openbsd.rb index c31df25e68..c60bbf170c 100644 --- a/lib/chef/provider/service/openbsd.rb +++ b/lib/chef/provider/service/openbsd.rb @@ -92,7 +92,7 @@ class Chef old_services_list = rc_conf_local.match(/^pkg_scripts="(.*)"/) old_services_list = old_services_list ? old_services_list[1].split(" ") : [] new_services_list = old_services_list + [new_resource.service_name] - if rc_conf_local.match(/^pkg_scripts="(.*)"/) + if rc_conf_local =~ /^pkg_scripts="(.*)"/ new_rcl = rc_conf_local.sub(/^pkg_scripts="(.*)"/, "pkg_scripts=\"#{new_services_list.join(' ')}\"") else new_rcl = rc_conf_local + "\n" + "pkg_scripts=\"#{new_services_list.join(' ')}\"\n" @@ -159,7 +159,7 @@ class Chef result = false var_name = builtin_service_enable_variable_name if var_name - if rc_conf.match(/^#{Regexp.escape(var_name)}=(.*)/) + if rc_conf =~ /^#{Regexp.escape(var_name)}=(.*)/ result = true end end diff --git a/lib/chef/provider/service/redhat.rb b/lib/chef/provider/service/redhat.rb index a76622ee8f..08f8e108d5 100644 --- a/lib/chef/provider/service/redhat.rb +++ b/lib/chef/provider/service/redhat.rb @@ -76,7 +76,7 @@ class Chef if ::File.exists?("/sbin/chkconfig") chkconfig = shell_out!("/sbin/chkconfig --list #{current_resource.service_name}", :returns => [0, 1]) - unless run_levels.nil? or run_levels.empty? + unless run_levels.nil? || run_levels.empty? all_levels_match = true chkconfig.stdout.split(/\s+/)[1..-1].each do |level| index = level.split(":").first @@ -100,11 +100,11 @@ class Chef # @api private def levels - (run_levels.nil? or run_levels.empty?) ? "" : "--level #{run_levels.join('')} " + (run_levels.nil? || run_levels.empty?) ? "" : "--level #{run_levels.join('')} " end def enable_service() - unless run_levels.nil? or run_levels.empty? + unless run_levels.nil? || run_levels.empty? disable_levels = current_run_levels - run_levels shell_out! "/sbin/chkconfig --level #{disable_levels.join('')} #{new_resource.service_name} off" unless disable_levels.empty? end diff --git a/lib/chef/provider/service/simple.rb b/lib/chef/provider/service/simple.rb index d76779a74b..fe4768b2e8 100644 --- a/lib/chef/provider/service/simple.rb +++ b/lib/chef/provider/service/simple.rb @@ -76,8 +76,8 @@ class Chef end requirements.assert(:all_actions) do |a| - a.assertion { @new_resource.status_command or supports[:status] or - (!ps_cmd.nil? and !ps_cmd.empty?) } + a.assertion { @new_resource.status_command || supports[:status] || + (!ps_cmd.nil? && !ps_cmd.empty?) } a.failure_message Chef::Exceptions::Service, "#{@new_resource} could not determine how to inspect the process table, please set this node's 'command.ps' attribute" end requirements.assert(:all_actions) do |a| diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb index 0787392094..1e5398eba8 100644 --- a/lib/chef/provider/service/solaris.rb +++ b/lib/chef/provider/service/solaris.rb @@ -49,6 +49,11 @@ class Chef @current_resource end + def define_resource_requirements + # FIXME? need reload from service.rb + shared_resource_requirements + end + def enable_service shell_out!(default_init_command, "clear", @new_resource.service_name) if @maintenance shell_out!(default_init_command, "enable", "-s", @new_resource.service_name) diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb index e70576fea7..1597d46a3d 100644 --- a/lib/chef/provider/service/systemd.rb +++ b/lib/chef/provider/service/systemd.rb @@ -1,5 +1,6 @@ # # Author:: Stephen Haynes (<sh@nomitor.com>) +# Author:: Davide Cavalca (<dcavalca@fb.com>) # Copyright:: Copyright 2011-2016, Chef Software Inc. # License:: Apache License, Version 2.0 # @@ -48,15 +49,21 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple @status_check_success = false current_resource.running(false) current_resource.enabled(false) + current_resource.masked(false) end else current_resource.running(is_active?) end current_resource.enabled(is_enabled?) + current_resource.masked(is_masked?) current_resource end + # systemd supports user services just fine + def user_services_requirements + end + def define_resource_requirements shared_resource_requirements requirements.assert(:all_actions) do |a| @@ -67,6 +74,24 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple end end + def get_systemctl_options_args + if new_resource.user + uid = node["etc"]["passwd"][new_resource.user]["uid"] + options = { + "environment" => { + "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{uid}/bus", + }, + "user" => new_resource.user, + } + args = "--user" + else + options = {} + args = "--system" + end + + return options, args + end + def start_service if current_resource.running Chef::Log.debug("#{new_resource} already running, not starting") @@ -74,7 +99,8 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple if new_resource.start_command super else - shell_out_with_systems_locale!("#{systemctl_path} start #{new_resource.service_name}") + options, args = get_systemctl_options_args + shell_out_with_systems_locale!("#{systemctl_path} #{args} start #{new_resource.service_name}", options) end end end @@ -86,7 +112,8 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple if new_resource.stop_command super else - shell_out_with_systems_locale!("#{systemctl_path} stop #{new_resource.service_name}") + options, args = get_systemctl_options_args + shell_out_with_systems_locale!("#{systemctl_path} #{args} stop #{new_resource.service_name}", options) end end end @@ -95,7 +122,8 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple if new_resource.restart_command super else - shell_out_with_systems_locale!("#{systemctl_path} restart #{new_resource.service_name}") + options, args = get_systemctl_options_args + shell_out_with_systems_locale!("#{systemctl_path} #{args} restart #{new_resource.service_name}", options) end end @@ -104,7 +132,8 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple super else if current_resource.running - shell_out_with_systems_locale!("#{systemctl_path} reload #{new_resource.service_name}") + options, args = get_systemctl_options_args + shell_out_with_systems_locale!("#{systemctl_path} #{args} reload #{new_resource.service_name}", options) else start_service end @@ -112,19 +141,39 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple end def enable_service - shell_out!("#{systemctl_path} enable #{new_resource.service_name}") + options, args = get_systemctl_options_args + shell_out!("#{systemctl_path} #{args} enable #{new_resource.service_name}", options) end def disable_service - shell_out!("#{systemctl_path} disable #{new_resource.service_name}") + options, args = get_systemctl_options_args + shell_out!("#{systemctl_path} #{args} disable #{new_resource.service_name}", options) + end + + def mask_service + options, args = get_systemctl_options_args + shell_out!("#{systemctl_path} #{args} mask #{new_resource.service_name}", options) + end + + def unmask_service + options, args = get_systemctl_options_args + shell_out!("#{systemctl_path} #{args} unmask #{new_resource.service_name}", options) end def is_active? - shell_out("#{systemctl_path} is-active #{new_resource.service_name} --quiet").exitstatus == 0 + options, args = get_systemctl_options_args + shell_out("#{systemctl_path} #{args} is-active #{new_resource.service_name} --quiet", options).exitstatus == 0 end def is_enabled? - shell_out("#{systemctl_path} is-enabled #{new_resource.service_name} --quiet").exitstatus == 0 + options, args = get_systemctl_options_args + shell_out("#{systemctl_path} #{args} is-enabled #{new_resource.service_name} --quiet", options).exitstatus == 0 + end + + def is_masked? + options, args = get_systemctl_options_args + s = shell_out("#{systemctl_path} #{args} is-enabled #{new_resource.service_name}", options) + s.exitstatus != 0 && s.stdout.include?("masked") end private diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb index edd41dba7e..3ac5ff51da 100644 --- a/lib/chef/provider/service/upstart.rb +++ b/lib/chef/provider/service/upstart.rb @@ -62,7 +62,7 @@ class Chef end platform, version = Chef::Platform.find_platform_and_version(run_context.node) - if platform == "ubuntu" && (8.04..9.04).include?(version.to_f) + if platform == "ubuntu" && (8.04..9.04).cover?(version.to_f) @upstart_job_dir = "/etc/event.d" @upstart_conf_suffix = "" else diff --git a/lib/chef/provider/user/aix.rb b/lib/chef/provider/user/aix.rb index 42798a5f62..3f168b8da3 100644 --- a/lib/chef/provider/user/aix.rb +++ b/lib/chef/provider/user/aix.rb @@ -79,7 +79,7 @@ class Chef # Aix specific handling to update users home directory. def manage_home # -m option does not work on aix, so move dir. - if updating_home? and managing_home_dir? + if updating_home? && managing_home_dir? universal_options.delete("-m") if ::File.directory?(@current_resource.home) Chef::Log.debug("Changing users home directory from #{@current_resource.home} to #{new_resource.home}") diff --git a/lib/chef/provider/user/dscl.rb b/lib/chef/provider/user/dscl.rb index fecfb73e2d..e933bf9dc0 100644 --- a/lib/chef/provider/user/dscl.rb +++ b/lib/chef/provider/user/dscl.rb @@ -331,7 +331,7 @@ user password using shadow hash.") src = current_resource.home FileUtils.mkdir_p(new_resource.home) - files = ::Dir.glob("#{Chef::Util::PathHelper.escape_glob(src)}/*", ::File::FNM_DOTMATCH) - ["#{src}/.", "#{src}/.."] + files = ::Dir.glob("#{Chef::Util::PathHelper.escape_glob_dir(src)}/*", ::File::FNM_DOTMATCH) - ["#{src}/.", "#{src}/.."] ::FileUtils.mv(files, new_resource.home, :force => true) ::FileUtils.rmdir(src) ::FileUtils.chown_R(new_resource.username, new_resource.gid.to_s, new_resource.home) diff --git a/lib/chef/provider/user/useradd.rb b/lib/chef/provider/user/useradd.rb index e2f5b5897a..3fef8d3642 100644 --- a/lib/chef/provider/user/useradd.rb +++ b/lib/chef/provider/user/useradd.rb @@ -150,7 +150,7 @@ class Chef # ::File.expand_path("///tmp") == ::File.expand_path("/tmp") => false # ::File.expand_path("\\tmp") => "C:/tmp" return true if @current_resource.home.nil? && new_resource.home - new_resource.home and Pathname.new(@current_resource.home).cleanpath != Pathname.new(new_resource.home).cleanpath + new_resource.home && Pathname.new(@current_resource.home).cleanpath != Pathname.new(new_resource.home).cleanpath end def managing_home_dir? diff --git a/lib/chef/resource/mount.rb b/lib/chef/resource/mount.rb index 44143d583c..2d85b3897c 100644 --- a/lib/chef/resource/mount.rb +++ b/lib/chef/resource/mount.rb @@ -102,7 +102,7 @@ class Chef ) if ret.is_a? String - ret.gsub(/,/, " ").split(/ /) + ret.tr(",", " ").split(/ /) else ret end diff --git a/lib/chef/resource/remote_file.rb b/lib/chef/resource/remote_file.rb index b42cf4ba5f..595280a583 100644 --- a/lib/chef/resource/remote_file.rb +++ b/lib/chef/resource/remote_file.rb @@ -139,7 +139,7 @@ class Chef end def absolute_uri?(source) - Chef::Provider::RemoteFile::Fetcher.network_share?(source) or (source.kind_of?(String) and as_uri(source).absolute?) + Chef::Provider::RemoteFile::Fetcher.network_share?(source) || (source.kind_of?(String) && as_uri(source).absolute?) rescue URI::InvalidURIError false end diff --git a/lib/chef/resource/ruby_block.rb b/lib/chef/resource/ruby_block.rb index 0e3a980b11..87a4cfb7c5 100644 --- a/lib/chef/resource/ruby_block.rb +++ b/lib/chef/resource/ruby_block.rb @@ -34,7 +34,7 @@ class Chef end def block(&block) - if block_given? and block + if block_given? && block @block = block else @block diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb index 849afebad0..1ca4b84af0 100644 --- a/lib/chef/resource/service.rb +++ b/lib/chef/resource/service.rb @@ -24,16 +24,18 @@ class Chef class Service < Chef::Resource identity_attr :service_name - state_attrs :enabled, :running + state_attrs :enabled, :running, :masked default_action :nothing - allowed_actions :enable, :disable, :start, :stop, :restart, :reload + allowed_actions :enable, :disable, :start, :stop, :restart, :reload, + :mask, :unmask def initialize(name, run_context = nil) super @service_name = name @enabled = nil @running = nil + @masked = nil @parameters = nil @pattern = service_name @start_command = nil @@ -45,6 +47,7 @@ class Chef @priority = nil @timeout = nil @run_levels = nil + @user = nil @supports = { :restart => nil, :reload => nil, :status => nil } end @@ -140,6 +143,15 @@ class Chef ) end + # if the service is masked or not + def masked(arg = nil) + set_or_return( + :masked, + arg, + :kind_of => [ TrueClass, FalseClass ] + ) + end + # Priority arguments can have two forms: # # - a simple number, in which the default start runlevels get @@ -182,6 +194,14 @@ class Chef :kind_of => [ Array ] ) end + def user(arg = nil) + set_or_return( + :user, + arg, + :kind_of => [ String ] + ) + end + def supports(args = {}) if args.is_a? Array args.each { |arg| @supports[arg] = true } diff --git a/lib/chef/resource/template.rb b/lib/chef/resource/template.rb index e33af3174b..896aa71340 100644 --- a/lib/chef/resource/template.rb +++ b/lib/chef/resource/template.rb @@ -161,7 +161,7 @@ class Chef # helpers(MyTemplateHelper) # The template code in the above example will work unmodified. def helpers(module_name = nil, &block) - if block_given? and !module_name.nil? + if block_given? && !module_name.nil? raise Exceptions::ValidationFailed, "Passing both a module and block to #helpers is not supported. Call #helpers multiple times instead" elsif block_given? diff --git a/lib/chef/resource_collection/resource_list.rb b/lib/chef/resource_collection/resource_list.rb index 20bfc7b5f0..37eb12a107 100644 --- a/lib/chef/resource_collection/resource_list.rb +++ b/lib/chef/resource_collection/resource_list.rb @@ -76,7 +76,8 @@ class Chef @resources end - def execute_each_resource(&resource_exec_block) + # FIXME: yard with @yield + def execute_each_resource @iterator = ResourceCollection::StepableIterator.for_collection(@resources) @iterator.each_with_index do |resource, idx| @insert_after_idx = idx diff --git a/lib/chef/role.rb b/lib/chef/role.rb index ed22bc87e4..331fa614f1 100644 --- a/lib/chef/role.rb +++ b/lib/chef/role.rb @@ -253,10 +253,10 @@ class Chef def self.from_disk(name) paths = Array(Chef::Config[:role_path]) paths.each do |path| - roles_files = Dir.glob(File.join(Chef::Util::PathHelper.escape_glob(path), "**", "**")) + roles_files = Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(path), "**", "**")) js_files = roles_files.select { |file| file.match(/\/#{name}\.json$/) } rb_files = roles_files.select { |file| file.match(/\/#{name}\.rb$/) } - if js_files.count > 1 or rb_files.count > 1 + if js_files.count > 1 || rb_files.count > 1 raise Chef::Exceptions::DuplicateRole, "Multiple roles of same type found named #{name}" end js_path, rb_path = js_files.first, rb_files.first diff --git a/lib/chef/run_list.rb b/lib/chef/run_list.rb index b9ec9259ca..4dea938423 100644 --- a/lib/chef/run_list.rb +++ b/lib/chef/run_list.rb @@ -105,12 +105,14 @@ class Chef @run_list_items[pos] = parse_entry(item) end - def each(&block) - @run_list_items.each { |i| block.call(i) } + # FIXME: yard with @yield + def each + @run_list_items.each { |i| yield(i) } end - def each_index(&block) - @run_list_items.each_index { |i| block.call(i) } + # FIXME: yard with @yield + def each_index + @run_list_items.each_index { |i| yield(i) } end def include?(item) diff --git a/lib/chef/search/query.rb b/lib/chef/search/query.rb index 487a54f0df..ebf13bec36 100644 --- a/lib/chef/search/query.rb +++ b/lib/chef/search/query.rb @@ -87,7 +87,7 @@ WARNDEP response = call_rest_service(type, query: query, **args_h) if block - response["rows"].each { |row| block.call(row) if row } + response["rows"].each { |row| yield(row) if row } # # args_h[:rows] and args_h[:start] are the page size and # start position requested of the search index backing the diff --git a/lib/chef/shell/model_wrapper.rb b/lib/chef/shell/model_wrapper.rb index 403f9479cf..8c3e456a9b 100644 --- a/lib/chef/shell/model_wrapper.rb +++ b/lib/chef/shell/model_wrapper.rb @@ -59,7 +59,8 @@ module Shell alias :load :show - def transform(what_to_transform, &block) + # FIXME: yard with @yield + def transform(what_to_transform) if what_to_transform == :all objects_to_transform = list_objects else diff --git a/lib/chef/util/dsc/lcm_output_parser.rb b/lib/chef/util/dsc/lcm_output_parser.rb index 2e81b363e0..bdcedff7f8 100644 --- a/lib/chef/util/dsc/lcm_output_parser.rb +++ b/lib/chef/util/dsc/lcm_output_parser.rb @@ -79,7 +79,7 @@ class Chef end when :end # Make sure we log the last line - if current_resource[:context] == :logging and info.include? current_resource[:name] + if current_resource[:context] == :logging && info.include?(current_resource[:name]) current_resource[:logs].push(info) end current_resource[:context] = nil diff --git a/lib/chef/util/dsc/resource_store.rb b/lib/chef/util/dsc/resource_store.rb index bb3480d105..be8d0b301b 100644 --- a/lib/chef/util/dsc/resource_store.rb +++ b/lib/chef/util/dsc/resource_store.rb @@ -74,7 +74,7 @@ class Chef found = rs.find_all do |r| name_matches = r["Name"].casecmp(name) == 0 if name_matches - module_name == nil || (r["Module"] and r["Module"]["Name"].casecmp(module_name) == 0) + module_name == nil || (r["Module"] && r["Module"]["Name"].casecmp(module_name) == 0) else false end diff --git a/lib/chef/util/windows/net_user.rb b/lib/chef/util/windows/net_user.rb index b0a779e44a..009252c4c1 100644 --- a/lib/chef/util/windows/net_user.rb +++ b/lib/chef/util/windows/net_user.rb @@ -119,11 +119,12 @@ class Chef::Util::Windows::NetUser < Chef::Util::Windows NetUser.net_local_group_add_member(nil, "Users", args[:name]) end - def user_modify(&proc) + # FIXME: yard with @yield + def user_modify user = get_info user[:last_logon] = user[:units_per_week] = 0 #ignored as per USER_INFO_3 doc user[:logon_hours] = nil #PBYTE field; \0 == no changes - proc.call(user) + yield(user) set_info(user) end diff --git a/lib/chef/version.rb b/lib/chef/version.rb index 6c1fe2227a..9d42fa581a 100644 --- a/lib/chef/version.rb +++ b/lib/chef/version.rb @@ -21,7 +21,7 @@ class Chef CHEF_ROOT = File.dirname(File.expand_path(File.dirname(__FILE__))) - VERSION = "12.8.0" + VERSION = "12.9.0" end # diff --git a/lib/chef/win32/api/file.rb b/lib/chef/win32/api/file.rb index 52ac4868c7..7489c94fd9 100644 --- a/lib/chef/win32/api/file.rb +++ b/lib/chef/win32/api/file.rb @@ -535,7 +535,8 @@ BOOL WINAPI VerQueryValue( # retrieves a file search handle and passes it # to +&block+ along with the find_data. also # ensures the handle is closed on exit of the block - def file_search_handle(path, &block) + # FIXME: yard with @yield + def file_search_handle(path) begin # Workaround for CHEF-4419: # Make sure paths starting with "/" has a drive letter @@ -550,7 +551,7 @@ BOOL WINAPI VerQueryValue( if handle == INVALID_HANDLE_VALUE Chef::ReservedNames::Win32::Error.raise! end - block.call(handle, find_data) + yield(handle, find_data) ensure FindClose(handle) if handle && handle != INVALID_HANDLE_VALUE end @@ -559,7 +560,8 @@ BOOL WINAPI VerQueryValue( # retrieves a file handle and passes it # to +&block+ along with the find_data. also # ensures the handle is closed on exit of the block - def file_handle(path, &block) + # FIXME: yard with @yield + def file_handle(path) begin path = canonical_encode_path(path) handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, @@ -568,13 +570,14 @@ BOOL WINAPI VerQueryValue( if handle == INVALID_HANDLE_VALUE Chef::ReservedNames::Win32::Error.raise! end - block.call(handle) + yield(handle) ensure CloseHandle(handle) if handle && handle != INVALID_HANDLE_VALUE end end - def symlink_file_handle(path, &block) + # FIXME: yard with @yield + def symlink_file_handle(path) begin path = encode_path(path) handle = CreateFileW(path, FILE_READ_EA, FILE_SHARE_READ, @@ -583,7 +586,7 @@ BOOL WINAPI VerQueryValue( if handle == INVALID_HANDLE_VALUE Chef::ReservedNames::Win32::Error.raise! end - block.call(handle) + yield(handle) ensure CloseHandle(handle) if handle && handle != INVALID_HANDLE_VALUE end diff --git a/lib/chef/win32/eventlog.rb b/lib/chef/win32/eventlog.rb index 723b43fc44..4254b8ead3 100644 --- a/lib/chef/win32/eventlog.rb +++ b/lib/chef/win32/eventlog.rb @@ -16,7 +16,7 @@ # limitations under the License. # -if Chef::Platform.windows? and not Chef::Platform.windows_server_2003? +if Chef::Platform.windows? && (not Chef::Platform.windows_server_2003?) if !defined? Chef::Win32EventLogLoaded if defined? Windows::Constants [:INFINITE, :WAIT_FAILED, :FORMAT_MESSAGE_IGNORE_INSERTS, :ERROR_INSUFFICIENT_BUFFER].each do |c| diff --git a/lib/chef/win32/version.rb b/lib/chef/win32/version.rb index 85a2744645..303fe1531d 100644 --- a/lib/chef/win32/version.rb +++ b/lib/chef/win32/version.rb @@ -41,7 +41,7 @@ class Chef private_class_method :get_system_metrics def self.method_name_from_marketing_name(marketing_name) - "#{marketing_name.gsub(/\s/, '_').gsub(/\./, '_').downcase}?" + "#{marketing_name.gsub(/\s/, '_').tr('.', '_').downcase}?" # "#{marketing_name.gsub(/\s/, '_').gsub(//, '_').downcase}?" end diff --git a/omnibus/config/projects/chef.rb b/omnibus/config/projects/chef.rb index 2e003322f8..1b6e373725 100644 --- a/omnibus/config/projects/chef.rb +++ b/omnibus/config/projects/chef.rb @@ -34,17 +34,10 @@ else install_dir "#{default_root}/#{name}" end -if windows? - override :ruby, version: "2.0.0-p645" - # Leave dev-kit pinned to 4.5 because 4.7 is 20MB larger and we don't want - # to unnecessarily make the client any fatter. - if windows_arch_i386? - override :'ruby-windows-devkit', version: "4.5.2-20111229-1559" - end -else - override :ruby, version: "2.1.6" -end - +override :ruby, version: "2.1.8" +# Leave dev-kit pinned to 4.5 because 4.7 is 20MB larger and we don't want +# to unnecessarily make the client any fatter. +override :'ruby-windows-devkit', version: "4.5.2-20111229-1559" if windows? && windows_arch_i386? override :bundler, version: "1.11.2" override :rubygems, version: "2.5.2" @@ -71,6 +64,8 @@ if windows? dependency "ruby-windows-devkit-bash" end +dependency "clean-static-libs" + package :rpm do signing_passphrase ENV["OMNIBUS_RPM_SIGNING_PASSPHRASE"] end diff --git a/spec/functional/event_loggers/windows_eventlog_spec.rb b/spec/functional/event_loggers/windows_eventlog_spec.rb index 69874ef677..78aed7409f 100644 --- a/spec/functional/event_loggers/windows_eventlog_spec.rb +++ b/spec/functional/event_loggers/windows_eventlog_spec.rb @@ -19,7 +19,7 @@ require "spec_helper" require "securerandom" require "chef/event_loggers/windows_eventlog" -if Chef::Platform.windows? and not Chef::Platform.windows_server_2003? +if Chef::Platform.windows? && (not Chef::Platform.windows_server_2003?) require "win32/eventlog" include Win32 end diff --git a/spec/functional/knife/rehash_spec.rb b/spec/functional/knife/rehash_spec.rb new file mode 100644 index 0000000000..22ffa125fa --- /dev/null +++ b/spec/functional/knife/rehash_spec.rb @@ -0,0 +1,39 @@ +# +# Author:: Daniel DeLeo (<dan@chef.io>) +# Copyright:: Copyright 2010-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. +# + +require "spec_helper" + +require "chef/knife/rehash" +require "chef/knife/core/subcommand_loader" + +describe "knife rehash" do + before do + allow(Chef::Knife::SubcommandLoader).to receive(:load_commands) + end + + after do + # We need to clean up the generated manifest or else is messes with later tests + FileUtils.rm_f(Chef::Knife::SubcommandLoader.plugin_manifest_path) + end + + it "writes the loaded plugins to disc" do + knife_rehash = Chef::Knife::Rehash.new + knife_rehash.run + expect(File.read(Chef::Knife::SubcommandLoader.plugin_manifest_path)).to match(/node_list.rb/) + end +end diff --git a/spec/functional/resource/bash_spec.rb b/spec/functional/resource/bash_spec.rb index 13ffac57d1..87211ec264 100644 --- a/spec/functional/resource/bash_spec.rb +++ b/spec/functional/resource/bash_spec.rb @@ -33,7 +33,7 @@ describe Chef::Resource::Bash, :unix_only do # in Chef-12 the `command` attribute is largely useless, but does set the identity attribute # so that notifications need to target the value of the command. it will not run the `command` # and if it is given without a code block then it does nothing and always succeeds. - describe "in Chef-12", :chef_lt_13_only do + describe "in Chef-12", chef: "< 13" do it "gets the commmand attribute from the name" do expect(resource.command).to eql("foo_resource") end @@ -61,7 +61,7 @@ describe Chef::Resource::Bash, :unix_only do end # in Chef-13 the `command` attribute needs to be for internal use only - describe "in Chef-13", :chef_gte_13_only do + describe "in Chef-13", chef: ">= 13" do it "should raise an exception when trying to set the command" do expect { resource.command command }.to raise_error # FIXME: add a real error in Chef-13 end diff --git a/spec/functional/resource/link_spec.rb b/spec/functional/resource/link_spec.rb index f55b9fca1e..6dd6ad8422 100644 --- a/spec/functional/resource/link_spec.rb +++ b/spec/functional/resource/link_spec.rb @@ -73,7 +73,7 @@ describe Chef::Resource::Link do end def canonicalize(path) - windows? ? path.gsub("/", '\\') : path + windows? ? path.tr("/", '\\') : path end def symlink(a, b) @@ -343,7 +343,7 @@ describe Chef::Resource::Link do it "create errors out" do if windows? expect { resource.run_action(:create) }.to raise_error(Errno::EACCES) - elsif os_x? or solaris? or freebsd? or aix? + elsif os_x? || solaris? || freebsd? || aix? expect { resource.run_action(:create) }.to raise_error(Errno::EPERM) else expect { resource.run_action(:create) }.to raise_error(Errno::EISDIR) @@ -512,7 +512,7 @@ describe Chef::Resource::Link do it "errors out" do if windows? expect { resource.run_action(:create) }.to raise_error(Errno::EACCES) - elsif os_x? or solaris? or freebsd? or aix? + elsif os_x? || solaris? || freebsd? || aix? expect { resource.run_action(:create) }.to raise_error(Errno::EPERM) else expect { resource.run_action(:create) }.to raise_error(Errno::EISDIR) @@ -559,7 +559,7 @@ describe Chef::Resource::Link do end context "and the link does not yet exist" do it "links to the target file" do - skip("OS X/FreeBSD/AIX symlink? and readlink working on hard links to symlinks") if os_x? or freebsd? or aix? + skip("OS X/FreeBSD/AIX symlink? and readlink working on hard links to symlinks") if os_x? || freebsd? || aix? resource.run_action(:create) expect(File.exists?(target_file)).to be_truthy # OS X gets angry about this sort of link. Bug in OS X, IMO. @@ -578,7 +578,7 @@ describe Chef::Resource::Link do end context "and the link does not yet exist" do it "links to the target file" do - skip("OS X/FreeBSD/AIX fails to create hardlinks to broken symlinks") if os_x? or freebsd? or aix? + skip("OS X/FreeBSD/AIX fails to create hardlinks to broken symlinks") if os_x? || freebsd? || aix? resource.run_action(:create) # Windows and Unix have different definitions of exists? here, and that's OK. if windows? diff --git a/spec/functional/resource/user/useradd_spec.rb b/spec/functional/resource/user/useradd_spec.rb index 5ce3ed7354..43c26ac006 100644 --- a/spec/functional/resource/user/useradd_spec.rb +++ b/spec/functional/resource/user/useradd_spec.rb @@ -506,7 +506,7 @@ describe Chef::Provider::User::Useradd, metadata do let(:user_locked_context?) { false } def shadow_entry - etc_shadow.lines.select { |l| l.include?(username) }.first + etc_shadow.lines.find { |l| l.include?(username) } end def shadow_password diff --git a/spec/functional/run_lock_spec.rb b/spec/functional/run_lock_spec.rb index b0e52471db..f1e480c917 100644 --- a/spec/functional/run_lock_spec.rb +++ b/spec/functional/run_lock_spec.rb @@ -343,7 +343,7 @@ describe Chef::RunLock do write_to_process.print "#{to_event}\n" # Run the background block - background_block.call if background_block + yield if background_block # Wait until it gets there Timeout.timeout(CLIENT_PROCESS_TIMEOUT) do diff --git a/spec/functional/util/path_helper_spec.rb b/spec/functional/util/path_helper_spec.rb index f1a953ebad..fd484adff2 100644 --- a/spec/functional/util/path_helper_spec.rb +++ b/spec/functional/util/path_helper_spec.rb @@ -30,7 +30,7 @@ describe Chef::Util::PathHelper, "escape_glob" do File.new(File.join(dir, file), "w").close end - pattern = File.join(PathHelper.escape_glob(dir), "*") + pattern = File.join(PathHelper.escape_glob_dir(dir), "*") expect(Dir.glob(pattern).map { |x| File.basename(x) }).to match_array(files) end end diff --git a/spec/functional/win32/versions_spec.rb b/spec/functional/win32/versions_spec.rb index 53fce39491..d6e840ed7f 100644 --- a/spec/functional/win32/versions_spec.rb +++ b/spec/functional/win32/versions_spec.rb @@ -50,7 +50,7 @@ describe "Chef::ReservedNames::Win32::Version", :windows_only, :not_supported_on @version = Chef::ReservedNames::Win32::Version.new end - def for_each_windows_version(&block) + def for_each_windows_version @version.methods.each do |method_name| if Chef::ReservedNames::Win32::Version::WIN_VERSIONS.keys.find { |key| method_name.to_s == Chef::ReservedNames::Win32::Version.send(:method_name_from_marketing_name, key) } yield method_name diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb index bfc88659e0..f6e50066bf 100644 --- a/spec/integration/client/client_spec.rb +++ b/spec/integration/client/client_spec.rb @@ -47,7 +47,7 @@ describe "chef-client" do # cf. CHEF-4914 let(:chef_client) { "ruby '#{chef_dir}/chef-client' --minimal-ohai" } - let(:critical_env_vars) { %w{PATH RUBYOPT BUNDLE_GEMFILE GEM_PATH}.map { |o| "#{o}=#{ENV[o]}" } .join(" ") } + let(:critical_env_vars) { %w{_ORIGINAL_GEM_PATH GEM_PATH GEM_HOME GEM_ROOT BUNDLE_BIN_PATH BUNDLE_GEMFILE RUBYLIB RUBYOPT RUBY_ENGINE RUBY_ROOT RUBY_VERSION PATH}.map { |o| "#{o}=#{ENV[o]}" } .join(" ") } when_the_repository "has a cookbook with a no-op recipe" do before { file "cookbooks/x/recipes/default.rb", "" } diff --git a/spec/integration/knife/upload_spec.rb b/spec/integration/knife/upload_spec.rb index 739dfa44d1..9a1717b2d9 100644 --- a/spec/integration/knife/upload_spec.rb +++ b/spec/integration/knife/upload_spec.rb @@ -159,14 +159,14 @@ EOM file "cookbooks/x/metadata.rb", "name 'x'; version '1.0.0'; depends 'x'" end - it "should warn", :chef_lt_13_only do + it "should warn", chef: "< 13" do knife("upload /cookbooks").should_succeed( stdout: "Updated /cookbooks/x\n", stderr: "WARN: Ignoring self-dependency in cookbook x, please remove it (in the future this will be fatal).\n" ) knife("diff --name-status /").should_succeed "" end - it "should fail in Chef 13", :chef_gte_13_only do + it "should fail in Chef 13", chef: ">= 13" do knife("upload /cookbooks").should_fail "" # FIXME: include the error message here end diff --git a/spec/integration/recipes/lwrp_inline_resources_spec.rb b/spec/integration/recipes/lwrp_inline_resources_spec.rb index 0fc2c338fd..46fd83423d 100644 --- a/spec/integration/recipes/lwrp_inline_resources_spec.rb +++ b/spec/integration/recipes/lwrp_inline_resources_spec.rb @@ -45,6 +45,33 @@ describe "LWRPs with inline resources" do end end + context "with an inline resource with a property that shadows the enclosing provider's property" do + class LwrpShadowedPropertyTest < Chef::Resource::LWRPBase + PATH = ::File.join(Dir.tmpdir, "shadow-property.txt") + use_automatic_resource_name + actions :fiddle + property :content + action :fiddle do + file PATH do + content new_resource.content + action [:create, :delete] + end + end + end + + after { File.delete(LwrpShadowedPropertyTest::PATH) if File.exists?(LwrpShadowedPropertyTest::PATH) } + + # https://github.com/chef/chef/issues/4334 + it "does not warn spuriously" do + expect(Chef::Log).to_not receive(:warn).with(/is declared in both/) + expect_recipe { + lwrp_shadowed_property_test "fnord" do + action :fiddle + end + } + end + end + context "with an inline_resources provider with two actions, one calling the other" do class LwrpInlineResourcesTest2 < Chef::Resource::LWRPBase resource_name :lwrp_inline_resources_test2 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8ba4c8eb70..2f6747c9af 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -117,7 +117,7 @@ RSpec.configure do |config| end # Only run these tests on platforms that are also chef workstations - config.filter_run_excluding :workstation if solaris? or aix? + config.filter_run_excluding :workstation if solaris? || aix? # Tests that randomly fail, but may have value. config.filter_run_excluding :volatile => true @@ -154,11 +154,6 @@ RSpec.configure do |config| 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? - config.filter_run_excluding :ruby_20_only => true unless ruby_20? - # chef_gte_XX_only and chef_lt_XX_only pair up correctly with the same XX - # number. please conserve this pattern & resist filling out all the operators - config.filter_run_excluding :chef_gte_13_only => true unless chef_gte_13? - config.filter_run_excluding :chef_lt_13_only => true unless chef_lt_13? config.filter_run_excluding :requires_root => true unless root? config.filter_run_excluding :requires_root_or_running_windows => true unless root? || windows? config.filter_run_excluding :requires_unprivileged_user => true if root? @@ -170,6 +165,10 @@ RSpec.configure do |config| config.filter_run_excluding :not_wpar => true unless wpar? config.filter_run_excluding :not_supported_under_fips => true if fips? + # these let us use chef: ">= 13" or ruby: "~> 2.0.0" or any other Gem::Dependency-style constraint + config.filter_run_excluding chef: DependencyProc.with(Chef::VERSION) + config.filter_run_excluding ruby: DependencyProc.with(RUBY_VERSION) + running_platform_arch = `uname -m`.strip unless windows? config.filter_run_excluding :arch => lambda {|target_arch| diff --git a/spec/stress/win32/security_spec.rb b/spec/stress/win32/security_spec.rb index 4fbd1dac9c..58cf7b3357 100644 --- a/spec/stress/win32/security_spec.rb +++ b/spec/stress/win32/security_spec.rb @@ -27,7 +27,7 @@ end describe "Chef::ReservedNames::Win32::Security", :windows_only do def monkeyfoo - File.join(CHEF_SPEC_DATA, "monkeyfoo").gsub("/", "\\") + File.join(CHEF_SPEC_DATA, "monkeyfoo").tr("/", "\\") end before :all do diff --git a/spec/support/chef_helpers.rb b/spec/support/chef_helpers.rb index aa60737c86..f64c14da4d 100644 --- a/spec/support/chef_helpers.rb +++ b/spec/support/chef_helpers.rb @@ -81,7 +81,7 @@ end # This is a helper to canonicalize paths that we're using in the file # tests. def canonicalize_path(path) - windows? ? path.gsub("/", '\\') : path + windows? ? path.tr("/", '\\') : path end # Check if a cmd exists on the PATH diff --git a/spec/support/lib/chef/resource/cat.rb b/spec/support/lib/chef/resource/cat.rb index 94190e1f5b..f62db4d2cd 100644 --- a/spec/support/lib/chef/resource/cat.rb +++ b/spec/support/lib/chef/resource/cat.rb @@ -28,7 +28,7 @@ class Chef end def pretty_kitty(arg = nil) - if arg == true or arg == false + if arg == true || arg == false @pretty_kitty = arg end @pretty_kitty diff --git a/spec/support/lib/chef/resource/one_two_three_four.rb b/spec/support/lib/chef/resource/one_two_three_four.rb index d46d20d2b5..e46bede0fa 100644 --- a/spec/support/lib/chef/resource/one_two_three_four.rb +++ b/spec/support/lib/chef/resource/one_two_three_four.rb @@ -27,7 +27,7 @@ class Chef end def something(arg = nil) - if arg == true or arg == false + if arg == true || arg == false @something = arg end @something diff --git a/spec/support/matchers/leak.rb b/spec/support/matchers/leak.rb index f50a1bf5f7..5f22c1c151 100644 --- a/spec/support/matchers/leak.rb +++ b/spec/support/matchers/leak.rb @@ -20,7 +20,7 @@ module Matchers module LeakBase include RSpec::Matchers - def initialize(opts = {}, &block) + def initialize(opts = {}) @warmup = opts[:warmup] || 5 @iterations = opts[:iterations] || 100 @variance = opts[:variance] || 5000 diff --git a/spec/support/mock/constant.rb b/spec/support/mock/constant.rb index a2abc1905e..3a23b4d8d8 100644 --- a/spec/support/mock/constant.rb +++ b/spec/support/mock/constant.rb @@ -4,7 +4,7 @@ # http://missingbit.blogspot.com/2011/07/stubbing-constants-in-rspec_20.html # http://digitaldumptruck.jotabout.com/?p=551 -def mock_constants(constants, &block) +def mock_constants(constants) saved_constants = {} constants.each do |constant, val| source_object, const_name = parse_constant(constant) @@ -13,7 +13,7 @@ def mock_constants(constants, &block) end begin - block.call + yield ensure constants.each do |constant, val| source_object, const_name = parse_constant(constant) diff --git a/spec/support/mock/platform.rb b/spec/support/mock/platform.rb index ef94678b64..c6670827f9 100644 --- a/spec/support/mock/platform.rb +++ b/spec/support/mock/platform.rb @@ -5,7 +5,7 @@ # 'i386-mingw32' (windows) or 'x86_64-darwin11.2.0' (unix). Usueful for # testing code that mixes in platform specific modules like +Chef::Mixin::Securable+ # or +Chef::FileAccessControl+ -def platform_mock(platform = :unix, &block) +def platform_mock(platform = :unix) allow(ChefConfig).to receive(:windows?).and_return(platform == :windows ? true : false) ENV["SYSTEMDRIVE"] = (platform == :windows ? "C:" : nil) diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb index b50c2a01f0..9ba56a15e3 100644 --- a/spec/support/platform_helpers.rb +++ b/spec/support/platform_helpers.rb @@ -6,24 +6,20 @@ class ShellHelpers extend Chef::Mixin::ShellOut end -def ruby_lt_20? - !ruby_gte_20? -end - -def chef_gte_13? - Chef::VERSION.split(".").first.to_i >= 13 -end - -def chef_lt_13? - Chef::VERSION.split(".").first.to_i < 13 -end - -def ruby_gte_19? - RUBY_VERSION.to_f >= 1.9 -end +# magic stolen from bundler/spec/support/less_than_proc.rb +class DependencyProc < Proc + attr_accessor :present + + def self.with(present) + provided = Gem::Version.new(present.dup) + new do |required| + !Gem::Requirement.new(required).satisfied_by?(provided) + end.tap { |l| l.present = present } + end -def ruby_20? - !!(RUBY_VERSION =~ /^2.0/) + def inspect + "\"#{present}\"" + end end def ruby_64bit? diff --git a/spec/support/shared/integration/knife_support.rb b/spec/support/shared/integration/knife_support.rb index fe9c6f78a7..1e81cd115c 100644 --- a/spec/support/shared/integration/knife_support.rb +++ b/spec/support/shared/integration/knife_support.rb @@ -23,7 +23,7 @@ require "chef/log" module KnifeSupport DEBUG = ENV["DEBUG"] - def knife(*args, &block) + def knife(*args) # Allow knife('role from file roles/blah.json') rather than requiring the # arguments to be split like knife('role', 'from', 'file', 'roles/blah.json') # If any argument will have actual spaces in it, the long form is required. diff --git a/spec/support/shared/matchers/exit_with_code.rb b/spec/support/shared/matchers/exit_with_code.rb index c5458eea0e..a9f1af81ce 100644 --- a/spec/support/shared/matchers/exit_with_code.rb +++ b/spec/support/shared/matchers/exit_with_code.rb @@ -9,7 +9,7 @@ RSpec::Matchers.define :exit_with_code do |exp_code| rescue SystemExit => e actual = e.status end - actual and actual == exp_code + actual && actual == exp_code end failure_message do |block| diff --git a/spec/support/shared/unit/execute_resource.rb b/spec/support/shared/unit/execute_resource.rb index 27c60ef377..e33247da42 100644 --- a/spec/support/shared/unit/execute_resource.rb +++ b/spec/support/shared/unit/execute_resource.rb @@ -76,13 +76,13 @@ shared_examples_for "an execute resource" do expect(@resource.group).to eql(1) end - it "should accept an array for the execution path in Chef-12 and log deprecation message", :chef_lt_13_only do + it "should accept an array for the execution path in Chef-12 and log deprecation message", chef: "< 13" do expect(Chef::Log).to receive(:warn).at_least(:once) @resource.path ["woot"] expect(@resource.path).to eql(["woot"]) end - it "should raise an exception in chef-13", :chef_gte_13_only do + it "should raise an exception in chef-13", chef: ">= 13" do expect(@resource.path [ "woot" ]).to raise_error end diff --git a/spec/support/shared/unit/provider/file.rb b/spec/support/shared/unit/provider/file.rb index 7ddd51db80..2b2c7255cc 100644 --- a/spec/support/shared/unit/provider/file.rb +++ b/spec/support/shared/unit/provider/file.rb @@ -37,7 +37,7 @@ end # forwards-vs-reverse slashes on windows sucks def windows_path - windows? ? normalized_path.gsub(/\\/, "/") : normalized_path + windows? ? normalized_path.tr('\\', "/") : normalized_path end # this is all getting a bit stupid, CHEF-4802 cut to remove all this diff --git a/spec/support/shared/unit/script_resource.rb b/spec/support/shared/unit/script_resource.rb index ba33d69a59..732b07d4ef 100644 --- a/spec/support/shared/unit/script_resource.rb +++ b/spec/support/shared/unit/script_resource.rb @@ -30,11 +30,11 @@ shared_examples_for "a script resource" do expect(script_resource.resource_name).to eql(resource_name) end - it "should set command to nil on the resource", :chef_gte_13_only do + it "should set command to nil on the resource", chef: ">= 13" do expect(script_resource.command).to be nil end - it "should set command to the name on the resource", :chef_lt_13_only do + it "should set command to the name on the resource", chef: "< 13" do expect(script_resource.command).to eql script_resource.name end @@ -48,11 +48,11 @@ shared_examples_for "a script resource" do expect(script_resource.flags).to eql("-f") end - it "should raise an exception if users set command on the resource", :chef_gte_13_only do + it "should raise an exception if users set command on the resource", chef: ">= 13" do expect { script_resource.command("foo") }.to raise_error(Chef::Exceptions::Script) end - it "should not raise an exception if users set command on the resource", :chef_lt_13_only do + it "should not raise an exception if users set command on the resource", chef: "< 13" do expect { script_resource.command("foo") }.not_to raise_error end diff --git a/spec/unit/api_client/registration_spec.rb b/spec/unit/api_client/registration_spec.rb index f086993860..0f036766da 100644 --- a/spec/unit/api_client/registration_spec.rb +++ b/spec/unit/api_client/registration_spec.rb @@ -98,7 +98,7 @@ describe Chef::ApiClient::Registration do it "has an HTTP client configured with validator credentials" do expect(registration.http_api).to be_a_kind_of(Chef::ServerAPI) expect(registration.http_api.options[:client_name]).to eq("test-validator") - auth = registration.http_api.middlewares.select { |klass| klass.kind_of? Chef::HTTP::Authenticator }.first + auth = registration.http_api.middlewares.find { |klass| klass.kind_of? Chef::HTTP::Authenticator } expect(auth.client_name).to eq("test-validator") end diff --git a/spec/unit/chef_fs/parallelizer.rb b/spec/unit/chef_fs/parallelizer.rb index 20edbcdcde..9de8077677 100644 --- a/spec/unit/chef_fs/parallelizer.rb +++ b/spec/unit/chef_fs/parallelizer.rb @@ -463,15 +463,15 @@ describe Chef::ChefFS::Parallelizer do attr_reader :num_processed - def each(&each_block) + def each @values.each do |value| @num_processed += 1 - each_block.call(value) + yield(value) end if @block @block.call do |value| @num_processed += 1 - each_block.call(value) + yield(value) end end end diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb index 0107667fcd..761355b6e0 100644 --- a/spec/unit/cookbook/metadata_spec.rb +++ b/spec/unit/cookbook/metadata_spec.rb @@ -30,7 +30,8 @@ describe Chef::Cookbook::Metadata do :maintainer_email, :license, :platforms, :dependencies, :recommendations, :suggestions, :conflicting, :providing, :replacing, :attributes, :groupings, :recipes, :version, - :source_url, :issues_url, :privacy, :ohai_versions, :chef_versions ] + :source_url, :issues_url, :privacy, :ohai_versions, :chef_versions, + :gems ] end it "does not depend on object identity for equality" do @@ -308,7 +309,7 @@ describe Chef::Cookbook::Metadata do end end - it "strips out self-dependencies", :chef_lt_13_only do + it "strips out self-dependencies", chef: "< 13" do metadata.name("foo") expect(Chef::Log).to receive(:warn).with( "Ignoring self-dependency in cookbook foo, please remove it (in the future this will be fatal)." @@ -317,7 +318,7 @@ describe Chef::Cookbook::Metadata do expect(metadata.dependencies).to eql({}) end - it "errors on self-dependencies", :chef_gte_13_only do + it "errors on self-dependencies", chef: ">= 13" do metadata.name("foo") expect { metadata.depends("foo") }.to raise_error # FIXME: add the error type @@ -428,6 +429,29 @@ describe Chef::Cookbook::Metadata do end end + describe "gem" do + def expect_gem_works(*args) + ret = [] + args.each do |arg| + metadata.send(:gem, *arg) + ret << arg + end + expect(metadata.send(:gems)).to eql(ret) + end + + it "works on a simple case" do + expect_gem_works(["foo", "~> 1.2"]) + end + + it "works if there's two gems" do + expect_gem_works(["foo", "~> 1.2"], ["bar", "~> 2.0"]) + end + + it "works if there's a more complicated constraint" do + expect_gem_works(["foo", "~> 1.2"], ["bar", ">= 2.4", "< 4.0"]) + end + end + describe "attribute groupings" do it "should allow you set a grouping" do group = { @@ -786,6 +810,8 @@ describe Chef::Cookbook::Metadata do metadata.attribute "bizspark/has_login", :display_name => "You have nothing" metadata.version "1.2.3" + metadata.gem "foo", "~> 1.2" + metadata.gem "bar", ">= 2.2", "< 4.0" metadata.chef_version ">= 11.14.2", "< 11.18.10" metadata.chef_version ">= 12.2.1", "< 12.5.1" metadata.ohai_version ">= 7.1.0", "< 7.5.0" @@ -825,6 +851,7 @@ describe Chef::Cookbook::Metadata do source_url issues_url privacy + gems }.each do |t| it "should include '#{t}'" do expect(deserialized_metadata[t]).to eq(metadata.send(t.to_sym)) @@ -871,6 +898,7 @@ describe Chef::Cookbook::Metadata do privacy chef_versions ohai_versions + gems }.each do |t| it "should match '#{t}'" do expect(deserialized_metadata.send(t.to_sym)).to eq(metadata.send(t.to_sym)) diff --git a/spec/unit/cookbook_version_file_specificity_spec.rb b/spec/unit/cookbook_version_file_specificity_spec.rb index 2bc20ac64e..df9e6571d8 100644 --- a/spec/unit/cookbook_version_file_specificity_spec.rb +++ b/spec/unit/cookbook_version_file_specificity_spec.rb @@ -21,7 +21,7 @@ require "spec_helper" describe Chef::CookbookVersion, "file specificity" do before(:each) do - @cookbook = Chef::CookbookVersion.new "test-cookbook" + @cookbook = Chef::CookbookVersion.new("test-cookbook", "/cookbook-folder") @cookbook.manifest = { "files" => [ @@ -301,6 +301,29 @@ describe Chef::CookbookVersion, "file specificity" do expect(manifest_record[:checksum]).to eq("csum4-platver-full") end + it "should raise a FileNotFound exception without match" do + node = Chef::Node.new + + expect { + @cookbook.preferred_manifest_record(node, :files, "doesn't_exist.rb") + }.to raise_error(Chef::Exceptions::FileNotFound) + end + it "should raise a FileNotFound exception consistently without match" do + node = Chef::Node.new + + expect { + @cookbook.preferred_manifest_record(node, :files, "doesn't_exist.rb") + }.to raise_error(Chef::Exceptions::FileNotFound) + + expect { + @cookbook.preferred_manifest_record(node, :files, "doesn't_exist.rb") + }.to raise_error(Chef::Exceptions::FileNotFound) + + expect { + @cookbook.preferred_manifest_record(node, :files, "doesn't_exist.rb") + }.to raise_error(Chef::Exceptions::FileNotFound) + end + describe "when fetching the contents of a directory by file specificity" do it "should return a directory of manifest records based on priority preference: host" do diff --git a/spec/unit/data_bag_item_spec.rb b/spec/unit/data_bag_item_spec.rb index 7f7d2b3013..99bf89e583 100644 --- a/spec/unit/data_bag_item_spec.rb +++ b/spec/unit/data_bag_item_spec.rb @@ -109,6 +109,24 @@ describe Chef::DataBagItem do end end + describe "class method name" do + let(:data_bag_item) { + data_bag_item = Chef::DataBagItem.new + data_bag_item.data_bag("dreams") + data_bag_item.raw_data = { "id" => "the_beatdown", "name" => "Bruce" } + data_bag_item + } + + it "should return the object name" do + expect(data_bag_item.name).to eq(data_bag_item.object_name) + end + + it "should be distinct from raw_data 'name' key" do + expect(data_bag_item["name"]).to eq("Bruce") + expect(data_bag_item["name"]).not_to eq(data_bag_item.object_name) + end + end + describe "when used like a Hash" do let(:data_bag_item) { data_bag_item = Chef::DataBagItem.new @@ -138,11 +156,41 @@ describe Chef::DataBagItem do end end + describe "from_hash" do + context "when hash contains raw_data" do + let(:data_bag_item) { + Chef::DataBagItem.from_hash({ "raw_data" => { "id" => "whoa", "name" => "Bruce", "i_know" => "kung_fu" } }) + } + + it "should have the id key set" do + expect(data_bag_item["id"]).to eq("whoa") + end + + it "should have the name key set" do + expect(data_bag_item["name"]).to eq("Bruce") + end + end + + context "when hash does not contain raw_data" do + let(:data_bag_item) { + Chef::DataBagItem.from_hash({ "id" => "whoa", "name" => "Bruce", "i_know" => "kung_fu" }) + } + + it "should have the id key set" do + expect(data_bag_item["id"]).to eq("whoa") + end + + it "should have the name key set" do + expect(data_bag_item["name"]).to eq("Bruce") + end + end + end + describe "to_hash" do let(:data_bag_item) { data_bag_item = Chef::DataBagItem.new data_bag_item.data_bag("still_lost") - data_bag_item.raw_data = { "id" => "whoa", "i_know" => "kung_fu" } + data_bag_item.raw_data = { "id" => "whoa", "name" => "Bruce", "i_know" => "kung_fu" } data_bag_item } @@ -156,6 +204,7 @@ describe Chef::DataBagItem do it "should have the raw_data keys as top level keys" do expect(to_hash["id"]).to eq("whoa") + expect(to_hash["name"]).to eq("Bruce") expect(to_hash["i_know"]).to eq("kung_fu") end @@ -177,7 +226,7 @@ describe Chef::DataBagItem do let(:data_bag_item) { data_bag_item = Chef::DataBagItem.new data_bag_item.data_bag("mars_volta") - data_bag_item.raw_data = { "id" => "octahedron", "snooze" => { "finally" => :world_will } } + data_bag_item.raw_data = { "id" => "octahedron", "name" => "Bruce", "snooze" => { "finally" => :world_will } } data_bag_item } @@ -195,6 +244,10 @@ describe Chef::DataBagItem do expect(deserial["id"]).to eq("octahedron") end + it "should have a matching 'name' key" do + expect(deserial["name"]).to eq("Bruce") + end + it "should have a matching 'snooze' key" do expect(deserial["snooze"]).to eq({ "finally" => "world_will" }) end @@ -325,6 +378,11 @@ describe Chef::DataBagItem do expect(item).to be_a_kind_of(Chef::DataBagItem) expect(item).to eq(data_bag_item) end + + it "raises an exception for unknown items" do + expect(Chef::DataBag).to receive(:load).with("users").and_return({ "charlie" => data_bag_item.to_hash }) + expect { Chef::DataBagItem.load("users", "wonka") }.to raise_error Chef::Exceptions::InvalidDataBagItemID + end end end end diff --git a/spec/unit/dsl/resources_spec.rb b/spec/unit/dsl/resources_spec.rb index 53cd6fcdb1..dc05f8bcf4 100644 --- a/spec/unit/dsl/resources_spec.rb +++ b/spec/unit/dsl/resources_spec.rb @@ -25,7 +25,7 @@ describe Chef::DSL::Resources do r = declared_resources Class.new do include Chef::DSL::Resources - define_method(:declare_resource) do |dsl_name, name, _created_at, &_block| + define_method(:declare_resource) do |dsl_name, name, _created_at| r << [dsl_name, name] end end diff --git a/spec/unit/encrypted_data_bag_item/check_encrypted_spec.rb b/spec/unit/encrypted_data_bag_item/check_encrypted_spec.rb index 685c2e738e..c2cb275f9d 100644 --- a/spec/unit/encrypted_data_bag_item/check_encrypted_spec.rb +++ b/spec/unit/encrypted_data_bag_item/check_encrypted_spec.rb @@ -83,7 +83,7 @@ describe Chef::EncryptedDataBagItem::CheckEncrypted do end end - context "when encryption version is 3", :aes_256_gcm_only, :ruby_20_only do + context "when encryption version is 3", :aes_256_gcm_only, ruby: "~> 2.0.0" do include_examples "encryption detected" do let(:version) { 3 } let(:encryptor) { Chef::EncryptedDataBagItem::Encryptor::Version3Encryptor } diff --git a/spec/unit/encrypted_data_bag_item_spec.rb b/spec/unit/encrypted_data_bag_item_spec.rb index e3b77852b7..e17f7a2331 100644 --- a/spec/unit/encrypted_data_bag_item_spec.rb +++ b/spec/unit/encrypted_data_bag_item_spec.rb @@ -97,7 +97,7 @@ describe Chef::EncryptedDataBagItem::Encryptor do Chef::Config[:data_bag_encrypt_version] = 3 end - context "on supported platforms", :aes_256_gcm_only, :ruby_20_only do + context "on supported platforms", :aes_256_gcm_only, ruby: "~> 2.0.0" do it "creates a version 3 encryptor" do expect(encryptor).to be_a_instance_of(Chef::EncryptedDataBagItem::Encryptor::Version3Encryptor) @@ -166,7 +166,7 @@ describe Chef::EncryptedDataBagItem::Decryptor do context "when decrypting a version 3 (JSON+aes-256-gcm+random iv+auth tag) encrypted value" do - context "on supported platforms", :aes_256_gcm_only, :ruby_20_only do + context "on supported platforms", :aes_256_gcm_only, ruby: "~> 2.0.0" do let(:encrypted_value) do Chef::EncryptedDataBagItem::Encryptor::Version3Encryptor.new(plaintext_data, encryption_key).for_encrypted_item diff --git a/spec/unit/knife/bootstrap_spec.rb b/spec/unit/knife/bootstrap_spec.rb index 8ad5c338c3..1508e6e3a7 100644 --- a/spec/unit/knife/bootstrap_spec.rb +++ b/spec/unit/knife/bootstrap_spec.rb @@ -621,9 +621,9 @@ describe Chef::Knife::Bootstrap do end it "use_sudo_password contains description and long params for help" do - expect(knife.options).to have_key(:use_sudo_password) \ - and expect(knife.options[:use_sudo_password][:description].to_s).not_to eq("")\ - and expect(knife.options[:use_sudo_password][:long].to_s).not_to eq("") + expect(knife.options).to(have_key(:use_sudo_password)) \ + && expect(knife.options[:use_sudo_password][:description].to_s).not_to(eq(""))\ + && expect(knife.options[:use_sudo_password][:long].to_s).not_to(eq("")) end it "uses the password from --ssh-password for sudo when --use-sudo-password is set" do diff --git a/spec/unit/knife/cookbook_site_download_spec.rb b/spec/unit/knife/cookbook_site_download_spec.rb index d7f26f2f2e..d283bd417f 100644 --- a/spec/unit/knife/cookbook_site_download_spec.rb +++ b/spec/unit/knife/cookbook_site_download_spec.rb @@ -28,7 +28,7 @@ describe Chef::Knife::CookbookSiteDownload do @stderr = StringIO.new @cookbook_api_url = "https://supermarket.chef.io/api/v1/cookbooks" @version = "1.0.2" - @version_us = @version.gsub ".", "_" + @version_us = @version.tr ".", "_" @current_data = { "deprecated" => false, "latest_version" => "#{@cookbook_api_url}/apache2/versions/#{@version_us}", "replacement" => "other_apache2" } @@ -120,7 +120,7 @@ describe Chef::Knife::CookbookSiteDownload do context "downloading a cookbook of a specific version" do before do @version = "1.0.1" - @version_us = @version.gsub ".", "_" + @version_us = @version.tr ".", "_" @cookbook_data = { "version" => @version, "file" => "http://example.com/apache2_#{@version_us}.tgz" } @temp_file = double(:path => "/tmp/apache2_#{@version_us}.tgz") diff --git a/spec/unit/knife/core/hashed_command_loader_spec.rb b/spec/unit/knife/core/hashed_command_loader_spec.rb index 0135868bf5..081f9deae5 100644 --- a/spec/unit/knife/core/hashed_command_loader_spec.rb +++ b/spec/unit/knife/core/hashed_command_loader_spec.rb @@ -46,6 +46,10 @@ describe Chef::Knife::SubcommandLoader::HashedCommandLoader do plugin_manifest)} describe "#list_commands" do + before do + allow(File).to receive(:exists?).and_return(true) + end + it "lists all commands by category when no argument is given" do expect(loader.list_commands).to eq({ "cool" => ["cool_a"], "cooler" => ["cooler_b"] }) end @@ -53,6 +57,18 @@ describe Chef::Knife::SubcommandLoader::HashedCommandLoader do it "lists only commands in the given category when a category is given" do expect(loader.list_commands("cool")).to eq({ "cool" => ["cool_a"] }) end + + context "when the plugin path is invalid" do + before do + expect(File).to receive(:exists?).with("/file/for/plugin/b").and_return(false) + end + + it "lists all commands by category when no argument is given" do + expect(Chef::Log).to receive(:error).with(/There are files specified in the manifest that are missing/) + expect(Chef::Log).to receive(:error).with("Missing files:\n\t/file/for/plugin/b") + expect(loader.list_commands).to eq({}) + end + end end describe "#subcommand_files" do diff --git a/spec/unit/knife/core/subcommand_loader_spec.rb b/spec/unit/knife/core/subcommand_loader_spec.rb index 6cda244132..b235102a0b 100644 --- a/spec/unit/knife/core/subcommand_loader_spec.rb +++ b/spec/unit/knife/core/subcommand_loader_spec.rb @@ -61,4 +61,10 @@ describe Chef::Knife::SubcommandLoader do end end end + + describe "#gem_glob_loader" do + it "always creates a GemGlobLoader" do + expect(Chef::Knife::SubcommandLoader.gem_glob_loader(config_dir)).to be_a Chef::Knife::SubcommandLoader::GemGlobLoader + end + end end diff --git a/spec/unit/knife/environment_compare_spec.rb b/spec/unit/knife/environment_compare_spec.rb index 863cdd4e6e..e408532884 100644 --- a/spec/unit/knife/environment_compare_spec.rb +++ b/spec/unit/knife/environment_compare_spec.rb @@ -62,7 +62,7 @@ describe Chef::Knife::EnvironmentCompare do @knife.config[:format] = "summary" @knife.run @environments.each do |item, url| - expect(@stdout.string).to match /#{item}/ and expect(@stdout.string.lines.count).to be 4 + expect(@stdout.string).to(match /#{item}/) && expect(@stdout.string.lines.count).to(be 4) end end diff --git a/spec/unit/knife_spec.rb b/spec/unit/knife_spec.rb index 698ae205f1..ec1e59d863 100644 --- a/spec/unit/knife_spec.rb +++ b/spec/unit/knife_spec.rb @@ -23,6 +23,7 @@ end require "spec_helper" require "uri" +require "chef/knife/core/gem_glob_loader" describe Chef::Knife do @@ -148,6 +149,12 @@ describe Chef::Knife do expect(Chef::Knife.subcommand_class_from(%w{cookbook site vendor --help foo bar baz})).to eq(:CookbookSiteVendor) end + it "special case sets the subcommand_loader to GemGlobLoader when running rehash" do + Chef::Knife.subcommands["rehash"] = :Rehash + expect(Chef::Knife.subcommand_class_from(%w{rehash })).to eq(:Rehash) + expect(Chef::Knife.subcommand_loader).to be_a(Chef::Knife::SubcommandLoader::GemGlobLoader) + end + end describe "the headers include X-Remote-Request-Id" do diff --git a/spec/unit/mixin/shell_out_spec.rb b/spec/unit/mixin/shell_out_spec.rb index e9fabfd0a7..2dedd7d364 100644 --- a/spec/unit/mixin/shell_out_spec.rb +++ b/spec/unit/mixin/shell_out_spec.rb @@ -53,7 +53,7 @@ describe Chef::Mixin::ShellOut do def self.should_emit_deprecation_warning_about(old_option, new_option) it "should emit a deprecation warning" do - assume_deprecation_log_level and capture_log_output + assume_deprecation_log_level && capture_log_output subject expect(output.string).to match /DEPRECATION:/ expect(output.string).to match Regexp.escape(old_option.to_s) diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb index 29f386aa7d..923b488f72 100644 --- a/spec/unit/node_spec.rb +++ b/spec/unit/node_spec.rb @@ -1511,7 +1511,7 @@ describe Chef::Node do # added the policyfile attributes to the node JSON, therefore # policyfile users need to be on 12.3 minimum when upgrading Chef # Client to 13+ - it "lets the 400 pass through", :chef_gte_13_only do + it "lets the 400 pass through", chef: ">= 13" do expect { node.save }.to raise_error(http_exception) end diff --git a/spec/unit/policy_builder/expand_node_object_spec.rb b/spec/unit/policy_builder/expand_node_object_spec.rb index 8667532d72..420db2e855 100644 --- a/spec/unit/policy_builder/expand_node_object_spec.rb +++ b/spec/unit/policy_builder/expand_node_object_spec.rb @@ -38,7 +38,7 @@ describe Chef::PolicyBuilder::ExpandNodeObject do expect(policy_builder).to respond_to(:load_node) end - it "has removed the deprecated #load_node method", :chef_gte_13_only do + it "has removed the deprecated #load_node method", chef: ">= 13" do expect(policy_builder).to_not respond_to(:load_node) end diff --git a/spec/unit/policy_builder/policyfile_spec.rb b/spec/unit/policy_builder/policyfile_spec.rb index 6dab6d14b2..0f345ee344 100644 --- a/spec/unit/policy_builder/policyfile_spec.rb +++ b/spec/unit/policy_builder/policyfile_spec.rb @@ -658,6 +658,7 @@ describe Chef::PolicyBuilder::Policyfile do expect(cookbook_synchronizer).to receive(:sync_cookbooks) expect_any_instance_of(Chef::RunContext).to receive(:load).with(policy_builder.run_list_expansion_ish) expect_any_instance_of(Chef::CookbookCollection).to receive(:validate!) + expect_any_instance_of(Chef::CookbookCollection).to receive(:install_gems) run_context = policy_builder.setup_run_context expect(run_context.node).to eq(node) expect(run_context.cookbook_collection.keys).to match_array(%w{example1 example2}) @@ -667,6 +668,7 @@ describe Chef::PolicyBuilder::Policyfile do expect(cookbook_synchronizer).to receive(:sync_cookbooks) expect_any_instance_of(Chef::RunContext).to receive(:load).with(policy_builder.run_list_expansion_ish) expect_any_instance_of(Chef::CookbookCollection).to receive(:validate!) + expect_any_instance_of(Chef::CookbookCollection).to receive(:install_gems) run_context = policy_builder.setup_run_context expect(Chef.run_context).to eq(run_context) end diff --git a/spec/unit/provider/execute_spec.rb b/spec/unit/provider/execute_spec.rb index c0646f2999..4b0afcb928 100644 --- a/spec/unit/provider/execute_spec.rb +++ b/spec/unit/provider/execute_spec.rb @@ -118,7 +118,7 @@ describe Chef::Provider::Execute do new_resource.creates "foo_resource" end - it "should warn in Chef-12", :chef_lt_13_only do + it "should warn in Chef-12", chef: "< 13" do expect(Chef::Log).to receive(:warn).with(/relative path/) expect(FileTest).to receive(:exist?).with(new_resource.creates).and_return(true) expect(provider).not_to receive(:shell_out!) @@ -126,7 +126,7 @@ describe Chef::Provider::Execute do expect(new_resource).not_to be_updated end - it "should raise if user specified relative path without cwd for Chef-13", :chef_gte_13_only do + it "should raise if user specified relative path without cwd for Chef-13", chef: ">= 13" do expect(Chef::Log).to receive(:warn).with(/relative path/) expect(FileTest).to receive(:exist?).with(new_resource.creates).and_return(true) expect(provider).not_to receive(:shell_out!) diff --git a/spec/unit/provider/link_spec.rb b/spec/unit/provider/link_spec.rb index 31065d7bfd..6bb08551a2 100644 --- a/spec/unit/provider/link_spec.rb +++ b/spec/unit/provider/link_spec.rb @@ -39,7 +39,7 @@ describe Chef::Resource::Link, :not_supported_on_win2k3 do end def canonicalize(path) - Chef::Platform.windows? ? path.gsub("/", '\\') : path + Chef::Platform.windows? ? path.tr("/", '\\') : path end describe "when the target is a symlink" do diff --git a/spec/unit/provider/mount/windows_spec.rb b/spec/unit/provider/mount/windows_spec.rb index ab7a161c08..ec1945de50 100644 --- a/spec/unit/provider/mount/windows_spec.rb +++ b/spec/unit/provider/mount/windows_spec.rb @@ -120,6 +120,18 @@ describe Chef::Provider::Mount::Windows do @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) + expect(@provider.send :mount_options_unchanged?).to be true + end + + it "should return false if mounted device has changed" do + allow(@current_resource).to receive(:device).and_return("XXXX") + 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) diff --git a/spec/unit/provider/service/systemd_service_spec.rb b/spec/unit/provider/service/systemd_service_spec.rb index b445d93aeb..e0a94127b7 100644 --- a/spec/unit/provider/service/systemd_service_spec.rb +++ b/spec/unit/provider/service/systemd_service_spec.rb @@ -1,5 +1,6 @@ # # Author:: Stephen Haynes (<sh@nomitor.com>) +# Author:: Davide Cavalca (<dcavalca@fb.com>) # Copyright:: Copyright 2011-2016, Chef Software Inc. # License:: Apache License, Version 2.0 # @@ -20,7 +21,16 @@ require "spec_helper" describe Chef::Provider::Service::Systemd do - let(:node) { Chef::Node.new } + let(:node) { + node = Chef::Node.new + node.default["etc"] = Hash.new + node.default["etc"]["passwd"] = { + "joe" => { + "uid" => 10000, + }, + } + node + } let(:events) { Chef::EventDispatch::Dispatcher.new } @@ -51,6 +61,7 @@ describe Chef::Provider::Service::Systemd do before(:each) do allow(provider).to receive(:is_active?).and_return(false) allow(provider).to receive(:is_enabled?).and_return(false) + allow(provider).to receive(:is_masked?).and_return(false) end it "should create a current resource with the name of the new resource" do @@ -127,6 +138,23 @@ describe Chef::Provider::Service::Systemd do expect(current_resource.enabled).to be false end + it "should check if the service is masked" do + expect(provider).to receive(:is_masked?) + provider.load_current_resource + end + + it "should set masked to true if the service is masked" do + allow(provider).to receive(:is_masked?).and_return(true) + provider.load_current_resource + expect(current_resource.masked).to be true + end + + it "should set masked to false if the service is not masked" do + allow(provider).to receive(:is_masked?).and_return(false) + provider.load_current_resource + expect(current_resource.masked).to be false + end + it "should return the current resource" do expect(provider.load_current_resource).to eql(current_resource) end @@ -152,15 +180,32 @@ describe Chef::Provider::Service::Systemd do provider.start_service end - it "should call '#{systemctl_path} start service_name' if no start command is specified" do - expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} start #{service_name}").and_return(shell_out_success) - provider.start_service + context "when a user is not specified" do + it "should call '#{systemctl_path} --system start service_name' if no start command is specified" do + expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system start #{service_name}", {}).and_return(shell_out_success) + provider.start_service + end + + it "should not call '#{systemctl_path} --system start service_name' if it is already running" do + current_resource.running(true) + expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system start #{service_name}", {}) + provider.start_service + end end - it "should not call '#{systemctl_path} start service_name' if it is already running" do - current_resource.running(true) - expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} start #{service_name}") - provider.start_service + context "when a user is specified" do + it "should call '#{systemctl_path} --user start service_name' if no start command is specified" do + current_resource.user("joe") + expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --user start #{service_name}", { "environment" => { "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/10000/bus" }, "user" => "joe" }).and_return(shell_out_success) + provider.start_service + end + + it "should not call '#{systemctl_path} --user start service_name' if it is already running" do + current_resource.running(true) + current_resource.user("joe") + expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --user start #{service_name}", { "environment" => { "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/10000/bus" }, "user" => "joe" }) + provider.start_service + end end it "should call the restart command if one is specified" do @@ -170,9 +215,9 @@ describe Chef::Provider::Service::Systemd do provider.restart_service end - it "should call '#{systemctl_path} restart service_name' if no restart command is specified" do + it "should call '#{systemctl_path} --system restart service_name' if no restart command is specified" do current_resource.running(true) - expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} restart #{service_name}").and_return(shell_out_success) + expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system restart #{service_name}", {}).and_return(shell_out_success) provider.restart_service end @@ -187,9 +232,9 @@ describe Chef::Provider::Service::Systemd do end context "when a reload command is not specified" do - it "should call '#{systemctl_path} reload service_name' if the service is running" do + it "should call '#{systemctl_path} --system reload service_name' if the service is running" do current_resource.running(true) - expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} reload #{service_name}").and_return(shell_out_success) + expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system reload #{service_name}", {}).and_return(shell_out_success) provider.reload_service end @@ -208,15 +253,15 @@ describe Chef::Provider::Service::Systemd do provider.stop_service end - it "should call '#{systemctl_path} stop service_name' if no stop command is specified" do + it "should call '#{systemctl_path} --system stop service_name' if no stop command is specified" do current_resource.running(true) - expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} stop #{service_name}").and_return(shell_out_success) + expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system stop #{service_name}", {}).and_return(shell_out_success) provider.stop_service end - it "should not call '#{systemctl_path} stop service_name' if it is already stopped" do + it "should not call '#{systemctl_path} --system stop service_name' if it is already stopped" do current_resource.running(false) - expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} stop #{service_name}") + expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system stop #{service_name}", {}) provider.stop_service end end @@ -228,17 +273,35 @@ describe Chef::Provider::Service::Systemd do allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}") end - it "should call '#{systemctl_path} enable service_name' to enable the service" do - expect(provider).to receive(:shell_out!).with("#{systemctl_path} enable #{service_name}").and_return(shell_out_success) + it "should call '#{systemctl_path} --system enable service_name' to enable the service" do + expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system enable #{service_name}", {}).and_return(shell_out_success) provider.enable_service end - it "should call '#{systemctl_path} disable service_name' to disable the service" do - expect(provider).to receive(:shell_out!).with("#{systemctl_path} disable #{service_name}").and_return(shell_out_success) + it "should call '#{systemctl_path} --system disable service_name' to disable the service" do + expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system disable #{service_name}", {}).and_return(shell_out_success) provider.disable_service end end + describe "mask and unmask service" do + before(:each) do + provider.current_resource = current_resource + current_resource.service_name(service_name) + allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}") + end + + it "should call '#{systemctl_path} --system mask service_name' to mask the service" do + expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system mask #{service_name}", {}).and_return(shell_out_success) + provider.mask_service + end + + it "should call '#{systemctl_path} --system unmask service_name' to unmask the service" do + expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system unmask #{service_name}", {}).and_return(shell_out_success) + provider.unmask_service + end + end + describe "is_active?" do before(:each) do provider.current_resource = current_resource @@ -246,13 +309,13 @@ describe Chef::Provider::Service::Systemd do allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}") end - it "should return true if '#{systemctl_path} is-active service_name' returns 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} is-active #{service_name} --quiet").and_return(shell_out_success) + it "should return true if '#{systemctl_path} --system is-active service_name' returns 0" do + expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-active #{service_name} --quiet", {}).and_return(shell_out_success) expect(provider.is_active?).to be true end - it "should return false if '#{systemctl_path} is-active service_name' returns anything except 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} is-active #{service_name} --quiet").and_return(shell_out_failure) + it "should return false if '#{systemctl_path} --system is-active service_name' returns anything except 0" do + expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-active #{service_name} --quiet", {}).and_return(shell_out_failure) expect(provider.is_active?).to be false end end @@ -264,16 +327,44 @@ describe Chef::Provider::Service::Systemd do allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}") end - it "should return true if '#{systemctl_path} is-enabled service_name' returns 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} is-enabled #{service_name} --quiet").and_return(shell_out_success) + it "should return true if '#{systemctl_path} --system is-enabled service_name' returns 0" do + expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name} --quiet", {}).and_return(shell_out_success) expect(provider.is_enabled?).to be true end - it "should return false if '#{systemctl_path} is-enabled service_name' returns anything except 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} is-enabled #{service_name} --quiet").and_return(shell_out_failure) + it "should return false if '#{systemctl_path} --system is-enabled service_name' returns anything except 0" do + expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name} --quiet", {}).and_return(shell_out_failure) expect(provider.is_enabled?).to be false end end + + describe "is_masked?" do + before(:each) do + provider.current_resource = current_resource + current_resource.service_name(service_name) + allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}") + end + + it "should return true if '#{systemctl_path} --system is-enabled service_name' returns 'masked' and returns anything except 0" do + expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "masked", :exitstatus => shell_out_failure)) + expect(provider.is_masked?).to be true + end + + it "should return true if '#{systemctl_path} --system is-enabled service_name' outputs 'masked-runtime' and returns anything except 0" do + expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "masked-runtime", :exitstatus => shell_out_failure)) + expect(provider.is_masked?).to be true + end + + it "should return false if '#{systemctl_path} --system is-enabled service_name' returns 0" do + expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "enabled", :exitstatus => shell_out_success)) + expect(provider.is_masked?).to be false + end + + it "should return false if '#{systemctl_path} --system is-enabled service_name' returns anything except 0 and outputs an error'" do + expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "Failed to get unit file state for #{service_name}: No such file or directory", :exitstatus => shell_out_failure)) + expect(provider.is_masked?).to be false + end + end end end end diff --git a/spec/unit/resource/chef_gem_spec.rb b/spec/unit/resource/chef_gem_spec.rb index 0de9247196..c98b447582 100644 --- a/spec/unit/resource/chef_gem_spec.rb +++ b/spec/unit/resource/chef_gem_spec.rb @@ -70,14 +70,14 @@ describe Chef::Resource::ChefGem, "gem_binary" do expect(Chef::Resource::ChefGem).to receive(:new).and_return(resource) end - it "runs the install at compile-time by default", :chef_lt_13_only do + it "runs the install at compile-time by default", chef: "< 13" do expect(resource).to receive(:run_action).with(:install) expect(Chef::Log).to receive(:deprecation).at_least(:once) recipe.chef_gem "foo" end # the default behavior will change in Chef-13 - it "does not runs the install at compile-time by default", :chef_gte_13_only do + it "does not runs the install at compile-time by default", chef: ">= 13" do expect(resource).not_to receive(:run_action).with(:install) expect(Chef::Log).not_to receive(:deprecation) recipe.chef_gem "foo" diff --git a/spec/unit/run_list/versioned_recipe_list_spec.rb b/spec/unit/run_list/versioned_recipe_list_spec.rb index 8bbd816956..91c601b294 100644 --- a/spec/unit/run_list/versioned_recipe_list_spec.rb +++ b/spec/unit/run_list/versioned_recipe_list_spec.rb @@ -186,7 +186,7 @@ describe Chef::RunList::VersionedRecipeList do end end - context "with duplicated names", :chef_gte_13_only do + context "with duplicated names", chef: ">= 13" do it "should fail in Chef 13" do expect(list).to_not respond_to(:with_duplicate_names) end diff --git a/tasks/external_tests.rb b/tasks/external_tests.rb index f6fd79c86b..a909ec2178 100644 --- a/tasks/external_tests.rb +++ b/tasks/external_tests.rb @@ -58,7 +58,7 @@ EXTERNAL_PROJECTS = { task :external_specs => EXTERNAL_PROJECTS.keys.map { |g| :"#{g.sub("-", "_")}_spec" } EXTERNAL_PROJECTS.each do |test_gem, commands| - task :"#{test_gem.gsub("-", "_")}_spec" do + task :"#{test_gem.tr("-", "_")}_spec" do bundle_exec_with_chef(test_gem, commands) end end |