From 8a7e29d52882c39d0c903eef83bd3472e4f334af Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Fri, 8 Nov 2019 14:06:33 -0800 Subject: Add chef-utils gem with various recipe DSL helpers This is the implementation of [RFC-087](https://github.com/chef-boneyard/chef-rfc/blob/master/rfc087-distro-sugar-helpers.md) although some of the specifics have been iterated on and changed. The documentation will be in the [README.md](https://github.com/chef/chef/tree/master/chef-utils/README.md) once this is merged. While this PR mostly moves chef-sugar utilities into core-chef via this chef-utils gem, the scope of the chef-utils gem should be considered larger than just that. As an example this PR moves the Mash class into this gem for reuse in ohai as well. Signed-off-by: Lamont Granquist --- .expeditor/config.yml | 1 + .expeditor/update_version.sh | 3 +- .gitignore | 5 + Gemfile | 2 + Gemfile.lock | 20 +- Rakefile | 8 +- chef-config/Gemfile | 2 + chef-config/chef-config.gemspec | 1 + chef-config/lib/chef-config/config.rb | 11 +- chef-config/lib/chef-config/exceptions.rb | 2 +- chef-config/lib/chef-config/fips.rb | 6 +- chef-config/lib/chef-config/path_helper.rb | 15 +- chef-config/lib/chef-config/version.rb | 17 +- chef-config/lib/chef-config/windows.rb | 12 +- .../lib/chef-config/workstation_config_loader.rb | 5 +- chef-config/spec/spec_helper.rb | 6 +- chef-config/spec/unit/config_spec.rb | 2 +- chef-config/spec/unit/fips_spec.rb | 6 +- chef-config/spec/unit/path_helper_spec.rb | 12 +- .../spec/unit/workstation_config_loader_spec.rb | 6 +- chef-utils/.rspec | 2 + chef-utils/Gemfile | 9 + chef-utils/LICENSE | 201 ++++++++++++ chef-utils/README.md | 209 +++++++++++++ chef-utils/Rakefile | 13 + chef-utils/chef-utils.gemspec | 47 +++ chef-utils/lib/chef-utils.rb | 43 +++ chef-utils/lib/chef-utils/dsl/architecture.rb | 117 +++++++ chef-utils/lib/chef-utils/dsl/introspection.rb | 93 ++++++ chef-utils/lib/chef-utils/dsl/os.rb | 55 ++++ chef-utils/lib/chef-utils/dsl/path_sanity.rb | 58 ++++ chef-utils/lib/chef-utils/dsl/platform.rb | 339 +++++++++++++++++++++ chef-utils/lib/chef-utils/dsl/platform_family.rb | 282 +++++++++++++++++ chef-utils/lib/chef-utils/dsl/service.rb | 91 ++++++ chef-utils/lib/chef-utils/dsl/train_helpers.rb | 63 ++++ chef-utils/lib/chef-utils/dsl/which.rb | 118 +++++++ chef-utils/lib/chef-utils/internal.rb | 77 +++++ chef-utils/lib/chef-utils/mash.rb | 239 +++++++++++++++ chef-utils/lib/chef-utils/version.rb | 19 ++ chef-utils/spec/spec_helper.rb | 93 ++++++ chef-utils/spec/unit/dsl/architecture_spec.rb | 139 +++++++++ chef-utils/spec/unit/dsl/dsl_spec.rb | 33 ++ chef-utils/spec/unit/dsl/introspection_spec.rb | 168 ++++++++++ chef-utils/spec/unit/dsl/os_spec.rb | 174 +++++++++++ chef-utils/spec/unit/dsl/path_sanity_spec.rb | 85 ++++++ chef-utils/spec/unit/dsl/platform_family_spec.rb | 192 ++++++++++++ chef-utils/spec/unit/dsl/platform_spec.rb | 234 ++++++++++++++ chef-utils/spec/unit/dsl/service_spec.rb | 116 +++++++ chef-utils/spec/unit/dsl/which_spec.rb | 168 ++++++++++ chef-utils/spec/unit/mash_spec.rb | 50 +++ chef.gemspec | 1 + lib/chef/application.rb | 4 +- lib/chef/application/client.rb | 2 +- lib/chef/application/solo.rb | 2 +- lib/chef/chef_class.rb | 7 +- lib/chef/chef_fs.rb | 2 +- lib/chef/chef_fs/file_pattern.rb | 2 +- .../chef_server/cookbook_artifacts_dir.rb | 2 +- .../chef_server/versioned_cookbooks_dir.rb | 2 +- .../chef_repository_file_system_root_dir.rb | 6 +- .../chef_fs/file_system/repository/nodes_dir.rb | 6 +- lib/chef/chef_fs/knife.rb | 2 +- lib/chef/chef_fs/path_utils.rb | 4 +- lib/chef/client.rb | 9 +- lib/chef/config.rb | 5 +- lib/chef/dsl/core.rb | 2 +- lib/chef/dsl/platform_introspection.rb | 27 +- lib/chef/event_loggers/windows_eventlog.rb | 2 +- lib/chef/file_content_management/deploy.rb | 6 +- .../file_content_management/deploy/mv_windows.rb | 4 +- lib/chef/file_content_management/tempfile.rb | 2 +- .../error_inspectors/resource_failure_inspector.rb | 4 +- lib/chef/http.rb | 2 +- lib/chef/http/socketless_chef_zero_client.rb | 2 +- lib/chef/knife.rb | 7 +- lib/chef/local_mode.rb | 2 +- lib/chef/mash.rb | 253 ++------------- lib/chef/mixin/file_class.rb | 4 +- lib/chef/mixin/lazy_module_include.rb | 2 +- lib/chef/mixin/path_sanity.rb | 42 +-- lib/chef/mixin/securable.rb | 2 +- lib/chef/mixin/shell_out.rb | 9 +- lib/chef/mixin/template.rb | 2 +- lib/chef/mixin/train_helpers.rb | 60 ---- lib/chef/mixin/user_context.rb | 6 +- lib/chef/mixin/which.rb | 48 +-- lib/chef/mixin/windows_architecture_helper.rb | 12 +- lib/chef/mixin/windows_env_helper.rb | 10 +- lib/chef/node_map.rb | 21 +- lib/chef/platform/query_helpers.rb | 6 +- lib/chef/platform/rebooter.rb | 2 +- lib/chef/platform/service_helpers.rb | 99 +----- lib/chef/provider.rb | 2 + lib/chef/provider/file.rb | 2 +- lib/chef/provider/ifconfig/redhat.rb | 2 +- lib/chef/provider/link.rb | 6 +- lib/chef/provider/mount/solaris.rb | 2 +- lib/chef/provider/package/yum.rb | 2 +- lib/chef/provider/registry_key.rb | 2 +- lib/chef/provider/remote_directory.rb | 6 +- lib/chef/provider/remote_file/fetcher.rb | 4 +- lib/chef/provider/remote_file/local_file.rb | 2 +- lib/chef/provider/script.rb | 6 +- lib/chef/provider/service.rb | 7 +- lib/chef/provider/service/arch.rb | 2 +- lib/chef/provider/service/debian.rb | 8 +- lib/chef/provider/service/init.rb | 2 +- lib/chef/provider/service/insserv.rb | 8 +- lib/chef/provider/service/invokercd.rb | 8 +- lib/chef/provider/service/redhat.rb | 8 +- lib/chef/provider/service/systemd.rb | 6 +- lib/chef/provider/service/upstart.rb | 6 +- lib/chef/provider/subversion.rb | 2 +- lib/chef/provider/windows_path.rb | 6 +- lib/chef/provider/windows_task.rb | 8 +- lib/chef/resource.rb | 1 + lib/chef/resource/build_essential.rb | 4 +- lib/chef/resource/file.rb | 2 +- lib/chef/resource/link.rb | 4 +- lib/chef/resource/remote_directory.rb | 4 +- lib/chef/resource/service.rb | 7 +- lib/chef/resource/solaris_package.rb | 2 +- lib/chef/resource/yum_package.rb | 2 +- lib/chef/run_context.rb | 2 +- lib/chef/run_lock.rb | 10 +- lib/chef/train_transport.rb | 4 +- lib/chef/util/powershell/ps_credential.rb | 4 +- lib/chef/util/selinux.rb | 2 +- lib/chef/util/windows/logon_session.rb | 4 +- lib/chef/win32/eventlog.rb | 4 +- omnibus/config/projects/chef.rb | 2 +- .../event_loggers/windows_eventlog_spec.rb | 2 +- spec/functional/mixin/user_context_spec.rb | 4 +- spec/functional/rebooter_spec.rb | 2 +- spec/functional/resource/cookbook_file_spec.rb | 4 +- spec/functional/resource/template_spec.rb | 2 +- spec/functional/win32/crypto_spec.rb | 2 +- spec/functional/win32/security_spec.rb | 2 +- spec/functional/win32/service_manager_spec.rb | 2 +- spec/functional/win32/sid_spec.rb | 4 +- spec/functional/win32/version_info_spec.rb | 2 +- spec/functional/win32/versions_spec.rb | 2 +- spec/integration/knife/config_get_profile_spec.rb | 4 +- spec/integration/knife/config_get_spec.rb | 4 +- .../integration/knife/config_list_profiles_spec.rb | 4 +- spec/integration/knife/config_use_profile_spec.rb | 4 +- spec/integration/knife/list_spec.rb | 4 +- spec/integration/solo/solo_spec.rb | 2 +- spec/support/matchers/leak.rb | 2 +- spec/support/mock/platform.rb | 2 +- spec/support/platform_helpers.rb | 2 + .../shared/integration/integration_helper.rb | 2 +- spec/support/shared/integration/knife_support.rb | 2 +- spec/support/shared/unit/provider/file.rb | 8 +- spec/unit/application/client_spec.rb | 4 +- spec/unit/application_spec.rb | 2 +- spec/unit/chef_fs/file_pattern_spec.rb | 4 +- spec/unit/chef_fs/path_util_spec.rb | 6 +- spec/unit/client_spec.rb | 4 +- spec/unit/cookbook/cookbook_version_loader_spec.rb | 2 +- spec/unit/cookbook/syntax_check_spec.rb | 4 +- spec/unit/cookbook_loader_spec.rb | 2 +- spec/unit/data_bag_spec.rb | 4 +- spec/unit/dsl/platform_introspection_spec.rb | 32 +- .../deploy/mv_windows_spec.rb | 2 +- .../compile_error_inspector_spec.rb | 2 +- spec/unit/knife/core/gem_glob_loader_spec.rb | 2 +- spec/unit/knife/core/hashed_command_loader_spec.rb | 2 +- spec/unit/knife/core/subcommand_loader_spec.rb | 2 +- spec/unit/knife/core/ui_spec.rb | 4 +- spec/unit/knife/data_bag_from_file_spec.rb | 4 +- spec/unit/knife/environment_from_file_spec.rb | 4 +- spec/unit/knife/supermarket_install_spec.rb | 2 +- spec/unit/mash_spec.rb | 51 ---- spec/unit/mixin/path_sanity_spec.rb | 6 +- spec/unit/mixin/shell_out_spec.rb | 5 +- spec/unit/mixin/template_spec.rb | 8 +- spec/unit/mixin/user_context_spec.rb | 6 +- spec/unit/node_map_spec.rb | 24 +- spec/unit/platform/query_helpers_spec.rb | 18 +- spec/unit/provider/execute_spec.rb | 2 +- spec/unit/provider/link_spec.rb | 10 +- spec/unit/provider/package/windows/exe_spec.rb | 2 +- spec/unit/provider/package/windows_spec.rb | 4 +- spec/unit/provider/remote_file/fetcher_spec.rb | 4 +- spec/unit/provider/remote_file/local_file_spec.rb | 2 +- .../unit/provider/remote_file/network_file_spec.rb | 2 +- spec/unit/provider/script_spec.rb | 4 +- spec/unit/provider/subversion_spec.rb | 6 +- spec/unit/provider/user/dscl_spec.rb | 2 +- spec/unit/provider_resolver_spec.rb | 102 +++---- spec/unit/resource/cookbook_file_spec.rb | 6 +- spec/unit/resource/remote_file_spec.rb | 6 +- spec/unit/role_spec.rb | 4 +- spec/unit/shell_spec.rb | 2 +- spec/unit/util/selinux_spec.rb | 4 +- spec/unit/win32/error_spec.rb | 2 +- spec/unit/win32/link_spec.rb | 2 +- spec/unit/win32/security_spec.rb | 2 +- spec/unit/windows_service_spec.rb | 2 +- tasks/rspec.rb | 14 +- 201 files changed, 4048 insertions(+), 938 deletions(-) create mode 100644 chef-utils/.rspec create mode 100644 chef-utils/Gemfile create mode 100644 chef-utils/LICENSE create mode 100644 chef-utils/README.md create mode 100644 chef-utils/Rakefile create mode 100644 chef-utils/chef-utils.gemspec create mode 100644 chef-utils/lib/chef-utils.rb create mode 100644 chef-utils/lib/chef-utils/dsl/architecture.rb create mode 100644 chef-utils/lib/chef-utils/dsl/introspection.rb create mode 100644 chef-utils/lib/chef-utils/dsl/os.rb create mode 100644 chef-utils/lib/chef-utils/dsl/path_sanity.rb create mode 100644 chef-utils/lib/chef-utils/dsl/platform.rb create mode 100644 chef-utils/lib/chef-utils/dsl/platform_family.rb create mode 100644 chef-utils/lib/chef-utils/dsl/service.rb create mode 100644 chef-utils/lib/chef-utils/dsl/train_helpers.rb create mode 100644 chef-utils/lib/chef-utils/dsl/which.rb create mode 100644 chef-utils/lib/chef-utils/internal.rb create mode 100644 chef-utils/lib/chef-utils/mash.rb create mode 100644 chef-utils/lib/chef-utils/version.rb create mode 100644 chef-utils/spec/spec_helper.rb create mode 100644 chef-utils/spec/unit/dsl/architecture_spec.rb create mode 100644 chef-utils/spec/unit/dsl/dsl_spec.rb create mode 100644 chef-utils/spec/unit/dsl/introspection_spec.rb create mode 100644 chef-utils/spec/unit/dsl/os_spec.rb create mode 100644 chef-utils/spec/unit/dsl/path_sanity_spec.rb create mode 100644 chef-utils/spec/unit/dsl/platform_family_spec.rb create mode 100644 chef-utils/spec/unit/dsl/platform_spec.rb create mode 100644 chef-utils/spec/unit/dsl/service_spec.rb create mode 100644 chef-utils/spec/unit/dsl/which_spec.rb create mode 100644 chef-utils/spec/unit/mash_spec.rb delete mode 100644 lib/chef/mixin/train_helpers.rb delete mode 100644 spec/unit/mash_spec.rb diff --git a/.expeditor/config.yml b/.expeditor/config.yml index 9d3e5b85b2..d484a18177 100644 --- a/.expeditor/config.yml +++ b/.expeditor/config.yml @@ -18,6 +18,7 @@ rubygems: - chef - chef-config - chef-bin + - chef-utils docker_images: - chef diff --git a/.expeditor/update_version.sh b/.expeditor/update_version.sh index 85f7340811..b362157d4b 100755 --- a/.expeditor/update_version.sh +++ b/.expeditor/update_version.sh @@ -13,10 +13,11 @@ set -evx sed -i -r "s/^(\s*)VERSION = \".+\"/\1VERSION = \"$(cat VERSION)\"/" chef-config/lib/chef-config/version.rb sed -i -r "s/^(\s*)VERSION = \".+\"/\1VERSION = \"$(cat VERSION)\"/" chef-bin/lib/chef-bin/version.rb +sed -i -r "s/^(\s*)VERSION = \".+\"/\1VERSION = \"$(cat VERSION)\"/" chef-utils/lib/chef-utils/version.rb sed -i -r "s/VersionString\.new\(\".+\"\)/VersionString.new(\"$(cat VERSION)\")/" lib/chef/version.rb # Update the version inside Gemfile.lock -bundle update chef chef-config --jobs=7 --conservative +bundle update chef chef-config chef-utils --jobs=7 --conservative # Once Expeditor finishes executing this script, it will commit the changes and push # the commit as a new tag corresponding to the value in the VERSION file. diff --git a/.gitignore b/.gitignore index ed1d93ca31..7435401e97 100644 --- a/.gitignore +++ b/.gitignore @@ -70,6 +70,11 @@ chef-bin/.bundle chef-bin/Gemfile.lock chef-bin/pkg +# chef-utils +chef-utils/.bundle +chef-utils/Gemfile.lock +chef-utils/pkg + # auto generated docs from the docs.rb rake task docs_site diff --git a/Gemfile b/Gemfile index 39436e3057..710aa25529 100644 --- a/Gemfile +++ b/Gemfile @@ -10,6 +10,7 @@ gem "chef", path: "." # necessary until we release ohai 15 gem "ohai", git: "https://github.com/chef/ohai.git", branch: "master" +gem "chef-utils", path: File.expand_path("../chef-utils", __FILE__) if File.exist?(File.expand_path("../chef-utils", __FILE__)) gem "chef-config", path: File.expand_path("../chef-config", __FILE__) if File.exist?(File.expand_path("../chef-config", __FILE__)) if File.exist?(File.expand_path("../chef-bin", __FILE__)) @@ -65,6 +66,7 @@ group(:development, :test) do gem "rspec_junit_formatter", "~> 0.2.0" gem "simplecov" gem "webmock" + gem "fauxhai-ng" # for chef-utils gem end group(:chefstyle) do diff --git a/Gemfile.lock b/Gemfile.lock index dcc68e57cd..0fb4707693 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,10 @@ GIT remote: https://github.com/chef/chefstyle.git - revision: 6c2d8583fd345c09c7931e2f8c0ed33a48925c40 + revision: c12114af6196c4bc843bb39b930f6141a3239ff5 branch: master specs: - chefstyle (0.13.3) - rubocop (= 0.72.0) + chefstyle (0.14.0) + rubocop (= 0.75.1) GIT remote: https://github.com/chef/ohai.git @@ -32,6 +32,7 @@ PATH bcrypt_pbkdf (~> 1.0) bundler (>= 1.10) chef-config (= 15.4.69) + chef-utils (= 15.4.69) chef-zero (>= 14.0.11) diff-lcs (~> 1.2, >= 1.2.4) ed25519 (~> 1.2) @@ -63,6 +64,7 @@ PATH bcrypt_pbkdf (~> 1.0) bundler (>= 1.10) chef-config (= 15.4.69) + chef-utils (= 15.4.69) chef-zero (>= 14.0.11) diff-lcs (~> 1.2, >= 1.2.4) ed25519 (~> 1.2) @@ -113,11 +115,17 @@ PATH specs: chef-config (15.4.69) addressable + chef-utils (= 15.4.69) fuzzyurl mixlib-config (>= 2.2.12, < 4.0) mixlib-shellout (>= 2.0, < 4.0) tomlrb (~> 1.2) +PATH + remote: chef-utils + specs: + chef-utils (15.4.69) + GEM remote: https://rubygems.org/ specs: @@ -158,6 +166,8 @@ GEM multipart-post (>= 1.2, < 3) faraday_middleware (0.12.2) faraday (>= 0.7.4, < 1.0) + fauxhai-ng (7.5.1) + net-ssh ffi (1.11.1) ffi (1.11.1-x64-mingw32) ffi (1.11.1-x86-mingw32) @@ -294,7 +304,7 @@ GEM rspec_junit_formatter (0.2.3) builder (< 4) rspec-core (>= 2, < 4, != 2.12.0) - rubocop (0.72.0) + rubocop (0.75.1) jaro_winkler (~> 1.5.1) parallel (~> 1.10) parser (>= 2.6) @@ -417,10 +427,12 @@ DEPENDENCIES chef! chef-bin! chef-config! + chef-utils! chef-vault cheffish (~> 14) chefstyle! ed25519 + fauxhai-ng inspec-core (~> 4.3) inspec-core-bin (~> 4.3) ohai! diff --git a/Rakefile b/Rakefile index 063abe1a85..818ac251bb 100644 --- a/Rakefile +++ b/Rakefile @@ -26,9 +26,11 @@ ENV["CHEF_LICENSE"] = "accept-no-persist" # hack the chef-config install to run before the traditional install task task :super_install do - chef_config_path = ::File.join(::File.dirname(__FILE__), "chef-config") - Dir.chdir(chef_config_path) - sh("rake install") + %w{chef-utils chef-config}.each do |gem| + path = ::File.join(::File.dirname(__FILE__), gem) + Dir.chdir(path) + sh("rake install") + end end task install: :super_install diff --git a/chef-config/Gemfile b/chef-config/Gemfile index 96ab544690..1652c89ad6 100644 --- a/chef-config/Gemfile +++ b/chef-config/Gemfile @@ -1,4 +1,6 @@ source "https://rubygems.org" +gem "chef-utils", path: File.expand_path("../../chef-utils", __FILE__) if File.exist?(File.expand_path("../../chef-utils", __FILE__)) + # Specify your gem's dependencies in chef-config.gemspec gemspec diff --git a/chef-config/chef-config.gemspec b/chef-config/chef-config.gemspec index b6bc5da1c9..2e978236ee 100644 --- a/chef-config/chef-config.gemspec +++ b/chef-config/chef-config.gemspec @@ -15,6 +15,7 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] + spec.add_dependency "chef-utils", "= #{ChefConfig::VERSION}" spec.add_dependency "mixlib-shellout", ">= 2.0", "< 4.0" spec.add_dependency "mixlib-config", ">= 2.2.12", "< 4.0" spec.add_dependency "fuzzyurl" diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb index 02acdf4ca2..d1c4001739 100644 --- a/chef-config/lib/chef-config/config.rb +++ b/chef-config/lib/chef-config/config.rb @@ -21,6 +21,7 @@ require "mixlib/config" unless defined?(Mixlib::Config) require "pathname" unless defined?(Pathname) +require "chef-utils" unless defined?(ChefUtils::CANARY) require_relative "fips" require_relative "logger" @@ -60,7 +61,7 @@ module ChefConfig # @return [String] a platform specific path def self.platform_specific_path(path) path = PathHelper.cleanpath(path) - if ChefConfig.windows? + if ChefUtils.windows? # turns \etc\chef\client.rb and \var\chef\client.rb into C:/chef/client.rb # Some installations will be on different drives so use the drive that # the expanded path to __FILE__ is found. @@ -78,7 +79,7 @@ module ChefConfig # # @return [String] the drive letter def self.windows_installation_drive - if ChefConfig.windows? + if ChefUtils.windows? drive = File.expand_path(__FILE__).split("/", 2)[0] drive = ENV["SYSTEMDRIVE"] if drive.to_s == "" drive @@ -573,7 +574,7 @@ module ChefConfig # Path to the default CA bundle files. default :ssl_ca_path, nil default(:ssl_ca_file) do - if ChefConfig.windows? && embedded_dir + if ChefUtils.windows? && embedded_dir cacert_path = File.join(embedded_dir, "ssl/certs/cacert.pem") cacert_path if File.exist?(cacert_path) else @@ -841,7 +842,7 @@ module ChefConfig # Those lists of regular expressions define what chef considers a # valid user and group name - if ChefConfig.windows? + if ChefUtils.windows? set_defaults_for_windows else set_defaults_for_nix @@ -1138,7 +1139,7 @@ module ChefConfig end end rescue - if ChefConfig.windows? + if ChefUtils.windows? ChefConfig.logger.trace "Defaulting to locale en_US.UTF-8 on Windows, until it matters that we do something else." else ChefConfig.logger.trace "No usable locale -a command found, assuming you have en_US.UTF-8 installed." diff --git a/chef-config/lib/chef-config/exceptions.rb b/chef-config/lib/chef-config/exceptions.rb index 86d34374ab..2bd2fb415d 100644 --- a/chef-config/lib/chef-config/exceptions.rb +++ b/chef-config/lib/chef-config/exceptions.rb @@ -1,5 +1,5 @@ # -# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# Copyright:: Copyright 2015-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/chef-config/lib/chef-config/fips.rb b/chef-config/lib/chef-config/fips.rb index 4c365301d5..06d039eb9e 100644 --- a/chef-config/lib/chef-config/fips.rb +++ b/chef-config/lib/chef-config/fips.rb @@ -1,6 +1,6 @@ # # Author:: Matt Wrock () -# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# Copyright:: Copyright (c) 2016-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,10 +16,12 @@ # limitations under the License. # +require "chef-utils" unless defined?(ChefUtils::CANARY) + module ChefConfig def self.fips? - if ChefConfig.windows? + if ChefUtils.windows? begin require "win32/registry" unless defined?(Win32::Registry) rescue LoadError diff --git a/chef-config/lib/chef-config/path_helper.rb b/chef-config/lib/chef-config/path_helper.rb index 6c60b82b89..9ffdd0be56 100644 --- a/chef-config/lib/chef-config/path_helper.rb +++ b/chef-config/lib/chef-config/path_helper.rb @@ -1,6 +1,6 @@ # # Author:: Bryan McLellan -# Copyright:: Copyright 2014-2018, Chef Software, Inc. +# Copyright:: Copyright 2014-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,7 @@ # limitations under the License. # +require "chef-utils" unless defined?(ChefUtils::CANARY) require_relative "windows" require_relative "logger" require_relative "exceptions" @@ -26,7 +27,7 @@ module ChefConfig WIN_MAX_PATH = 259 def self.dirname(path) - if ChefConfig.windows? + if ChefUtils.windows? # Find the first slash, not counting trailing slashes end_slash = path.size loop do @@ -47,7 +48,7 @@ module ChefConfig BACKSLASH = '\\'.freeze def self.path_separator - if ChefConfig.windows? + if ChefUtils.windows? File::ALT_SEPARATOR || BACKSLASH else File::SEPARATOR @@ -71,7 +72,7 @@ module ChefConfig end def self.validate_path(path) - if ChefConfig.windows? + if ChefUtils.windows? unless printable?(path) msg = "Path '#{path}' contains non-printable characters. Check that backslashes are escaped with another backslash (e.g. C:\\\\Windows) in double-quoted strings." ChefConfig.logger.error(msg) @@ -114,7 +115,7 @@ module ChefConfig # First remove extra separators and resolve any relative paths abs_path = File.absolute_path(path) - if ChefConfig.windows? + if ChefUtils.windows? # Add the \\?\ API prefix on Windows unless add_prefix is false # Downcase on Windows where paths are still case-insensitive abs_path.gsub!(::File::SEPARATOR, path_separator) @@ -142,7 +143,7 @@ module ChefConfig def self.cleanpath(path) path = Pathname.new(path).cleanpath.to_s # ensure all forward slashes are backslashes - if ChefConfig.windows? + if ChefUtils.windows? path = path.gsub(File::SEPARATOR, path_separator) end path @@ -219,7 +220,7 @@ module ChefConfig paths = [] paths << ENV[@@per_tool_home_environment] if defined?(@@per_tool_home_environment) && @@per_tool_home_environment && ENV[@@per_tool_home_environment] paths << ENV["CHEF_HOME"] if ENV["CHEF_HOME"] - if ChefConfig.windows? + if ChefUtils.windows? # By default, Ruby uses the the following environment variables to determine Dir.home: # HOME # HOMEDRIVE HOMEPATH diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb index d345e107b5..3225d4f3cf 100644 --- a/chef-config/lib/chef-config/version.rb +++ b/chef-config/lib/chef-config/version.rb @@ -1,4 +1,4 @@ -# Copyright:: Copyright 2010-2016, Chef Software, Inc. +# Copyright:: Copyright 2010-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -13,22 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# NOTE: This file is generated by running `rake version` in the top level of -# this repo. Do not edit this manually. Edit the VERSION file and run the rake -# task instead. -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - module ChefConfig CHEFCONFIG_ROOT = File.expand_path("../..", __FILE__) VERSION = "15.4.69".freeze end - -# -# NOTE: the Chef::Version class is defined in version_class.rb -# -# NOTE: DO NOT Use the Chef::Version class on ChefConfig::VERSIONs. The -# Chef::Version class is for _cookbooks_ only, and cannot handle -# pre-release versions like "10.14.0.rc.2". Please use Rubygem's -# Gem::Version class instead. -# diff --git a/chef-config/lib/chef-config/windows.rb b/chef-config/lib/chef-config/windows.rb index 9c606110a4..ae39246f55 100644 --- a/chef-config/lib/chef-config/windows.rb +++ b/chef-config/lib/chef-config/windows.rb @@ -1,5 +1,5 @@ # -# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# Copyright:: Copyright 2015-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,14 +15,10 @@ # limitations under the License. # -module ChefConfig +require "chef-utils" unless defined?(ChefUtils::CANARY) +module ChefConfig def self.windows? - if RUBY_PLATFORM =~ /mswin|mingw|windows/ - true - else - false - end + ChefUtils.windows? end - end diff --git a/chef-config/lib/chef-config/workstation_config_loader.rb b/chef-config/lib/chef-config/workstation_config_loader.rb index d38cae3d88..c5eb8b5678 100644 --- a/chef-config/lib/chef-config/workstation_config_loader.rb +++ b/chef-config/lib/chef-config/workstation_config_loader.rb @@ -1,6 +1,6 @@ # # Author:: Daniel DeLeo () -# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# Copyright:: Copyright 2014-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,6 +16,7 @@ # limitations under the License. # +require "chef-utils" unless defined?(ChefUtils::CANARY) require_relative "config" require_relative "exceptions" require_relative "logger" @@ -139,7 +140,7 @@ module ChefConfig end def working_directory - a = if ChefConfig.windows? + a = if ChefUtils.windows? env["CD"] else env["PWD"] diff --git a/chef-config/spec/spec_helper.rb b/chef-config/spec/spec_helper.rb index 6a324474e1..557f1f6432 100644 --- a/chef-config/spec/spec_helper.rb +++ b/chef-config/spec/spec_helper.rb @@ -1,4 +1,4 @@ -require "chef-config/windows" +require "chef-utils" # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config| @@ -32,8 +32,8 @@ RSpec.configure do |config| config.filter_run :focus config.run_all_when_everything_filtered = true - config.filter_run_excluding windows_only: true unless ChefConfig.windows? - config.filter_run_excluding unix_only: true if ChefConfig.windows? + config.filter_run_excluding windows_only: true unless ChefUtils.windows? + config.filter_run_excluding unix_only: true if ChefUtils.windows? # Limits the available syntax to the non-monkey patched syntax that is # recommended. For more details, see: diff --git a/chef-config/spec/unit/config_spec.rb b/chef-config/spec/unit/config_spec.rb index dec5b8755f..674246dfd1 100644 --- a/chef-config/spec/unit/config_spec.rb +++ b/chef-config/spec/unit/config_spec.rb @@ -201,7 +201,7 @@ RSpec.describe ChefConfig::Config do end before :each do - allow(ChefConfig).to receive(:windows?).and_return(is_windows) + allow(ChefUtils).to receive(:windows?).and_return(is_windows) end describe "class method: windows_installation_drive" do before do diff --git a/chef-config/spec/unit/fips_spec.rb b/chef-config/spec/unit/fips_spec.rb index d53096cead..d618117b57 100644 --- a/chef-config/spec/unit/fips_spec.rb +++ b/chef-config/spec/unit/fips_spec.rb @@ -1,6 +1,6 @@ # # Author:: Matt Wrock () -# Copyright:: Copyright (c) 2016-2017, Chef Software Inc. +# Copyright:: Copyright (c) 2016-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,7 +32,7 @@ RSpec.describe "ChefConfig.fips?" do let(:fips_path) { "/proc/sys/crypto/fips_enabled" } before(:each) do - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) allow(::File).to receive(:exist?).with(fips_path).and_return(true) allow(::File).to receive(:read).with(fips_path).and_return(enabled) end @@ -69,7 +69,7 @@ RSpec.describe "ChefConfig.fips?" do let(:win_reg_entry) { { "Enabled" => enabled } } before(:each) do - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) allow(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open).with(fips_key, arch).and_yield(win_reg_entry) end diff --git a/chef-config/spec/unit/path_helper_spec.rb b/chef-config/spec/unit/path_helper_spec.rb index 399b3dc965..1a0c2660e0 100644 --- a/chef-config/spec/unit/path_helper_spec.rb +++ b/chef-config/spec/unit/path_helper_spec.rb @@ -1,6 +1,6 @@ # # Author:: Bryan McLellan -# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# Copyright:: Copyright 2014-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -58,7 +58,7 @@ RSpec.describe ChefConfig::PathHelper do context "on windows" do before(:each) do - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) end include_examples("common_functionality") @@ -106,7 +106,7 @@ RSpec.describe ChefConfig::PathHelper do context "on unix" do before(:each) do - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) end include_examples("common_functionality") @@ -144,7 +144,7 @@ RSpec.describe ChefConfig::PathHelper do context "on windows" do before(:each) do # pass by default - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) allow(path_helper).to receive(:printable?).and_return(true) allow(path_helper).to receive(:windows_max_length_exceeded?).and_return(false) end @@ -254,7 +254,7 @@ RSpec.describe ChefConfig::PathHelper do context "when given more than one argument" do it "joins, cleanpaths, and escapes characters reserved by glob" do args = ["this/*path", "[needs]", "escaping?"] - escaped_path = if ChefConfig.windows? + escaped_path = if ChefUtils.windows? "this\\\\\\*path\\\\\\[needs\\]\\\\escaping\\?" else "this/\\*path/\\[needs\\]/escaping\\?" @@ -286,7 +286,7 @@ RSpec.describe ChefConfig::PathHelper do describe "all_homes" do before do stub_const("ENV", env) - allow(ChefConfig).to receive(:windows?).and_return(is_windows) + allow(ChefUtils).to receive(:windows?).and_return(is_windows) end context "on windows" do diff --git a/chef-config/spec/unit/workstation_config_loader_spec.rb b/chef-config/spec/unit/workstation_config_loader_spec.rb index e1cab3d4d0..704c3ac2dc 100644 --- a/chef-config/spec/unit/workstation_config_loader_spec.rb +++ b/chef-config/spec/unit/workstation_config_loader_spec.rb @@ -20,7 +20,7 @@ require "spec_helper" require "tempfile" require "chef-config/exceptions" -require "chef-config/windows" +require "chef-utils" require "chef-config/workstation_config_loader" RSpec.describe ChefConfig::WorkstationConfigLoader do @@ -98,7 +98,7 @@ RSpec.describe ChefConfig::WorkstationConfigLoader do let(:env_pwd) { "/path/to/cwd" } before do - if ChefConfig.windows? + if ChefUtils.windows? env["CD"] = env_pwd else env["PWD"] = env_pwd @@ -431,7 +431,7 @@ RSpec.describe ChefConfig::WorkstationConfigLoader do end describe "when loading a credentials file" do - if ChefConfig.windows? + if ChefUtils.windows? let(:home) { "C:/Users/example.user" } else let(:home) { "/Users/example.user" } diff --git a/chef-utils/.rspec b/chef-utils/.rspec new file mode 100644 index 0000000000..da740c0724 --- /dev/null +++ b/chef-utils/.rspec @@ -0,0 +1,2 @@ +--color +-fp diff --git a/chef-utils/Gemfile b/chef-utils/Gemfile new file mode 100644 index 0000000000..65cb76c2b5 --- /dev/null +++ b/chef-utils/Gemfile @@ -0,0 +1,9 @@ +source "https://rubygems.org" + +gemspec + +group(:development, :test) do + gem "fauxhai-ng" + gem "rake" + gem "rspec" +end diff --git a/chef-utils/LICENSE b/chef-utils/LICENSE new file mode 100644 index 0000000000..11069edd79 --- /dev/null +++ b/chef-utils/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +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. diff --git a/chef-utils/README.md b/chef-utils/README.md new file mode 100644 index 0000000000..79d0a1ac57 --- /dev/null +++ b/chef-utils/README.md @@ -0,0 +1,209 @@ +# Chef Utils gem + +**Umbrella Project**: [Chef Infra](https://github.com/chef/chef-oss-practices/blob/master/projects/chef-infra.md) + +**Project State**: [Active](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md#active) + +**Issues [Response Time Maximum](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md)**: 14 days + +**Pull Request [Response Time Maximum](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md)**: 14 days + +## Getting Started + +Chef Utils gem is common code and mixins for the core Chef Infra ruby gems. This should be are "core library" or "foundations" library +for the chef ecosystem (and external related gems) which allows the use of core code and utility functions of the chef gem without requiring +all the heaviness of the chef gem. + +### Platform Helpers + +Individual platforms for when code MUST be different on a case-by-case basis. It is generally encouraged to not use these and to use +the `platform_family` helpers unless it is known that code must be special cased for individual platforms. + +* `aix_platform?` +* `amazon_platform?` +* `arch_platform?` +* `centos_platform?` +* `clearos_platform?` +* `debian_platform?` +* `dragonfly_platform?` +* `fedora_platform?` +* `freebsd_platform?` +* `gentoo_platform?` +* `leap_platform?` +* `linuxmint_platform?` +* `macos_platform?` +* `netbsd_platform?` +* `nexentacore_platform?` +* `omnios_platform?` +* `openbsd_platform?` +* `openindiana_platform?` +* `opensolaris_platform?` +* `opensuse_platform?` +* `oracle_platform?` +* `raspbian_platform?` +* `redhat_platform?` +* `scientific_platform?` +* `slackware_platform?` +* `smartos_platform?` +* `solaris2_platform?` +* `suse_platform?` +* `ubuntu_platform?` +* `windows_platform?` + +For campatibility with old chef-sugar code the following aliases work for backwards compatibility, but will be DEPRECATED in the future. + +* `centos?` +* `clearos?` +* `linuxmint?` +* `nexentacore?` +* `omnios?` +* `openindiana?` +* `opensolaris?` +* `opensuse?` +* `oracle?` +* `raspbian?` +* `redhat?` +* `scientific?` +* `ubuntu?` + +### Platform Family Helpers + +These should be the most commonly used helpers to identify the type of node which group somewhat similar or nearly identical types of platforms. +There are helpers here which are also meta-families which group together multiple types into supertypes. + +* `aix?` +* `amazon?` +* `arch?` +* `debian?` - includes debian, ubuntu, linuxmint, raspbian, etc +* `dragonflybsd?` +* `fedora?` +* `freebsd?` +* `gentoo?` +* `macos?` +* `netbsd?` +* `openbsd?` +* `rhel?` - includes redhat, cnetos, scientific, oracle +* `smartos?` +* `solaris2?` +* `suse?` +* `windows?` +* `windows_ruby_platform?` - this is always true if the ruby VM is running on a windows host and is not stubbed by chefspec + +Super Families: + +* `fedora_based?` - anything of fedora lineage (fedora, fedhat, centos, amazon, pidora, etc) +* `rpm_based?`- all `fedora_based` systems plus `suse` and any future linux distros based on RPM (excluding AIX) +* `solaris_based?`- all solaris-derived systems (opensolaris, nexentacore, omnios, smartos, etc) +* `bsd_based?`- all bsd-derived systems (freebsd, netbsd, openbsd, dragonflybsd). + +### OS Helpers + +OS helpers are only provided for OS types that contain multiple platform families ("linux"), or for unique OS values ("darwin"). Users should +use the Platform Family helper level instead. + +* linux? +* darwin? + +### Architecture Helpers + +* `_64_bit?` +* `_32_bit?` +* `i386?` +* `intel?` +* `sparc?` +* `ppc64?` +* `ppc64le?` +* `powerpc?` +* `armhf?` +* `s390x?` +* `s390?` + +### Train Helpers + +**EXPERIMENTAL**: APIs may have breaking changes any time without warning + +* `file_exist?` +* `file_open` + +### Introspection Helpers + +* `docker?` - if the node is running inside of docker +* `systemd?` - if the init system is systemd +* `kitchen?` - if ENV['TEST_KITCHEN'] is set +* `ci?` - if ENV['CI'] is set + +### Service Helpers + +* `debianrcd?` - if the `update-rc.d` binary is present +* `invokercd?` - if the `invoke-rc.d` binary is present +* `upstart?` - if the `initctl` binary is present +* `insserv?` - if the `insserv` binary is present +* `redhatrcd?` - if the `chkconfig` binary is present + +* `service_script_exist?(type, service)` + +### Which/Where Helpers + +* `which` +* `where` + +### Path Sanity Helpers + +* `sanitized_path` + +## Documentation for Software Developers + +The design of the DSL helper libraries in this gem are designed around the Chef Infra Client use cases. Most of the helpers are +accessible through the Chef DSL directly via the `ChefUtils::DSL` module. They are also available via class method calls on +the ChefUtils module directly (e.g. `ChefUtils.debian?`). For that to be possible there is Chef Infra Client specific wiring in +the `ChefUtils::Internal` class allowing the helpers to access the `Chef.run_context` global values. This allows them to be +used from library helpers in cookbooks inside Chef Infra Client. + +For external use in other gems, this automatic wiring will not work correctly, and so it will not generally be possible to +call helpers off of the `ChefUtils` class (somee exceptions that do not require a node-like object or a train connection will +may still work). For use in other gems you should create your own module and mixin the helper class. If you have a node +method in your class/module then that method will be used. + +You can wire up a module which implements the Chef DSL with your own wiring using this template: + +```ruby +module MyDSL + include ChefUtils::DSL # or any individual module with DSL methods in it + + private + + def __getnode + # return something Mash-like with node semantics with a node["platform"], etc. + end + + def __transport_connection + # return a Train::Transport connection + end + + extend self # if your wiring is to global state to make `MyDSL.helper?` work. +end +``` + +Those methods are marked API private for the purposes of end-users, but are public APIs for the purposes of software development. + +## Getting Involved + +We'd love to have your help developing Chef Infra. See our [Contributing Document](./CONTRIBUTING.md) for more information on getting started. + +## License and Copyright + +Copyright 2008-2019, Chef Software, Inc. + +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/chef-utils/Rakefile b/chef-utils/Rakefile new file mode 100644 index 0000000000..df2f59e298 --- /dev/null +++ b/chef-utils/Rakefile @@ -0,0 +1,13 @@ +require "bundler/gem_tasks" + +task default: :spec + +begin + require "rspec/core/rake_task" + desc "Run standard specs" + RSpec::Core::RakeTask.new(:spec) do |t| + t.pattern = FileList["spec/**/*_spec.rb"] + end +rescue LoadError + STDERR.puts "\n*** RSpec not available. (sudo) gem install rspec to run unit tests. ***\n\n" +end diff --git a/chef-utils/chef-utils.gemspec b/chef-utils/chef-utils.gemspec new file mode 100644 index 0000000000..dbe0ef751e --- /dev/null +++ b/chef-utils/chef-utils.gemspec @@ -0,0 +1,47 @@ +# coding: utf-8 +lib = File.expand_path("../lib", __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require "chef-utils/version" + +Gem::Specification.new do |spec| + spec.name = "chef-utils" + spec.version = ChefUtils::VERSION + spec.authors = ["Chef Software, Inc"] + spec.email = ["oss@chef.io"] + + spec.summary = %q{Basic utility functions for Core Chef development} + spec.homepage = "https://github.com/chef/chef/tree/master/chef-utils" + spec.license = "Apache-2.0" + + spec.metadata = { + "bug_tracker_uri" => "https://github.com/chef/chef/issues", + "changelog_uri" => "https://github.com/chef/chef/CHANGELOG.md", + "documentation_uri" => "https://github.com/chef/chef/tree/master/chef-utils/README.md", + "homepage_uri" => "https://github.com/chef/chef/tree/master/chef-utils", + "source_code_uri" => "https://github.com/chef/chef/tree/master/chef-utils", + } + + spec.require_paths = ["lib"] + + # + # NOTE: DO NOT ADD RUNTIME DEPS TO OTHER CHEF ECOSYSTEM GEMS + # (e.g. chef, ohai, mixlib-anything, ffi-yajl, and IN PARTICULAR NOT chef-config) + # + # This is so that this set of common code can be reused in any other library without + # creating circular dependencies. If you find yourself wanting to do that you probably + # have a helper that should go into the library you want to declare a dependency on, + # or you need to create another gem that is not this one. You may also want to rub some + # dependency injection on your API to invert things so that you don't have to take + # a dependency on the thing you need (i.e. allow injecting a hash-like thing instead of taking + # a dep on mixlib-config and then require the consumer to wire up chef-config to your + # API). Same for mixlib-log and Chef::Log in general. + # + # ABSOLUTELY NO EXCEPTIONS + # + + spec.files = %w{Rakefile LICENSE} + Dir.glob("*.gemspec") + + Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) } + + spec.bindir = "bin" + spec.executables = [] +end diff --git a/chef-utils/lib/chef-utils.rb b/chef-utils/lib/chef-utils.rb new file mode 100644 index 0000000000..fe25ea5ff5 --- /dev/null +++ b/chef-utils/lib/chef-utils.rb @@ -0,0 +1,43 @@ +# +# Copyright:: Copyright 2015-2019, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "chef-utils/dsl/architecture" +require_relative "chef-utils/dsl/introspection" +require_relative "chef-utils/dsl/os" +require_relative "chef-utils/dsl/path_sanity" +require_relative "chef-utils/dsl/platform" +require_relative "chef-utils/dsl/platform_family" +require_relative "chef-utils/dsl/service" +require_relative "chef-utils/dsl/train_helpers" +require_relative "chef-utils/dsl/which" +require_relative "chef-utils/mash" + +# This is the Chef Infra Client DSL, not everytihng needs to go in here +module ChefUtils + include ChefUtils::DSL::Architecture + include ChefUtils::DSL::OS + include ChefUtils::DSL::PlatformFamily + include ChefUtils::DSL::Platform + include ChefUtils::DSL::Introspection + # FIXME: include ChefUtils::DSL::Which in Chef 16.0 + # FIXME: include ChefUtils::DSL::PathSanity in Chef 16.0 + # FIXME: include ChefUtils::DSL::TrainHelpers in Chef 16.0 + # ChefUtils::DSL::Service is deliberately excluded + + CANARY = 1 # used as a guard for requires + extend self +end diff --git a/chef-utils/lib/chef-utils/dsl/architecture.rb b/chef-utils/lib/chef-utils/dsl/architecture.rb new file mode 100644 index 0000000000..b3e9235b16 --- /dev/null +++ b/chef-utils/lib/chef-utils/dsl/architecture.rb @@ -0,0 +1,117 @@ +# +# Copyright:: Copyright 2018-2019, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../internal" + +module ChefUtils + module DSL + module Architecture + include Internal + + # Determine if the current architecture is 64-bit + # + # @return [Boolean] + # + def _64_bit?(node = __getnode) + %w{amd64 x86_64 ppc64 ppc64le s390x ia64 sparc64 aarch64 arch64 arm64 sun4v sun4u} + .include?(node["kernel"]["machine"]) + end + + # Determine if the current architecture is 32-bit + # + # @return [Boolean] + # + def _32_bit?(node = __getnode) + !_64_bit?(node) + end + + # Determine if the current architecture is i386 + # + # @return [Boolean] + # + def i386?(node = __getnode) + _32_bit?(node) && intel?(node) + end + + # Determine if the current architecture is Intel. + # + # @return [Boolean] + # + def intel?(node = __getnode) + %w{i86pc i386 x86_64 amd64 i686}.include?(node["kernel"]["machine"]) + end + + # Determine if the current architecture is SPARC. + # + # @return [Boolean] + # + def sparc?(node = __getnode) + %w{sun4u sun4v}.include?(node["kernel"]["machine"]) + end + + # Determine if the current architecture is Powerpc64 Big Endian + # + # @return [Boolean] + # + def ppc64?(node = __getnode) + %w{ppc64}.include?(node["kernel"]["machine"]) + end + + # Determine if the current architecture is Powerpc64 Little Endian + # + # @return [Boolean] + # + def ppc64le?(node = __getnode) + %w{ppc64le}.include?(node["kernel"]["machine"]) + end + + # Determine if the current architecture is PowerPC. + # + # @return [Boolean] + # + def powerpc?(node = __getnode) + %w{powerpc}.include?(node["kernel"]["machine"]) + end + + # Determine if the current architecture is 32-bit ARM + # + # @return [Boolean] + # + def armhf?(node = __getnode) + %w{armhf}.include?(node["kernel"]["machine"]) + end + + # Determine if the current architecture is s390x + # + # @return [Boolean] + # + def s390x?(node = __getnode) + %w{s390x}.include?(node["kernel"]["machine"]) + end + + # Determine if the current architecture is s390 + # + # @return [Boolean] + # + def s390?(node = __getnode) + %w{s390}.include?(node["kernel"]["machine"]) + end + + extend self + end + end +end diff --git a/chef-utils/lib/chef-utils/dsl/introspection.rb b/chef-utils/lib/chef-utils/dsl/introspection.rb new file mode 100644 index 0000000000..f4025d5773 --- /dev/null +++ b/chef-utils/lib/chef-utils/dsl/introspection.rb @@ -0,0 +1,93 @@ +# +# Copyright:: Copyright 2018-2019, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "train_helpers" + +module ChefUtils + module DSL + # This is for "introspection" helpers in the sense that we are inspecting the + # actual server or image under management to determine running state (duck-typing the system). + # The helpers here may use the node object state from ohai, but typically not the big 5: platform, + # platform_family, platform_version, arch, os. The helpers here should infer somewhat + # higher level facts about the system. + # + module Introspection + include TrainHelpers + + # Returns whether the node is a docker container. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def docker?(node = __getnode) + # Using "File.exist?('/.dockerinit') || File.exist?('/.dockerenv')" makes Travis sad, + # and that makes us sad too. + !!(node && node.read("virtualization", "systems", "docker") == "guest") + end + + # @param [Chef::Node] node + # + # @return [Boolean] + # + def systemd?(node = __getnode) + file_exist?("/proc/1/comm") && file_open("/proc/1/comm").gets.chomp == "systemd" + end + + # @param [Chef::Node] node + # + # @return [Boolean] + # + def kitchen?(node = __getnode) + ENV.key?("TEST_KITCHEN") + end + + # @param [Chef::Node] node + # + # @return [Boolean] + # + def ci?(node = __getnode) + ENV.key?("CI") + end + + # @param [String] svc_name + # + # @return [Boolean] + # + def has_systemd_service_unit?(svc_name) + %w{ /etc /usr/lib /lib /run }.any? do |load_path| + file_exist?( + "#{load_path}/systemd/system/#{svc_name.gsub(/@.*$/, "@")}.service" + ) + end + end + + # @param [String] svc_name + # + # @return [Boolean] + # + def has_systemd_unit?(svc_name) + # TODO: stop supporting non-service units with service resource + %w{ /etc /usr/lib /lib /run }.any? do |load_path| + file_exist?("#{load_path}/systemd/system/#{svc_name}") + end + end + + extend self + end + end +end diff --git a/chef-utils/lib/chef-utils/dsl/os.rb b/chef-utils/lib/chef-utils/dsl/os.rb new file mode 100644 index 0000000000..6d1d749957 --- /dev/null +++ b/chef-utils/lib/chef-utils/dsl/os.rb @@ -0,0 +1,55 @@ +# +# Copyright:: Copyright 2018-2019, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../internal" + +module ChefUtils + module DSL + module OS + include Internal + + # + # NOTE CAREFULLY: Most node['os'] values should not appear in this file at all. + # + # For cases where node['os'] == node['platform_family'] == node['platform'] then + # only the platform helper should be added. + # + + # Determine if the current node is linux. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def linux?(node = __getnode) + node["os"] == "linux" + end + + # Determine if the current node is darwin. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def darwin?(node = __getnode) + node["os"] == "darwin" + end + + extend self + end + end +end diff --git a/chef-utils/lib/chef-utils/dsl/path_sanity.rb b/chef-utils/lib/chef-utils/dsl/path_sanity.rb new file mode 100644 index 0000000000..ec8d84922e --- /dev/null +++ b/chef-utils/lib/chef-utils/dsl/path_sanity.rb @@ -0,0 +1,58 @@ +# +# Copyright:: Copyright 2018-2019, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../internal" +require_relative "platform_family" + +module ChefUtils + module DSL + module PathSanity + include Internal + + def sanitized_path(env = nil) + env_path = env ? env["PATH"] : __env_path + env_path = "" if env_path.nil? + path_separator = ChefUtils.windows? ? ";" : ":" + # ensure the Ruby and Gem bindirs are included for omnibus chef installs + new_paths = env_path.split(path_separator) + [ ChefUtils::DSL::PathSanity.ruby_bindir, ChefUtils::DSL::PathSanity.gem_bindir ].compact.each do |path| + new_paths = [ path ] + new_paths unless new_paths.include?(path) + end + ChefUtils::DSL::PathSanity.sane_paths.each do |path| + new_paths << path unless new_paths.include?(path) + end + new_paths.join(path_separator).encode("utf-8", invalid: :replace, undef: :replace) + end + + class << self + def sane_paths + ChefUtils.windows? ? %w{} : %w{/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin} + end + + def ruby_bindir + RbConfig::CONFIG["bindir"] + end + + def gem_bindir + Gem.bindir + end + end + + extend self + end + end +end diff --git a/chef-utils/lib/chef-utils/dsl/platform.rb b/chef-utils/lib/chef-utils/dsl/platform.rb new file mode 100644 index 0000000000..29f6b1563c --- /dev/null +++ b/chef-utils/lib/chef-utils/dsl/platform.rb @@ -0,0 +1,339 @@ +# +# Copyright:: Copyright 2018-2019, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../internal" + +module ChefUtils + module DSL + module Platform + include Internal + + # NOTE: if you are adding new platform helpers they should all have the `_platform?` suffix. + # DO NOT add new short aliases without the suffix (they will be deprecated in the future) + # aliases here are mostly for backwards compatibility with chef-sugar and new ones are DISCOURAGED. + # generally there should be one obviously correct way to do things. + + # Determine if the current node is linux mint. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def linuxmint?(node = __getnode) + node["platform"] == "linuxmint" + end + # chef-sugar backcompat methods + alias_method :mint?, :linuxmint? + alias_method :linux_mint?, :linuxmint? + alias_method :linuxmint_platform?, :linuxmint? + + # Determine if the current node is ubuntu. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def ubuntu?(node = __getnode) + node["platform"] == "ubuntu" + end + alias_method :ubuntu_platform?, :ubuntu? + + # Determine if the current node is raspbian. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def raspbian?(node = __getnode) + node["platform"] == "raspbian" + end + alias_method :raspbian_platform?, :raspbian? + + # Determine if the current node is debian. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def debian_platform?(node = __getnode) + node["platform"] == "debian" + end + + # Determine if the current node is amazon linux. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def amazon_platform?(node = __getnode) + node["platform"] == "amazon" + end + + # Determine if the current node is redhat enterprise. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def redhat?(node = __getnode) + node["platform"] == "redhat" + end + # chef-sugar backcompat methods + alias_method :redhat_enterprise?, :redhat? + alias_method :redhat_enterprise_linux?, :redhat? + alias_method :redhat_platform?, :redhat? + + # Determine if the current node is centos. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def centos?(node = __getnode) + node["platform"] == "centos" + end + alias_method :centos_platform?, :centos? + + # Determine if the current node is oracle linux. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def oracle?(node = __getnode) + node["platform"] == "oracle" + end + # chef-sugar backcompat methods + alias_method :oracle_linux?, :oracle? + alias_method :oracle_platform?, :oracle? + + # Determine if the current node is scientific linux. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def scientific?(node = __getnode) + node["platform"] == "scientific" + end + # chef-sugar backcompat methods + alias_method :scientific_linux?, :scientific? + alias_method :scientific_platform?, :scientific? + + # Determine if the current node is clearos. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def clearos?(node = __getnode) + node["platform"] == "clearos" + end + alias_method :clearos_platform?, :clearos? + + # Determine if the current node is fedora. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def fedora_platform?(node = __getnode) + node["platform"] == "fedora" + end + + # Determine if the current node is arch + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def arch_platform?(node = __getnode) + node["platform"] == "arch" + end + + # Determine if the current node is solaris2 + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def solaris2_platform?(node = __getnode) + node["platform"] == "solaris2" + end + + # Determine if the current node is smartos + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def smartos_platform?(node = __getnode) + node["platform"] == "smartos" + end + + # Determine if the current node is omnios + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def omnios?(node = __getnode) + node["platform"] == "omnios" + end + alias_method :omnios_platform?, :omnios? + + # Determine if the current node is openindiana + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def openindiana?(node = __getnode) + node["platform"] == "openindiana" + end + alias_method :openindiana_platform?, :openindiana? + + # Determine if the current node is nexentacore + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def nexentacore?(node = __getnode) + node["platform"] == "nexentacore" + end + alias_method :nexentacore_platform?, :nexentacore? + + # Determine if the current node is aix + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def aix_platform?(node = __getnode) + node["platform"] == "aix" + end + + # Determine if the current node is freebsd + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def freebsd_platform?(node = __getnode) + node["platform"] == "freebsd" + end + + # Determine if the current node is openbsd + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def openbsd_platform?(node = __getnode) + node["platform"] == "openbsd" + end + + # Determine if the current node is netbsd + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def netbsd_platform?(node = __getnode) + node["platform"] == "netbsd" + end + + # Determine if the current node is dragonflybsd + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def dragonfly_platform?(node = __getnode) + node["platform"] == "dragonfly" + end + + # Determine if the current node is MacOS. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def macos_platform?(node = __getnode) + node["platform"] == "mac_os_x" + end + alias_method :mac_os_x_platform?, :macos_platform? + + # Determine if the current node is gentoo + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def gentoo_platform?(node = __getnode) + node["platform"] == "gentoo" + end + + # Determine if the current node is slackware. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def slackware_platform?(node = __getnode) + node["platform"] == "slackware" + end + + # Determine if the current node is SuSE. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def suse_platform?(node = __getnode) + node["platform"] == "suse" + end + + # Determine if the current node is OpenSuSE. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def opensuse?(node = __getnode) + node["platform"] == "opensuse" || node["platform"] == "opensuseleap" + end + alias_method :opensuse_platform?, :opensuse? + alias_method :opensuseleap_platform?, :opensuse? + alias_method :leap_platform?, :opensuse? + # NOTE: to anyone adding :tumbleweed_platform? - :[opensuse]leap_platform? should be false on tumbleweed, :opensuse[_platform]? should be true + + # Determine if the current node is Windows. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def windows_platform?(node = __getnode) + node["platform"] == "windows" + end + + extend self + end + end +end diff --git a/chef-utils/lib/chef-utils/dsl/platform_family.rb b/chef-utils/lib/chef-utils/dsl/platform_family.rb new file mode 100644 index 0000000000..477d51c9a4 --- /dev/null +++ b/chef-utils/lib/chef-utils/dsl/platform_family.rb @@ -0,0 +1,282 @@ +# +# Copyright:: Copyright 2018-2019, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../internal" + +module ChefUtils + module DSL + module PlatformFamily + include Internal + + # Determine if the current node is arch linux. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def arch?(node = __getnode) + node["platform_family"] == "arch" + end + # chef-sugar backcompat methods + alias_method :arch_linux?, :arch? + + # Determine if the current node is aix + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def aix?(node = __getnode) + node["platform_family"] == "aix" + end + + # Determine if the current node is a member of the debian family. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def debian?(node = __getnode) + node["platform_family"] == "debian" + end + + # Determine if the current node is a member of the fedora family. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def fedora?(node = __getnode) + node["platform_family"] == "fedora" + end + + # Determine if the current node is a member of the OSX family. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def macos?(node = __getnode) + node["platform_family"] == "mac_os_x" + end + alias_method :osx?, :macos? + alias_method :mac?, :macos? + alias_method :mac_os_x?, :macos? + + # Determine if the current node is a member of the redhat family. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def rhel?(node = __getnode) + node["platform_family"] == "rhel" + end + alias_method :el?, :rhel? + + # Determine if the current node is a member of the amazon family. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def amazon?(node = __getnode) + node["platform_family"] == "amazon" + end + alias_method :amazon_linux?, :amazon? + + # Determine if the current node is solaris2 + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def solaris2?(node = __getnode) + node["platform_family"] == "solaris2" + end + # chef-sugar backcompat methods + alias_method :solaris?, :solaris2? + + # Determine if the current node is smartos + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def smartos?(node = __getnode) + node["platform_family"] == "smartos" + end + + # Determine if the current node is a member of the suse family. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def suse?(node = __getnode) + node["platform_family"] == "suse" + end + + # Determine if the current node is a member of the gentoo family. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def gentoo?(node = __getnode) + node["platform_family"] == "gentoo" + end + + # Determine if the current node is freebsd + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def freebsd?(node = __getnode) + node["platform_family"] == "freebsd" + end + + # Determine if the current node is openbsd + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def openbsd?(node = __getnode) + node["platform_family"] == "openbsd" + end + + # Determine if the current node is netbsd + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def netbsd?(node = __getnode) + node["platform_family"] == "netbsd" + end + + # Determine if the current node is dragonflybsd + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def dragonflybsd?(node = __getnode) + node["platform_family"] == "dragonflybsd" + end + + # Determine if the current node is a member of the windows family. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def windows?(node = __getnode(true)) + # This is all somewhat complicated. We prefer to get the node object so that chefspec can + # stub the node object. But we also have to deal with class-parsing time where there is + # no node object, so we have to fall back to RUBY_PLATFORM based detection. We cannot pull + # the node object out of the Chef.run_context.node global object here (which is what the + # false flag to __getnode is about) because some run-time code also cannot run under chefspec + # on non-windows where the node is stubbed to windows. + # + # As a result of this the `windows?` helper and the `ChefUtils.windows?` helper do not behave + # the same way in that the latter is not stubbable by chefspec. + # + node ? node["platform_family"] == "windows" : windows_ruby_platform? + end + + # Determine if the ruby VM is currently running on a windows node (chefspec can never stub + # this behavior, so this is useful for code which can never be parsed on a non-windows box). + # + # @return [Boolean] + # + def windows_ruby_platform? + !!(RUBY_PLATFORM =~ /mswin|mingw32|windows/) + end + + # + # Platform-Family-like Helpers + # + # These are meta-helpers which address the issue that platform_family is single valued and cannot + # be an array while a tree-like Taxonomy is what is called for in some cases. + # + + # If it uses RPM, it goes in here (rhel, fedora, amazon, suse platform_families). Deliberately does not + # include AIX because bff is AIX's primary package manager and adding it here would make this substantially + # less useful since in no way can AIX trace its lineage back to old redhat distros. This is most useful for + # "smells like redhat, including SuSE". + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def rpm_based?(node = __getnode) + fedora_derived?(node) || node["platform_family"] == "suse" + end + + # RPM-based distros which are not SuSE and are very loosely similar to fedora, using yum or dnf. The historical + # lineage of the distro should have forked off from old redhat fedora distros at some point. Currently rhel, + # fedora and amazon. This is most useful for "smells like redhat, but isn't SuSE". + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def fedora_derived?(node = __getnode) + redhat_based?(node) || node["platform_family"] == "amazon" + end + + # RedHat distros -- fedora and rhel platform_families, nothing else. This is most likely not as useful as the + # "fedora_dervied?" helper. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def redhat_based?(node = __getnode) + %w{rhel fedora}.include?(node["platform_family"]) + end + + # All of the Solaris-lineage. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def solaris_based?(node = __getnode) + %w{solaris2 smartos omnios openindiana opensolaris nexentacore}.include?(node["platform"]) + end + + # All of the BSD-lineage. + # + # Note that MacOSX is not included since Mac deviates so significantly from BSD that including it would not be useful. + # + # @param [Chef::Node] node + # + # @return [Boolean] + # + def bsd_based?(node = __getnode) + # we could use os, platform_family or platform here equally + %w{netbsd freebsd openbsd dragonflybsd}.include?(node["platform"]) + end + + extend self + end + end +end diff --git a/chef-utils/lib/chef-utils/dsl/service.rb b/chef-utils/lib/chef-utils/dsl/service.rb new file mode 100644 index 0000000000..da4ea6c8a1 --- /dev/null +++ b/chef-utils/lib/chef-utils/dsl/service.rb @@ -0,0 +1,91 @@ +# +# Copyright:: Copyright 2018-2019, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../internal" +require_relative "train_helpers" + +module ChefUtils + module DSL + # NOTE: these are mixed into the service resource+providers specifically and deliberately not + # injected into the global namespace + module Service + include Internal + include TrainHelpers + + # Returns if debian's old rc.d manager is installed (not necessarily the primary init system). + # + # @return [Boolean] + # + def debianrcd? + file_exist?("/usr/sbin/update-rc.d") + end + + # Returns if debian's old invoke rc.d manager is installed (not necessarily the primary init system). + # + # @return [Boolean] + # + def invokercd? + file_exist?("/usr/sbin/invoke-rc.d") + end + + # Returns if upstart is installed (not necessarily the primary init system). + # + # @return [Boolean] + # + def upstart? + file_exist?("/sbin/initctl") + end + + # Returns if insserv is installed (not necessarily the primary init system). + # + # @return [Boolean] + # + def insserv? + file_exist?("/sbin/insserv") + end + + # Returns if redhat's init system is installed (not necessarily the primary init system). + # + # @return [Boolean] + # + def redhatrcd? + file_exist?("/sbin/chkconfig") + end + + def service_script_exist?(type, script) + case type + when :initd + file_exist?("/etc/init.d/#{script}") + when :upstart + file_exist?("/etc/init/#{script}.conf") + when :xinetd + file_exist?("/etc/xinetd.d/#{script}") + when :etc_rcd + file_exist?("/etc/rc.d/#{script}") + when :systemd + file_exist?("/etc/init.d/#{script}") || + ChefUtils::DSL::Introspection.has_systemd_service_unit?(script) || + ChefUtils::DSL::Introspection.has_systemd_unit?(script) + else + raise ArgumentError, "type of service must be one of :initd, :upstart, :xinetd, :etc_rcd, or :systemd" + end + end + + extend self + end + end +end diff --git a/chef-utils/lib/chef-utils/dsl/train_helpers.rb b/chef-utils/lib/chef-utils/dsl/train_helpers.rb new file mode 100644 index 0000000000..a36db803f3 --- /dev/null +++ b/chef-utils/lib/chef-utils/dsl/train_helpers.rb @@ -0,0 +1,63 @@ +#-- +# Copyright:: Copyright 2019-2019, 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 "stringio" unless defined?(StringIO) +require_relative "../internal" + +module ChefUtils + module DSL + module TrainHelpers + include Internal + + # + # FIXME: generally these helpers all use the pattern of checking for target_mode? + # and then if it is we use train. That approach should likely be flipped so that + # even when we're running without target mode we still use inspec in its local + # mode. + # + + # Train wrapper around File.exist? to make it local mode aware. + # + # @param filename filename to check + # @return [Boolean] if it exists + # + def file_exist?(filename) + if __transport_connection + __transport_connection.file(filename).exist? + else + File.exist?(filename) + end + end + + # XXX: modifications to the StringIO won't get written back + # FIXME: this is very experimental and may be a bad idea and may break at any time + # @api private + # + def file_open(*args, &block) + if __transport_connection + content = __transport_connection.file(args[0]).content + string_io = StringIO.new content + yield string_io if block_given? + string_io + else + File.open(*args, &block) + end + end + + extend self + end + end +end diff --git a/chef-utils/lib/chef-utils/dsl/which.rb b/chef-utils/lib/chef-utils/dsl/which.rb new file mode 100644 index 0000000000..23bb21c9ee --- /dev/null +++ b/chef-utils/lib/chef-utils/dsl/which.rb @@ -0,0 +1,118 @@ +# +# Copyright:: Copyright 2018-2019, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require_relative "../internal" + +module ChefUtils + module DSL + module Which + include Internal + + # Lookup an executable through the systems search PATH. Allows specifying an array + # of executables to look for. The first executable that is found, along any path entry, + # will be the preferred one and returned first. The extra_path will override any default + # extra_paths which are added (allwing the user to pass an empty array to remove them). + # + # When passed a block the block will be called with the full pathname of any executables + # which are found, and the block should return truthy or falsey values to further filter + # the executable based on arbitrary criteria. + # + # This is syntactic sugar for `where(...).first` + # + # This helper can be used in target mode in chef or with train using the appropriate + # wiring extenerally. + # + # @example Find the most appropriate python executable, searching through the system PATH + # plus additionally the "/usr/libexec" directory, which has the dnf libraries + # installed and available. + # + # cmd = which("platform-python", "python", "python3", "python2", "python2.7", extra_path: "/usr/libexec") do |f| + # shell_out("#{f} -c 'import dnf'").exitstatus == 0 + # end + # + # @param [Array] list of commands to search for + # @param [String,Array] array of extra paths to search through + # @return [String] the first match + # + def which(*cmds, extra_path: nil, &block) + where(*cmds, extra_path: extra_path, &block).first || false + end + + # Lookup all the instances of an an executable that can be found through the systems search PATH. + # Allows specifying an array of executables to look for. All the instances of the first executable + # that is found will be returned first. The extra_path will override any default extra_paths + # which are added (allwing the user to pass an empty array to remove them). + # + # When passed a block the block will be called with the full pathname of any executables + # which are found, and the block should return truthy or falsey values to further filter + # the executable based on arbitrary criteria. + # + # This helper can be used in target mode in chef or with train using the appropriate + # wiring extenerally. + # + # @example Find all the python executables, searching through the system PATH plus additionally + # the "/usr/libexec" directory, which have the dnf libraries installed and available. + # + # cmds = where("platform-python", "python", "python3", "python2", "python2.7", extra_path: "/usr/libexec") do |f| + # shell_out("#{f} -c 'import dnf'").exitstatus == 0 + # end + # + # @param [Array] list of commands to search for + # @param [String,Array] array of extra paths to search through + # @return [String] the first match + # + def where(*cmds, extra_path: nil, &block) + extra_path ||= __extra_path + paths = __env_path.split(File::PATH_SEPARATOR) + Array(extra_path) + paths.uniq! + cmds.map do |cmd| + paths.map do |path| + filename = File.join(path, cmd) + filename if __valid_executable?(filename, &block) + end.compact + end.flatten + end + + private + + # This is for injecting common extra_paths into the search PATH. The chef-client codebase overrides this into its + # own custom mixin to ensure that /usr/sbin, /sbin, etc are in the search PATH for chef-client. + # + # @api private + def __extra_path + nil + end + + # Windows compatible and train/target-mode-enhanced helper to determine if an executable is valid. + # + # @api private + def __valid_executable?(filename, &block) + is_executable = + if __transport_connection + __transport_connection.file(filename).stat[:mode] & 1 && !__transport_connection.file(filename).directory? + else + File.executable?(filename) && !File.directory?(filename) + end + return false unless is_executable + + block ? yield(filename) : true + end + + extend self + end + end +end diff --git a/chef-utils/lib/chef-utils/internal.rb b/chef-utils/lib/chef-utils/internal.rb new file mode 100644 index 0000000000..657d3b6448 --- /dev/null +++ b/chef-utils/lib/chef-utils/internal.rb @@ -0,0 +1,77 @@ +# +# Copyright:: Copyright 2018-2019, 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. +# + +module ChefUtils + # + # This is glue code to make the helpers work when called as ChefUtils.helper? from inside of chef-client. + # + # This also is glue code to make the helpers work when mixed into classes that have node/run_context methods that + # provide those objects. + # + # It should not be assumed that any of this code runs from within chef-client and that the + # Chef class or run_context, etc exists. + # + # This gem may be used by gems like mixlib-shellout which can be consumed by external non-Chef utilities, + # so including brittle code here which depends on the existence of the chef-client will cause broken + # behavior downstream. You must practice defensive coding, and not make assumptions about runnign within chef-client. + # + # Other consumers may mix in the helper classes and then override the methods here and provide their own custom + # wiring and override what is provided here. They are marked as private because no downstream user should ever touch + # them -- they are intended to be subclassable and overridable by Chef developers in other projects. Chef Software + # reserves the right to change the implementation details of this class in minor revs which is what "api private" means, + # so external persons should subclass and override only when necessary (submit PRs and issues upstream if this is a problem). + # + module Internal + extend self + + private + + # FIXME: include a `__config` method so we can wire up Chef::Config automatically or allow other consumers to + # inject a config hash without having to take a direct dep on the chef-config gem + + # @api private + def __getnode(skip_global = false) + return node if respond_to?(:node) && node + + return run_context&.node if respond_to?(:run_context) && run_context&.node + + unless skip_global + return Chef.run_context&.node if defined?(Chef) && Chef.respond_to?(:run_context) && Chef.run_context&.node + end + + nil + end + + # @api private + def __env_path + if __transport_connection + __transport_connection.run_command("echo $PATH").stdout || "" + else + ENV["PATH"] || "" + end + end + + # @api private + def __transport_connection + return Chef.run_context.transport_connection if defined?(Chef) && Chef.respond_to?(:run_context) && Chef&.run_context&.transport_connection + + nil + end + + extend self + end +end diff --git a/chef-utils/lib/chef-utils/mash.rb b/chef-utils/lib/chef-utils/mash.rb new file mode 100644 index 0000000000..00a1444964 --- /dev/null +++ b/chef-utils/lib/chef-utils/mash.rb @@ -0,0 +1,239 @@ +# Copyright 2009-2016, Dan Kubb + +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: + +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# --- +# --- + +# Some portions of blank.rb and mash.rb are verbatim copies of software +# licensed under the MIT license. That license is included below: + +# Copyright 2005-2016, David Heinemeier Hansson + +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: + +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# This class has dubious semantics and we only have it so that people can write +# params[:key] instead of params['key']. +module ChefUtils + class Mash < Hash + + # @param constructor + # The default value for the mash. Defaults to an empty hash. + # + # @details [Alternatives] + # If constructor is a Hash, a new mash will be created based on the keys of + # the hash and no default value will be set. + def initialize(constructor = {}) + if constructor.is_a?(Hash) + super() + update(constructor) + else + super(constructor) + end + end + + # @param orig Mash being copied + # + # @return [Object] A new copied Mash + def initialize_copy(orig) + super + # Handle nested values + each do |k, v| + if v.is_a?(Mash) || v.is_a?(Array) + self[k] = v.dup + end + end + self + end + + # @param key The default value for the mash. Defaults to nil. + # + # @details [Alternatives] + # If key is a Symbol and it is a key in the mash, then the default value will + # be set to the value matching the key. + def default(key = nil) + if key.is_a?(Symbol) && include?(key = key.to_s) + self[key] + else + super + end + end + + unless method_defined?(:regular_writer) + alias_method :regular_writer, :[]= + end + + unless method_defined?(:regular_update) + alias_method :regular_update, :update + end + + # @param key The key to set. + # @param value + # The value to set the key to. + # + # @see Mash#convert_key + # @see Mash#convert_value + def []=(key, value) + regular_writer(convert_key(key), convert_value(value)) + end + + # internal API for use by Chef's deep merge cache + # @api private + def internal_set(key, value) + regular_writer(key, convert_value(value)) + end + + # @param other_hash + # A hash to update values in the mash with. The keys and the values will be + # converted to Mash format. + # + # @return [Mash] The updated mash. + def update(other_hash) + other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } + self + end + + alias_method :merge!, :update + + # @param key The key to check for. This will be run through convert_key. + # + # @return [Boolean] True if the key exists in the mash. + def key?(key) + super(convert_key(key)) + end + + # def include? def has_key? def member? + alias_method :include?, :key? + alias_method :has_key?, :key? + alias_method :member?, :key? + + # @param key The key to fetch. This will be run through convert_key. + # @param *extras Default value. + # + # @return [Object] The value at key or the default value. + def fetch(key, *extras) + super(convert_key(key), *extras) + end + + # @param *indices + # The keys to retrieve values for. These will be run through +convert_key+. + # + # @return [Array] The values at each of the provided keys + def values_at(*indices) + indices.collect { |key| self[convert_key(key)] } + end + + # @param hash The hash to merge with the mash. + # + # @return [Mash] A new mash with the hash values merged in. + def merge(hash) + dup.update(hash) + end + + # @param key + # The key to delete from the mash.\ + def delete(key) + super(convert_key(key)) + end + + # @param *rejected 1, :two => 2, :three => 3 }.except(:one) + # #=> { "two" => 2, "three" => 3 } + def except(*keys) + super(*keys.map { |k| convert_key(k) }) + end + + # Used to provide the same interface as Hash. + # + # @return [Mash] This mash unchanged. + def stringify_keys!; self end + + # @return [Hash] The mash as a Hash with symbolized keys. + def symbolize_keys + h = Hash.new(default) + each { |key, val| h[key.to_sym] = val } + h + end + + # @return [Hash] The mash as a Hash with string keys. + def to_hash + Hash.new(default).merge(self) + end + + # @return [Mash] Convert a Hash into a Mash + # The input Hash's default value is maintained + def self.from_hash(hash) + mash = Mash.new(hash) + mash.default = hash.default + mash + end + + protected + + # @param key The key to convert. + # + # @param [Object] + # The converted key. If the key was a symbol, it will be converted to a + # string. + # + # @api private + def convert_key(key) + key.is_a?(Symbol) ? key.to_s : key + end + + # @param value The value to convert. + # + # @return [Object] + # The converted value. A Hash or an Array of hashes, will be converted to + # their Mash equivalents. + # + # @api private + def convert_value(value) + if value.class == Hash + Mash.from_hash(value) + elsif value.is_a?(Array) + value.collect { |e| convert_value(e) } + else + value + end + end + end +end diff --git a/chef-utils/lib/chef-utils/version.rb b/chef-utils/lib/chef-utils/version.rb new file mode 100644 index 0000000000..fec7ca5ad8 --- /dev/null +++ b/chef-utils/lib/chef-utils/version.rb @@ -0,0 +1,19 @@ +# Copyright:: Copyright 2010-2019, 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. + +module ChefUtils + CHEFUTILS_ROOT = File.expand_path("../..", __FILE__) + VERSION = "15.4.69".freeze +end diff --git a/chef-utils/spec/spec_helper.rb b/chef-utils/spec/spec_helper.rb new file mode 100644 index 0000000000..20d49fd766 --- /dev/null +++ b/chef-utils/spec/spec_helper.rb @@ -0,0 +1,93 @@ +require "chef-utils" + +# FIXME: dynamically generate this for accuracy +HELPER_MODULES = [ + ChefUtils::DSL::Architecture, + ChefUtils::DSL::Introspection, + ChefUtils::DSL::OS, + ChefUtils::DSL::PathSanity, + ChefUtils::DSL::Platform, + ChefUtils::DSL::PlatformFamily, + ChefUtils::DSL::Service, + ChefUtils::DSL::Which, +].freeze + +ARCH_HELPERS = (ChefUtils::DSL::Architecture.methods - Module.methods).freeze +OS_HELPERS = (ChefUtils::DSL::OS.methods - Module.methods).freeze +PLATFORM_HELPERS = (ChefUtils::DSL::Platform.methods - Module.methods).freeze +PLATFORM_FAMILY_HELPERS = (ChefUtils::DSL::PlatformFamily.methods - Module.methods).freeze +INTROSPECTION_HELPERS = (ChefUtils::DSL::Introspection.methods - Module.methods).freeze + +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + + # These two settings work together to allow you to limit a spec run + # to individual examples or groups you care about by tagging them with + # `:focus` metadata. When nothing is tagged with `:focus`, all examples + # get run. + config.filter_run :focus + config.run_all_when_everything_filtered = true + + config.filter_run_excluding windows_only: true unless ChefUtils.windows? + config.filter_run_excluding unix_only: true if ChefUtils.windows? + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax + # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching + config.disable_monkey_patching! + + # This setting enables warnings. It's recommended, but in some cases may + # be too noisy due to issues in dependencies. + config.warnings = true + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = "doc" + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + # config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +end diff --git a/chef-utils/spec/unit/dsl/architecture_spec.rb b/chef-utils/spec/unit/dsl/architecture_spec.rb new file mode 100644 index 0000000000..a2ce300fe0 --- /dev/null +++ b/chef-utils/spec/unit/dsl/architecture_spec.rb @@ -0,0 +1,139 @@ +# +# Copyright:: Copyright 2018-2019, 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" + +def arch_reports_true_for(*args) + args.each do |method| + it "reports true for #{method}" do + expect(described_class.send(method, node)).to be true + end + end + (ARCH_HELPERS - args).each do |method| + it "reports false for #{method}" do + expect(described_class.send(method, node)).to be false + end + end +end + +RSpec.describe ChefUtils::DSL::Architecture do + let(:node) { { "kernel" => { "machine" => arch } } } + + ( HELPER_MODULES - [ described_class ] ).each do |klass| + it "does not have methods that collide with #{klass}" do + expect((klass.methods - Module.methods) & ARCH_HELPERS).to be_empty + end + end + + ARCH_HELPERS.each do |helper| + it "has the #{helper} in the ChefUtils module" do + expect(ChefUtils).to respond_to(helper) + end + end + + context "on x86_64" do + let(:arch) { "x86_64" } + + arch_reports_true_for(:intel?, :_64_bit?) + end + + context "on amd64" do + let(:arch) { "amd64" } + + arch_reports_true_for(:intel?, :_64_bit?) + end + context "on ppc64" do + let(:arch) { "ppc64" } + + arch_reports_true_for(:ppc64?, :_64_bit?) + end + context "on ppc64le" do + let(:arch) { "ppc64le" } + + arch_reports_true_for(:ppc64le?, :_64_bit?) + end + context "on s390x" do + let(:arch) { "s390x" } + + arch_reports_true_for(:s390x?, :_64_bit?) + end + context "on ia64" do + let(:arch) { "ia64" } + + arch_reports_true_for(:_64_bit?) + end + context "on sparc64" do + let(:arch) { "sparc64" } + + arch_reports_true_for(:_64_bit?) + end + context "on aarch64" do + let(:arch) { "aarch64" } + + arch_reports_true_for(:_64_bit?) + end + context "on arch64" do + let(:arch) { "arch64" } + + arch_reports_true_for(:_64_bit?) + end + context "on arm64" do + let(:arch) { "arm64" } + + arch_reports_true_for(:_64_bit?) + end + context "on sun4v" do + let(:arch) { "sun4v" } + + arch_reports_true_for(:sparc?, :_64_bit?) + end + context "on sun4u" do + let(:arch) { "sun4u" } + + arch_reports_true_for(:sparc?, :_64_bit?) + end + context "on i86pc" do + let(:arch) { "i86pc" } + + arch_reports_true_for(:i386?, :intel?, :_32_bit?) + end + context "on i386" do + let(:arch) { "i386" } + + arch_reports_true_for(:i386?, :intel?, :_32_bit?) + end + context "on i686" do + let(:arch) { "i686" } + + arch_reports_true_for(:i386?, :intel?, :_32_bit?) + end + context "on powerpc" do + let(:arch) { "powerpc" } + + arch_reports_true_for(:powerpc?, :_32_bit?) + end + context "on armhf" do + let(:arch) { "armhf" } + + arch_reports_true_for(:armhf?, :_32_bit?) + end + context "on s390" do + let(:arch) { "s390" } + + arch_reports_true_for(:s390?, :_32_bit?) + end +end diff --git a/chef-utils/spec/unit/dsl/dsl_spec.rb b/chef-utils/spec/unit/dsl/dsl_spec.rb new file mode 100644 index 0000000000..f05be11d4a --- /dev/null +++ b/chef-utils/spec/unit/dsl/dsl_spec.rb @@ -0,0 +1,33 @@ +# +# Copyright:: Copyright 2018-2019, 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" + +RSpec.describe ChefUtils do + class ThingWithDSL + extend ChefUtils + end + + (OS_HELPERS + ARCH_HELPERS + PLATFORM_HELPERS + PLATFORM_FAMILY_HELPERS + INTROSPECTION_HELPERS).each do |helper| + it "has the #{helper} in the ChefUtils module" do + expect(ThingWithDSL).to respond_to(helper) + end + it "has the #{helper} class method in the ChefUtils module" do + expect(ChefUtils).to respond_to(helper) + end + end +end diff --git a/chef-utils/spec/unit/dsl/introspection_spec.rb b/chef-utils/spec/unit/dsl/introspection_spec.rb new file mode 100644 index 0000000000..d45a3c6000 --- /dev/null +++ b/chef-utils/spec/unit/dsl/introspection_spec.rb @@ -0,0 +1,168 @@ +# +# Copyright:: Copyright 2018-2019, 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" + +RSpec.describe ChefUtils::DSL::Introspection do + class IntrospectionTestClass + include ChefUtils::DSL::Introspection + attr_accessor :node + def initialize(node) + @node = node + end + end + + let(:node) { double("node") } + + let(:test_instance) { IntrospectionTestClass.new(node) } + + context "#docker?" do + # FIXME: use a real VividMash for these tests insted of stubbing + it "is false by default" do + expect(node).to receive(:read).with("virtualization", "systems", "docker").and_return(nil) + expect(ChefUtils.docker?(node)).to be false + end + it "is true when ohai reports a docker guest" do + expect(node).to receive(:read).with("virtualization", "systems", "docker").and_return("guest") + expect(ChefUtils.docker?(node)).to be true + end + it "is false for any other value other than guest" do + expect(node).to receive(:read).with("virtualization", "systems", "docker").and_return("some nonsense") + expect(ChefUtils.docker?(node)).to be false + end + end + + context "#systemd?" do + # FIXME: somehow test the train helpers + it "returns false if /proc/1/comm does not exist" do + expect(File).to receive(:exist?).with("/proc/1/comm").and_return(false) + expect(ChefUtils.systemd?(node)).to be false + end + + it "returns false if /proc/1/comm is not systemd" do + expect(File).to receive(:exist?).with("/proc/1/comm").and_return(true) + expect(File).to receive(:open).with("/proc/1/comm").and_return(StringIO.new("upstart\n")) + expect(ChefUtils.systemd?(node)).to be false + end + + it "returns true if /proc/1/comm is systemd" do + expect(File).to receive(:exist?).with("/proc/1/comm").and_return(true) + expect(File).to receive(:open).with("/proc/1/comm").and_return(StringIO.new("systemd\n")) + expect(ChefUtils.systemd?(node)).to be true + end + end + + context "#kitchen?" do + before do + @saved = ENV["TEST_KITCHEN"] + end + after do + ENV["TEST_KITCHEN"] = @saved + end + + it "return true if ENV['TEST_KITCHEN'] is not set" do + ENV.delete("TEST_KITCHEN") + expect(ChefUtils.kitchen?(node)).to be false + end + + it "return true if ENV['TEST_KITCHEN'] is nil" do + ENV["TEST_KITCHEN"] = nil + expect(ChefUtils.kitchen?(node)).to be false + end + + it "return true if ENV['TEST_KITCHEN'] is set" do + ENV["TEST_KITCHEN"] = "1" + expect(ChefUtils.kitchen?(node)).to be true + end + end + + context "#ci?" do + before do + @saved = ENV["CI"] + end + after do + ENV["CI"] = @saved + end + + it "return true if ENV['CI'] is not set" do + ENV.delete("CI") + expect(ChefUtils.ci?(node)).to be false + end + + it "return true if ENV['CI'] is nil" do + ENV["CI"] = nil + expect(ChefUtils.ci?(node)).to be false + end + + it "return true if ENV['CI'] is set" do + ENV["CI"] = "1" + expect(ChefUtils.ci?(node)).to be true + end + end + + context "#has_systemd_service_unit?" do + # FIXME: test through train helpers + + before do + %w{ /etc /usr/lib /lib /run }.each do |base| + allow(File).to receive(:exist?).with("#{base}/systemd/system/example.service").and_return(false) + allow(File).to receive(:exist?).with("#{base}/systemd/system/example@.service").and_return(false) + end + end + + it "is false if no unit is present" do + expect(ChefUtils.has_systemd_service_unit?("example")).to be false + end + + it "is false if no template is present" do + expect(ChefUtils.has_systemd_service_unit?("example@instance1")).to be false + end + + %w{ /etc /usr/lib /lib /run }.each do |base| + it "finds a unit in #{base}" do + expect(File).to receive(:exist?).with("#{base}/systemd/system/example.service").and_return(true) + expect(ChefUtils.has_systemd_service_unit?("example")).to be true + end + + it "finds a template in #{base}" do + expect(File).to receive(:exist?).with("#{base}/systemd/system/example@.service").and_return(true) + expect(ChefUtils.has_systemd_service_unit?("example@instance1")).to be true + end + end + end + + context "#has_systemd_unit?" do + # FIXME: test through train helpers + + before do + %w{ /etc /usr/lib /lib /run }.each do |base| + allow(File).to receive(:exist?).with("#{base}/systemd/system/example.mount").and_return(false) + end + end + + it "is false if no unit is present" do + expect(ChefUtils.has_systemd_unit?("example.mount")).to be false + end + + %w{ /etc /usr/lib /lib /run }.each do |base| + it "finds a unit in #{base}" do + expect(File).to receive(:exist?).with("#{base}/systemd/system/example.mount").and_return(true) + expect(ChefUtils.has_systemd_unit?("example.mount")).to be true + end + end + end +end diff --git a/chef-utils/spec/unit/dsl/os_spec.rb b/chef-utils/spec/unit/dsl/os_spec.rb new file mode 100644 index 0000000000..d5d8c7d89e --- /dev/null +++ b/chef-utils/spec/unit/dsl/os_spec.rb @@ -0,0 +1,174 @@ +# +# Copyright:: Copyright 2018-2019, 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 "fauxhai" + +def os_reports_true_for(*args) + args.each do |method| + it "reports true for #{method}" do + expect(described_class.send(method, node)).to be true + end + end + (OS_HELPERS - args).each do |method| + it "reports false for #{method}" do + expect(described_class.send(method, node)).to be false + end + end +end + +RSpec.describe ChefUtils::DSL::OS do + let(:node) { Fauxhai.mock(options).data } + + ( HELPER_MODULES - [ described_class ] ).each do |klass| + it "does not have methods that collide with #{klass}" do + expect((klass.methods - Module.methods) & OS_HELPERS).to be_empty + end + end + + OS_HELPERS.each do |helper| + it "has the #{helper} in the ChefUtils module" do + expect(ChefUtils).to respond_to(helper) + end + end + + context "on ubuntu" do + let(:options) { { platform: "ubuntu" } } + + os_reports_true_for(:linux?) + end + + context "on raspbian" do + let(:options) { { platform: "raspbian" } } + + os_reports_true_for(:linux?) + end + + context "on linuxmint" do + let(:options) { { platform: "linuxmint" } } + + os_reports_true_for(:linux?) + end + + context "on debian" do + let(:options) { { platform: "debian" } } + + os_reports_true_for(:linux?) + end + + context "on amazon" do + let(:options) { { platform: "amazon" } } + + os_reports_true_for(:linux?) + end + + context "on arch" do + let(:options) { { platform: "arch" } } + + os_reports_true_for(:linux?) + end + + context "on centos" do + let(:options) { { platform: "centos" } } + + os_reports_true_for(:linux?) + end + + context "on clearos" do + let(:options) { { platform: "clearos" } } + + os_reports_true_for(:linux?) + end + + context "on dragonfly4" do + let(:options) { { platform: "dragonfly4" } } + + os_reports_true_for + end + + context "on fedora" do + let(:options) { { platform: "fedora" } } + + os_reports_true_for(:linux?) + end + + context "on freebsd" do + let(:options) { { platform: "freebsd" } } + + os_reports_true_for + end + + context "on gentoo" do + let(:options) { { platform: "gentoo" } } + + os_reports_true_for(:linux?) + end + + context "on mac_os_x" do + let(:options) { { platform: "mac_os_x" } } + + os_reports_true_for(:darwin?) + end + + context "on openbsd" do + let(:options) { { platform: "openbsd" } } + + os_reports_true_for + end + + context "on opensuse" do + let(:options) { { platform: "opensuse" } } + + os_reports_true_for(:linux?) + end + + context "on oracle" do + let(:options) { { platform: "oracle" } } + + os_reports_true_for(:linux?) + end + + context "on redhat" do + let(:options) { { platform: "redhat" } } + + os_reports_true_for(:linux?) + end + + context "on smartos" do + let(:options) { { platform: "smartos" } } + + os_reports_true_for + end + + context "on solaris2" do + let(:options) { { platform: "solaris2" } } + + os_reports_true_for + end + + context "on suse" do + let(:options) { { platform: "suse" } } + + os_reports_true_for(:linux?) + end + + context "on windows" do + let(:options) { { platform: "windows" } } + + os_reports_true_for + end +end diff --git a/chef-utils/spec/unit/dsl/path_sanity_spec.rb b/chef-utils/spec/unit/dsl/path_sanity_spec.rb new file mode 100644 index 0000000000..dc841f296b --- /dev/null +++ b/chef-utils/spec/unit/dsl/path_sanity_spec.rb @@ -0,0 +1,85 @@ +# +# Copyright:: Copyright 2018-2019, 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" + +RSpec.describe ChefUtils::DSL::PathSanity do + class PathSanityTestClass + include ChefUtils::DSL::PathSanity + end + + before do + allow(Gem).to receive(:bindir).and_return("/opt/ruby/bin/bundle") + allow(RbConfig::CONFIG).to receive(:[]).with("bindir").and_return("/opt/ruby/bin") + end + + context "on unix" do + before do + allow(ChefUtils).to receive(:windows?).and_return(false) + end + + let(:test_instance) { PathSanityTestClass.new } + + it "works with no path" do + env = {} + expect(test_instance.sanitized_path(env)).to eql("#{Gem.bindir}:#{RbConfig::CONFIG["bindir"]}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") + end + + it "works with nil path" do + env = { "PATH" => nil } + expect(test_instance.sanitized_path(env)).to eql("#{Gem.bindir}:#{RbConfig::CONFIG["bindir"]}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") + end + + it "works with empty path" do + env = { "PATH" => "" } + expect(test_instance.sanitized_path(env)).to eql("#{Gem.bindir}:#{RbConfig::CONFIG["bindir"]}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") + end + + it "appends the sane_paths to the end of the path, preserving any that already exist, in the same order" do + env = { "PATH" => "/bin:/opt/app/bin:/sbin" } + expect(test_instance.sanitized_path(env)).to eql("#{Gem.bindir}:#{RbConfig::CONFIG["bindir"]}:/bin:/opt/app/bin:/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin") + end + end + + context "on windows" do + before do + allow(ChefUtils).to receive(:windows?).and_return(true) + end + + let(:test_instance) { PathSanityTestClass.new } + + it "works with no path" do + env = {} + expect(test_instance.sanitized_path(env)).to eql("#{Gem.bindir};#{RbConfig::CONFIG["bindir"]}") + end + + it "works with nil path" do + env = { "PATH" => nil } + expect(test_instance.sanitized_path(env)).to eql("#{Gem.bindir};#{RbConfig::CONFIG["bindir"]}") + end + + it "works with empty path" do + env = { "PATH" => "" } + expect(test_instance.sanitized_path(env)).to eql("#{Gem.bindir};#{RbConfig::CONFIG["bindir"]}") + end + + it "prepends to an existing path" do + env = { "PATH" => '%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\\' } + expect(test_instance.sanitized_path(env)).to eql("#{Gem.bindir};#{RbConfig::CONFIG["bindir"]};%SystemRoot%\\system32;%SystemRoot%;%SystemRoot%\\System32\\Wbem;%SYSTEMROOT%\\System32\\WindowsPowerShell\\v1.0\\") + end + end +end diff --git a/chef-utils/spec/unit/dsl/platform_family_spec.rb b/chef-utils/spec/unit/dsl/platform_family_spec.rb new file mode 100644 index 0000000000..fa33deaf37 --- /dev/null +++ b/chef-utils/spec/unit/dsl/platform_family_spec.rb @@ -0,0 +1,192 @@ +# +# Copyright:: Copyright 2018-2019, 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 "fauxhai" + +def pf_reports_true_for(*args) + args.each do |method| + it "reports true for #{method}" do + expect(described_class.send(method, node)).to be true + end + end + (PLATFORM_FAMILY_HELPERS - [ :windows_ruby_platform? ] - args).each do |method| + it "reports false for #{method}" do + expect(described_class.send(method, node)).to be false + end + end +end + +RSpec.describe ChefUtils::DSL::PlatformFamily do + let(:node) { Fauxhai.mock(options).data } + + ( HELPER_MODULES - [ described_class ] ).each do |klass| + it "does not have methods that collide with #{klass}" do + expect((klass.methods - Module.methods) & PLATFORM_FAMILY_HELPERS).to be_empty + end + end + + ( PLATFORM_FAMILY_HELPERS - [ :windows_ruby_platform? ]).each do |helper| + it "has the #{helper} in the ChefUtils module" do + expect(ChefUtils).to respond_to(helper) + end + end + + context "on ubuntu" do + let(:options) { { platform: "ubuntu" } } + + pf_reports_true_for(:debian?) + end + + context "on raspbian" do + let(:options) { { platform: "raspbian" } } + + pf_reports_true_for(:debian?) + end + + context "on linuxmint" do + let(:options) { { platform: "linuxmint" } } + + pf_reports_true_for(:debian?) + end + + context "on debian" do + let(:options) { { platform: "debian" } } + + pf_reports_true_for(:debian?) + end + + context "on aix" do + let(:options) { { platform: "aix" } } + + pf_reports_true_for(:aix?) + end + + context "on amazon" do + let(:options) { { platform: "amazon" } } + + pf_reports_true_for(:amazon?, :amazon_linux?, :rpm_based?, :fedora_derived?) + end + + context "on arch" do + let(:options) { { platform: "arch" } } + + pf_reports_true_for(:arch?, :arch_linux?) + end + + context "on centos" do + let(:options) { { platform: "centos" } } + + pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?) + end + + context "on clearos" do + let(:options) { { platform: "clearos" } } + + pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?) + end + + context "on dragonfly4" do + let(:options) { { platform: "dragonfly4" } } + + pf_reports_true_for(:dragonflybsd?) + end + + context "on fedora" do + let(:options) { { platform: "fedora" } } + + pf_reports_true_for(:fedora?, :rpm_based?, :fedora_derived?, :redhat_based?) + end + + context "on freebsd" do + let(:options) { { platform: "freebsd" } } + + pf_reports_true_for(:freebsd?, :bsd_based?) + end + + context "on gentoo" do + let(:options) { { platform: "gentoo" } } + + pf_reports_true_for(:gentoo?) + end + + context "on mac_os_x" do + let(:options) { { platform: "mac_os_x" } } + + pf_reports_true_for(:mac_os_x?, :mac?, :osx?, :macos?) + end + + context "on openbsd" do + let(:options) { { platform: "openbsd" } } + + pf_reports_true_for(:openbsd?, :bsd_based?) + end + + context "on opensuse" do + let(:options) { { platform: "opensuse" } } + + pf_reports_true_for(:suse?, :rpm_based?) + end + + context "on oracle" do + let(:options) { { platform: "oracle" } } + + pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?) + end + + context "on redhat" do + let(:options) { { platform: "redhat" } } + + pf_reports_true_for(:rhel?, :rpm_based?, :fedora_derived?, :redhat_based?, :el?) + end + + context "on smartos" do + let(:options) { { platform: "smartos" } } + + pf_reports_true_for(:smartos?, :solaris_based?) + end + + context "on solaris2" do + let(:options) { { platform: "solaris2" } } + + pf_reports_true_for(:solaris?, :solaris2?, :solaris_based?) + end + + context "on suse" do + let(:options) { { platform: "suse" } } + + pf_reports_true_for(:suse?, :rpm_based?) + end + + context "on windows" do + let(:options) { { platform: "windows" } } + + pf_reports_true_for(:windows?) + end + + context "node-independent windows APIs" do + if RUBY_PLATFORM =~ /mswin|mingw32|windows/ + it "reports true for :windows_ruby_platform?" do + expect(described_class.windows_ruby_platform?).to be true + end + else + it "reports false for :windows_ruby_platform?" do + expect(described_class.windows_ruby_platform?).to be false + end + end + end +end diff --git a/chef-utils/spec/unit/dsl/platform_spec.rb b/chef-utils/spec/unit/dsl/platform_spec.rb new file mode 100644 index 0000000000..dade8b0495 --- /dev/null +++ b/chef-utils/spec/unit/dsl/platform_spec.rb @@ -0,0 +1,234 @@ +# +# Copyright:: Copyright 2018-2019, 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 "fauxhai" + +def platform_reports_true_for(*args) + args.each do |method| + it "reports true for #{method} on the module given a node" do + expect(described_class.send(method, node)).to be true + end + it "reports true for #{method} when mixed into a class with a node" do + expect(thing_with_a_node.send(method, node)).to be true + end + it "reports true for #{method} when mixed into a class with a run_context" do + expect(thing_with_a_run_context.send(method, node)).to be true + end + it "reports true for #{method} when mixed into a class with the dsl" do + expect(thing_with_the_dsl.send(method, node)).to be true + end + it "reports true for #{method} on the main class give a node" do + expect(ChefUtils.send(method, node)).to be true + end + end + (PLATFORM_HELPERS - args).each do |method| + it "reports false for #{method} on the module given a node" do + expect(described_class.send(method, node)).to be false + end + it "reports false for #{method} when mixed into a class with a node" do + expect(thing_with_a_node.send(method, node)).to be false + end + it "reports false for #{method} when mixed into a class with the dsl" do + expect(thing_with_the_dsl.send(method, node)).to be false + end + it "reports false for #{method} on the main class give a node" do + expect(ChefUtils.send(method, node)).to be false + end + end +end + +RSpec.describe ChefUtils::DSL::Platform do + let(:node) { Fauxhai.mock(options).data } + + class ThingWithANode + include ChefUtils::DSL::Platform + attr_accessor :node + def initialize(node) + @node = node + end + end + + class ThingWithARunContext + include ChefUtils::DSL::Platform + class RunContext + attr_accessor :node + end + attr_accessor :run_context + def initialize(node) + @run_context = RunContext.new + run_context.node = node + end + end + + class ThingWithTheDSL + include ChefUtils + attr_accessor :node + def initialize(node) + @node = node + end + end + + let(:thing_with_a_node) { ThingWithANode.new(node) } + let(:thing_with_a_run_context) { ThingWithARunContext.new(node) } + let(:thing_with_the_dsl) { ThingWithTheDSL.new(node) } + + ( HELPER_MODULES - [ described_class ] ).each do |klass| + it "does not have methods that collide with #{klass}" do + expect((klass.methods - Module.methods) & PLATFORM_HELPERS).to be_empty + end + end + + context "on ubuntu" do + let(:options) { { platform: "ubuntu" } } + + platform_reports_true_for(:ubuntu?, :ubuntu_platform?) + end + + context "on raspbian" do + let(:options) { { platform: "raspbian" } } + + platform_reports_true_for(:raspbian?, :raspbian_platform?) + end + + context "on linuxmint" do + let(:options) { { platform: "linuxmint" } } + + platform_reports_true_for(:mint?, :linux_mint?, :linuxmint?, :linuxmint_platform?) + end + + context "on debian" do + let(:options) { { platform: "debian" } } + + platform_reports_true_for(:debian_platform?) + end + + context "on aix" do + let(:options) { { platform: "aix" } } + + platform_reports_true_for(:aix_platform?) + end + + context "on amazon" do + let(:options) { { platform: "amazon" } } + + platform_reports_true_for(:amazon_platform?) + end + + context "on arch" do + let(:options) { { platform: "arch" } } + + platform_reports_true_for(:arch_platform?) + end + + context "on centos" do + let(:options) { { platform: "centos" } } + + platform_reports_true_for(:centos?, :centos_platform?) + end + + context "on clearos" do + let(:options) { { platform: "clearos" } } + + platform_reports_true_for(:clearos?, :clearos_platform?) + end + + context "on dragonfly4" do + let(:options) { { platform: "dragonfly4" } } + + platform_reports_true_for(:dragonfly_platform?) + end + + context "on fedora" do + let(:options) { { platform: "fedora" } } + + platform_reports_true_for(:fedora_platform?) + end + + context "on freebsd" do + let(:options) { { platform: "freebsd" } } + + platform_reports_true_for(:freebsd_platform?) + end + + context "on gentoo" do + let(:options) { { platform: "gentoo" } } + + platform_reports_true_for(:gentoo_platform?) + end + + context "on mac_os_x" do + let(:options) { { platform: "mac_os_x" } } + + platform_reports_true_for(:mac_os_x_platform?, :macos_platform?) + end + + context "on openbsd" do + let(:options) { { platform: "openbsd" } } + + platform_reports_true_for(:openbsd_platform?) + end + + context "on oracle" do + let(:options) { { platform: "oracle" } } + + platform_reports_true_for(:oracle?, :oracle_linux?, :oracle_platform?) + end + + context "on redhat" do + let(:options) { { platform: "redhat" } } + + platform_reports_true_for(:redhat?, :redhat_enterprise_linux?, :redhat_enterprise?, :redhat_platform?) + end + + context "on smartos" do + let(:options) { { platform: "smartos" } } + + platform_reports_true_for(:smartos_platform?) + end + + context "on solaris2" do + let(:options) { { platform: "solaris2" } } + + platform_reports_true_for(:solaris2_platform?) + end + + context "on suse" do + let(:options) { { platform: "suse" } } + + platform_reports_true_for(:suse_platform?) + end + + context "on windows" do + let(:options) { { platform: "windows" } } + + platform_reports_true_for(:windows_platform?) + end + + context "on opensuseleap" do + let(:node) { { "platform" => "opensuseleap", "platform_version" => "15.1", "platform_family" => "suse", "os" => "linux" } } + + platform_reports_true_for(:opensuse_platform?, :opensuseleap_platform?, :opensuse?, :leap_platform?) + end + + context "on opensuse" do + let(:node) { { "platform" => "opensuse", "platform_version" => "11.0", "platform_family" => "suse", "os" => "linux" } } + + platform_reports_true_for(:opensuse_platform?, :opensuseleap_platform?, :opensuse?, :leap_platform?) + end + +end diff --git a/chef-utils/spec/unit/dsl/service_spec.rb b/chef-utils/spec/unit/dsl/service_spec.rb new file mode 100644 index 0000000000..35e6b10e77 --- /dev/null +++ b/chef-utils/spec/unit/dsl/service_spec.rb @@ -0,0 +1,116 @@ +# +# Copyright:: Copyright 2018-2019, 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" + +RSpec.describe ChefUtils::DSL::Service do + class ServiceTestClass + include ChefUtils::DSL::Service + end + + let(:test_instance) { ServiceTestClass.new } + + context "#debianrcd?" do + it "is true if the binary is installed" do + expect(File).to receive(:exist?).with("/usr/sbin/update-rc.d").and_return(true) + expect(test_instance.debianrcd?).to be true + end + it "is false if the binary is not installed" do + expect(File).to receive(:exist?).with("/usr/sbin/update-rc.d").and_return(false) + expect(test_instance.debianrcd?).to be false + end + end + + context "#invokercd?" do + it "is true if the binary is installed" do + expect(File).to receive(:exist?).with("/usr/sbin/invoke-rc.d").and_return(true) + expect(test_instance.invokercd?).to be true + end + it "is false if the binary is not installed" do + expect(File).to receive(:exist?).with("/usr/sbin/invoke-rc.d").and_return(false) + expect(test_instance.invokercd?).to be false + end + end + + context "#upstart?" do + it "is true if the binary is installed" do + expect(File).to receive(:exist?).with("/sbin/initctl").and_return(true) + expect(test_instance.upstart?).to be true + end + it "is false if the binary is not installed" do + expect(File).to receive(:exist?).with("/sbin/initctl").and_return(false) + expect(test_instance.upstart?).to be false + end + end + + context "#insserv?" do + it "is true if the binary is installed" do + expect(File).to receive(:exist?).with("/sbin/insserv").and_return(true) + expect(test_instance.insserv?).to be true + end + it "is false if the binary is not installed" do + expect(File).to receive(:exist?).with("/sbin/insserv").and_return(false) + expect(test_instance.insserv?).to be false + end + end + + context "#redhatrcd?" do + it "is true if the binary is installed" do + expect(File).to receive(:exist?).with("/sbin/chkconfig").and_return(true) + expect(test_instance.redhatrcd?).to be true + end + it "is false if the binary is not installed" do + expect(File).to receive(:exist?).with("/sbin/chkconfig").and_return(false) + expect(test_instance.redhatrcd?).to be false + end + end + + context "#service_script_exist?" do + it "is true if the type is :initd and /etc/init.d script exists" do + expect(File).to receive(:exist?).with("/etc/init.d/example").and_return(true) + expect(test_instance.service_script_exist?(:initd, "example")).to be true + end + it "is false if the type is :initd and /etc/init.d script does not exist" do + expect(File).to receive(:exist?).with("/etc/init.d/example").and_return(false) + expect(test_instance.service_script_exist?(:initd, "example")).to be false + end + it "is true if the type is :upstart and /etc/init script exists" do + expect(File).to receive(:exist?).with("/etc/init/example.conf").and_return(true) + expect(test_instance.service_script_exist?(:upstart, "example")).to be true + end + it "is false if the type is :upstart and /etc/init script does not exist" do + expect(File).to receive(:exist?).with("/etc/init/example.conf").and_return(false) + expect(test_instance.service_script_exist?(:upstart, "example")).to be false + end + it "is true if the type is :xinetd and /etc/xinetd.d script exists" do + expect(File).to receive(:exist?).with("/etc/xinetd.d/example").and_return(true) + expect(test_instance.service_script_exist?(:xinetd, "example")).to be true + end + it "is false if the type is :xinetd and /etc/xinetd.d script does not exist" do + expect(File).to receive(:exist?).with("/etc/xinetd.d/example").and_return(false) + expect(test_instance.service_script_exist?(:xinetd, "example")).to be false + end + it "is true if the type is :etc_rcd and /etc/rc.d script exists" do + expect(File).to receive(:exist?).with("/etc/rc.d/example").and_return(true) + expect(test_instance.service_script_exist?(:etc_rcd, "example")).to be true + end + it "is false if the type is :etc_rcd and /etc/rc.d script does not exist" do + expect(File).to receive(:exist?).with("/etc/rc.d/example").and_return(false) + expect(test_instance.service_script_exist?(:etc_rcd, "example")).to be false + end + end +end diff --git a/chef-utils/spec/unit/dsl/which_spec.rb b/chef-utils/spec/unit/dsl/which_spec.rb new file mode 100644 index 0000000000..74a4e5638e --- /dev/null +++ b/chef-utils/spec/unit/dsl/which_spec.rb @@ -0,0 +1,168 @@ +# +# Copyright:: Copyright 2018-2019, 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" + +RSpec.describe ChefUtils::DSL::Which do + + class WhichTestClass + include ChefUtils::DSL::Which + end + + let(:test) { WhichTestClass.new } + + describe "#which" do + def self.test_which(description, *args, path: ["/dir1", "/dir2" ].join(File::PATH_SEPARATOR), finds: nil, others: [], directory: false, &block) + it description do + # stub the ENV['PATH'] + expect(ENV).to receive(:[]).with("PATH").and_return(path) + + # most files should not be found + allow(File).to receive(:executable?).and_return(false) + allow(File).to receive(:directory?).and_return(false) + + # stub the expectation + expect(File).to receive(:executable?).with(finds).and_return(true) if finds + + # if the file we find is a directory + expect(File).to receive(:directory?).with(finds).and_return(true) if finds && directory + + # allow for stubbing other paths to exist that we should not find + others.each do |other| + allow(File).to receive(:executable?).with(other).and_return(true) + end + + # setup the actual expectation on the return value + if finds && !directory + expect(test.which(*args, &block)).to eql(finds) + else + expect(test.which(*args, &block)).to eql(false) + end + end + end + + context "simple usage" do + test_which("returns false when it does not find anything", "foo1") + + ["/dir1", "/dir2" ].each do |dir| + test_which("finds `foo1` in #{dir} when it is stubbed", "foo1", finds: "#{dir}/foo1") + end + + test_which("does not find an executable directory", "foo1", finds: "/dir1/foo1", directory: true) + end + + context "with an array of args" do + test_which("finds the first arg", "foo1", "foo2", finds: "/dir2/foo1") + + test_which("finds the second arg", "foo1", "foo2", finds: "/dir2/foo2") + + test_which("finds the first arg when there's both", "foo1", "foo2", finds: "/dir2/foo1", others: [ "/dir1/foo2" ]) + + test_which("and the directory order can be reversed", "foo1", "foo2", finds: "/dir1/foo1", others: [ "/dir2/foo2" ]) + + test_which("or be the same", "foo1", "foo2", finds: "/dir1/foo1", others: [ "/dir1/foo2" ]) + end + + context "with a block" do + test_which("doesnt find it if its false", "foo1", others: [ "/dir1/foo1" ]) do |f| + false + end + + test_which("finds it if its true", "foo1", finds: "/dir1/foo1") do |f| + true + end + + test_which("passes in the filename as the arg", "foo1", finds: "/dir1/foo1") do |f| + raise "bad arg to block" unless f == "/dir1/foo1" + + true + end + + test_which("arrays with blocks", "foo1", "foo2", finds: "/dir2/foo1", others: [ "/dir1/foo2" ]) do |f| + raise "bad arg to block" unless f == "/dir2/foo1" || f == "/dir1/foo2" + + true + end + end + + context "nil path" do + test_which("returns false when it does not find anything", "foo1", path: nil) + end + end + + describe "#where" do + def self.test_where(description, *args, path: ["/dir1", "/dir2" ].join(File::PATH_SEPARATOR), finds: [], others: [], &block) + it description do + # stub the ENV['PATH'] + expect(ENV).to receive(:[]).with("PATH").and_return(path) + + # most files should not be found + allow(File).to receive(:executable?).and_return(false) + allow(File).to receive(:directory?).and_return(false) + + # allow for stubbing other paths to exist that we should not return + others.each do |other| + allow(File).to receive(:executable?).with(other).and_return(true) + end + + # stub the expectation + finds.each do |path| + expect(File).to receive(:executable?).with(path).and_return(true) + end + + # setup the actual expectation on the return value + expect(test.where(*args, &block)).to eql(finds) + end + end + + context "simple usage" do + test_where("returns empty array when it doesn't find anything", "foo1") + + ["/dir1", "/dir2" ].each do |dir| + test_where("finds `foo1` in #{dir} when it is stubbed", "foo1", finds: [ "#{dir}/foo1" ]) + end + + test_where("finds `foo1` in all directories", "foo1", finds: [ "/dir1/foo1", "/dir2/foo1" ]) + end + + context "with an array of args" do + test_where("finds the first arg", "foo1", "foo2", finds: [ "/dir2/foo1" ]) + + test_where("finds the second arg", "foo1", "foo2", finds: [ "/dir2/foo2" ]) + + test_where("finds foo1 before foo2 if the dirs are reversed", "foo1", "foo2", finds: [ "/dir1/foo1", "/dir2/foo2" ]) + + test_where("finds them both in the same directory", "foo1", "foo2", finds: [ "/dir1/foo1", "/dir1/foo2" ]) + + test_where("finds foo2 first if they're reversed", "foo2", "foo1", finds: [ "/dir1/foo2", "/dir1/foo1" ]) + end + + context "with a block do" do + test_where("finds foo1 and foo2 if they exist and the block is true", "foo1", "foo2", finds: [ "/dir1/foo2", "/dir2/foo2" ]) do + true + end + + test_where("does not finds foo1 and foo2 if they exist and the block is false", "foo1", "foo2", others: [ "/dir1/foo2", "/dir2/foo2" ]) do + false + end + end + + context "with a nil path" do + test_where("returns empty array when it doesn't find anything", "foo1", path: nil) + end + end +end diff --git a/chef-utils/spec/unit/mash_spec.rb b/chef-utils/spec/unit/mash_spec.rb new file mode 100644 index 0000000000..e8d321147e --- /dev/null +++ b/chef-utils/spec/unit/mash_spec.rb @@ -0,0 +1,50 @@ +# +# Author:: Matthew Kent () +# Copyright:: Copyright 2011-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" + +RSpec.describe ChefUtils::Mash do + it "should duplicate a simple key/value mash to a new mash" do + data = { x: "one", y: "two", z: "three" } + @orig = ChefUtils::Mash.new(data) + @copy = @orig.dup + expect(@copy.to_hash).to eq(ChefUtils::Mash.new(data).to_hash) + @copy[:x] = "four" + expect(@orig[:x]).to eq("one") + end + + it "should duplicate a mash with an array to a new mash" do + data = { x: "one", y: "two", z: [1, 2, 3] } + @orig = ChefUtils::Mash.new(data) + @copy = @orig.dup + expect(@copy.to_hash).to eq(ChefUtils::Mash.new(data).to_hash) + @copy[:z] << 4 + expect(@orig[:z]).to eq([1, 2, 3]) + end + + it "should duplicate a nested mash to a new mash" do + data = { x: "one", y: "two", z: ChefUtils::Mash.new({ a: [1, 2, 3] }) } + @orig = ChefUtils::Mash.new(data) + @copy = @orig.dup + expect(@copy.to_hash).to eq(ChefUtils::Mash.new(data).to_hash) + @copy[:z][:a] << 4 + expect(@orig[:z][:a]).to eq([1, 2, 3]) + end + + # add more! +end diff --git a/chef.gemspec b/chef.gemspec index 1340b749cc..b5c9d2e71c 100644 --- a/chef.gemspec +++ b/chef.gemspec @@ -16,6 +16,7 @@ Gem::Specification.new do |s| s.required_ruby_version = ">= 2.5.0" s.add_dependency "chef-config", "= #{Chef::VERSION}" + s.add_dependency "chef-utils", "= #{Chef::VERSION}" s.add_dependency "train-core", "~> 3.1" s.add_dependency "train-winrm", ">= 0.2.5" diff --git a/lib/chef/application.rb b/lib/chef/application.rb index 36cb4401c9..a793a91909 100644 --- a/lib/chef/application.rb +++ b/lib/chef/application.rb @@ -78,7 +78,7 @@ class Chef Chef::Application.fatal!("SIGTERM received, stopping", Chef::Exceptions::SigTerm.new) end - unless Chef::Platform.windows? + unless ChefUtils.windows? trap("QUIT") do logger.info("SIGQUIT received, call stack:\n " + caller.join("\n ")) end @@ -305,7 +305,7 @@ class Chef # win32-process gem exposes some form of :fork for Process # class. So we are separately ensuring that the platform we're # running on is not windows before forking. - chef_config[:client_fork] && Process.respond_to?(:fork) && !Chef::Platform.windows? + chef_config[:client_fork] && Process.respond_to?(:fork) && !ChefUtils.windows? end # Run chef-client once and then exit. If TERM signal is received, ignores the diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb index 890ecbd385..ea768a7fc6 100644 --- a/lib/chef/application/client.rb +++ b/lib/chef/application/client.rb @@ -33,7 +33,7 @@ class Chef::Application::Client < Chef::Application::Base long: "--config CONFIG", description: "The configuration file to use." - unless Chef::Platform.windows? + unless ChefUtils.windows? option :daemonize, short: "-d [WAIT]", long: "--daemonize [WAIT]", diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb index bffe970257..de34387fa4 100644 --- a/lib/chef/application/solo.rb +++ b/lib/chef/application/solo.rb @@ -36,7 +36,7 @@ class Chef::Application::Solo < Chef::Application::Base default: Chef::Config.platform_specific_path("#{Chef::Dist::CONF_DIR}/solo.rb"), description: "The configuration file to use." - unless Chef::Platform.windows? + unless ChefUtils.windows? option :daemonize, short: "-d", long: "--daemonize", diff --git a/lib/chef/chef_class.rb b/lib/chef/chef_class.rb index dccab726ed..dc87ebd271 100644 --- a/lib/chef/chef_class.rb +++ b/lib/chef/chef_class.rb @@ -1,6 +1,6 @@ # # Author:: Lamont Granquist () -# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# Copyright:: Copyright 2015-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -239,10 +239,5 @@ class Chef end end - # @api private Only for test dependency injection; not evenly implemented as yet. - def self.path_to(path) - path - end - reset! end diff --git a/lib/chef/chef_fs.rb b/lib/chef/chef_fs.rb index dbf02bd103..bb3408b781 100644 --- a/lib/chef/chef_fs.rb +++ b/lib/chef/chef_fs.rb @@ -53,7 +53,7 @@ require_relative "platform" class Chef module ChefFS def self.windows? - Chef::Platform.windows? + ChefUtils.windows? end end end diff --git a/lib/chef/chef_fs/file_pattern.rb b/lib/chef/chef_fs/file_pattern.rb index f4889fbd86..32c5e80bac 100644 --- a/lib/chef/chef_fs/file_pattern.rb +++ b/lib/chef/chef_fs/file_pattern.rb @@ -245,7 +245,7 @@ class Chef end def self.pattern_special_characters - if Chef::ChefFS.windows? + if ChefUtils.windows? @pattern_special_characters ||= /(\*\*|\*|\?|[\*\?\.\|\(\)\[\]\{\}\+\\\\\^\$])/ else # Unix also supports character regexes and backslashes 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 c99c689a71..974bbc91fd 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 @@ -86,7 +86,7 @@ class Chef # the symlink without removing the original contents if we # are running on windows # - if Chef::Platform.windows? + if ChefUtils.windows? Dir.rmdir proxy_cookbook_path 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 739a42b124..9a65f70f33 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 @@ -91,7 +91,7 @@ class Chef # the symlink without removing the original contents if we # are running on windows # - if Chef::Platform.windows? + if ChefUtils.windows? Dir.rmdir proxy_cookbook_path end end diff --git a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb index de1f071fb3..f156faf817 100644 --- a/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/chef_repository_file_system_root_dir.rb @@ -1,6 +1,6 @@ # # Author:: John Keiser () -# Copyright:: Copyright 2012-2016, Chef Software, Inc. +# Copyright:: Copyright 2012-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,7 +44,7 @@ require_relative "../../data_handler/role_data_handler" require_relative "../../data_handler/user_data_handler" require_relative "../../data_handler/group_data_handler" require_relative "../../data_handler/container_data_handler" -require_relative "../../../win32/security" if Chef::Platform.windows? +require_relative "../../../win32/security" if ChefUtils.windows? class Chef module ChefFS @@ -112,7 +112,7 @@ class Chef begin ::FileUtils.mkdir_p(path) ::FileUtils.chmod(0700, path) - if Chef::Platform.windows? + if ChefUtils.windows? all_mask = Chef::ReservedNames::Win32::API::Security::GENERIC_ALL administrators = Chef::ReservedNames::Win32::Security::SID.Administrators owner = Chef::ReservedNames::Win32::Security::SID.default_security_object_owner diff --git a/lib/chef/chef_fs/file_system/repository/nodes_dir.rb b/lib/chef/chef_fs/file_system/repository/nodes_dir.rb index 3edd442121..56118ffcd1 100644 --- a/lib/chef/chef_fs/file_system/repository/nodes_dir.rb +++ b/lib/chef/chef_fs/file_system/repository/nodes_dir.rb @@ -1,7 +1,7 @@ # # Author:: John Keiser () # Author:: Ho-Sheng Hsiao () -# Copyright:: Copyright 2012-2016, Chef Software Inc. +# Copyright:: Copyright 2012-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,7 @@ require_relative "node" require_relative "directory" require_relative "../exceptions" -require_relative "../../../win32/security" if Chef::Platform.windows? +require_relative "../../../win32/security" if ChefUtils.windows? class Chef module ChefFS @@ -35,7 +35,7 @@ class Chef def create_child(child_name, file_contents = nil) child = super File.chmod(0600, child.file_path) - if Chef::Platform.windows? + if ChefUtils.windows? read_mask = Chef::ReservedNames::Win32::API::Security::GENERIC_READ write_mask = Chef::ReservedNames::Win32::API::Security::GENERIC_WRITE administrators = Chef::ReservedNames::Win32::Security::SID.Administrators diff --git a/lib/chef/chef_fs/knife.rb b/lib/chef/chef_fs/knife.rb index 288acac10a..84301c92e4 100644 --- a/lib/chef/chef_fs/knife.rb +++ b/lib/chef/chef_fs/knife.rb @@ -18,7 +18,7 @@ require_relative "../knife" require "pathname" unless defined?(Pathname) -require "chef/dist" +require_relative "../dist" class Chef module ChefFS diff --git a/lib/chef/chef_fs/path_utils.rb b/lib/chef/chef_fs/path_utils.rb index c490f50c17..b894359e2a 100644 --- a/lib/chef/chef_fs/path_utils.rb +++ b/lib/chef/chef_fs/path_utils.rb @@ -58,7 +58,7 @@ class Chef end def self.regexp_path_separator - Chef::ChefFS.windows? ? '[\/\\\\]' : "/" + ChefUtils.windows? ? '[\/\\\\]' : "/" end # Given a server path, determines if it is absolute. @@ -103,7 +103,7 @@ class Chef # Compares two path fragments according to the case-sentitivity of the host platform. def self.os_path_eq?(left, right) - Chef::ChefFS.windows? ? left.casecmp(right) == 0 : left == right + ChefUtils.windows? ? left.casecmp(right) == 0 : left == right end # Given two general OS-dependent file paths, determines the relative path of the diff --git a/lib/chef/client.rb b/lib/chef/client.rb index 06370f5d07..9e1859eba8 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -20,7 +20,7 @@ require_relative "config" require_relative "mixin/params_validate" -require_relative "mixin/path_sanity" +require "chef-utils/dsl/path_sanity" unless defined?(ChefUtils::DSL::PathSanity) require_relative "log" require_relative "deprecated" require_relative "server_api" @@ -52,6 +52,7 @@ require_relative "policy_builder" require_relative "request_id" require_relative "platform/rebooter" require_relative "mixin/deprecation" +require "chef-utils" unless defined?(ChefUtils::CANARY) require "ohai" unless defined?(Ohai::System) require "rbconfig" require_relative "dist" @@ -62,8 +63,6 @@ class Chef # The main object in a Chef run. Preps a Chef::Node and Chef::RunContext, # syncs cookbooks if necessary, and triggers convergence. class Client - include Chef::Mixin::PathSanity - extend Chef::Mixin::Deprecation extend Forwardable @@ -251,7 +250,7 @@ class Chef logger.info "#{Chef::Dist::CLIENT.capitalize} pid: #{Process.pid}" logger.info "Targeting node: #{Chef::Config.target_mode.host}" if Chef::Config.target_mode? logger.debug("#{Chef::Dist::CLIENT.capitalize} request_id: #{request_id}") - enforce_path_sanity + ENV["PATH"] = ChefUtils::PathSanity.sanitized_path if Chef::Config[:enforce_path_sanity] if Chef::Config.target_mode? get_ohai_data_remotely @@ -749,7 +748,7 @@ class Chef # @api private # def do_windows_admin_check - if Chef::Platform.windows? + if ChefUtils.windows? logger.trace("Checking for administrator privileges....") if !has_admin_privileges? diff --git a/lib/chef/config.rb b/lib/chef/config.rb index 135ae622f7..6964d37abe 100644 --- a/lib/chef/config.rb +++ b/lib/chef/config.rb @@ -4,7 +4,7 @@ # Author:: AJ Christensen () # Author:: Mark Mzyk () # Author:: Kyle Goodwin () -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,6 +28,7 @@ require "chef-config/logger" ChefConfig.logger = Chef::Log require "chef-config/config" +require "chef-utils" unless defined?(ChefUtils::CANARY) require_relative "platform/query_helpers" # Ohai::Config defines its own log_level and log_location. When loaded, it will @@ -55,7 +56,7 @@ class Chef default :event_loggers do evt_loggers = [] - if ChefConfig.windows? && !Chef::Platform.windows_nano_server? + if ChefUtils.windows? && !Chef::Platform.windows_nano_server? evt_loggers << :win_evt end evt_loggers diff --git a/lib/chef/dsl/core.rb b/lib/chef/dsl/core.rb index a06adc28d0..f564dd0418 100644 --- a/lib/chef/dsl/core.rb +++ b/lib/chef/dsl/core.rb @@ -1,7 +1,7 @@ #-- # Author:: Adam Jacob () # Author:: Christopher Walters () -# Copyright:: Copyright 2008-2016 Chef Software, Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/lib/chef/dsl/platform_introspection.rb b/lib/chef/dsl/platform_introspection.rb index 3f79782798..c0856c15cc 100644 --- a/lib/chef/dsl/platform_introspection.rb +++ b/lib/chef/dsl/platform_introspection.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob () -# Copyright:: Copyright 2008-2018, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,13 +16,15 @@ # limitations under the License. # +require "chef-utils" unless defined?(ChefUtils::CANARY) + class Chef module DSL - # == Chef::DSL::PlatformIntrospection # Provides the DSL for platform-dependent switch logic, such as # #value_for_platform. module PlatformIntrospection + include ChefUtils # Implementation class for determining platform dependent values class PlatformDependentValue @@ -245,27 +247,16 @@ class Chef end end - # Shamelessly stolen from https://github.com/sethvargo/chef-sugar/blob/master/lib/chef/sugar/docker.rb - # Given a node object, returns whether the node is a docker container. - # - # === Parameters - # node:: [Chef::Node] The node to check. - # - # === Returns - # true:: if the current node is a docker container - # false:: if the current node is not a docker container - def docker?(node = run_context.nil? ? nil : run_context.node) - # Using "File.exist?('/.dockerinit') || File.exist?('/.dockerenv')" makes Travis sad, - # and that makes us sad too. - !!(node && node[:virtualization] && node[:virtualization][:systems] && - node[:virtualization][:systems][:docker] && node[:virtualization][:systems][:docker] == "guest") - end - # a simple helper to determine if we're on a windows release pre-2012 / 8 # @return [Boolean] Is the system older than Windows 8 / 2012 def older_than_win_2012_or_8?(node = run_context.nil? ? nil : run_context.node) node["platform_version"].to_f < 6.2 end + + # ^^^^^^ NOTE: PLEASE DO NOT CONTINUE TO ADD THESE KINDS OF PLATFORM_VERSION APIS WITHOUT ^^^^^^^ + # ^^^^^^ GOING THROUGH THE DESIGN REVIEW PROCESS AND ADDRESS THE EXISTING CHEF-SUGAR ONES ^^^^^^^ + # ^^^^^^ DO "THE HARD RIGHT THING" AND ADDRESS THE BROADER PROBLEM AND FIX IT ALL. ^^^^^^^ + end end end diff --git a/lib/chef/event_loggers/windows_eventlog.rb b/lib/chef/event_loggers/windows_eventlog.rb index 7111d975d5..3ace9e6f44 100644 --- a/lib/chef/event_loggers/windows_eventlog.rb +++ b/lib/chef/event_loggers/windows_eventlog.rb @@ -39,7 +39,7 @@ class Chef SOURCE = "#{Chef::Dist::PRODUCT}".freeze def self.available? - Chef::Platform.windows? + ChefUtils.windows? end def initialize diff --git a/lib/chef/file_content_management/deploy.rb b/lib/chef/file_content_management/deploy.rb index 1f158059e6..b048cfb454 100644 --- a/lib/chef/file_content_management/deploy.rb +++ b/lib/chef/file_content_management/deploy.rb @@ -1,6 +1,6 @@ # # Author:: Lamont Granquist () -# Copyright:: Copyright 2013-2016, Chef Software Inc. +# Copyright:: Copyright 2013-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,7 @@ require_relative "deploy/cp" require_relative "deploy/mv_unix" -if Chef::Platform.windows? +if ChefUtils.windows? require_relative "deploy/mv_windows" end @@ -27,7 +27,7 @@ class Chef class Deploy def self.strategy(atomic_update) if atomic_update - Chef::Platform.windows? ? MvWindows.new : MvUnix.new + ChefUtils.windows? ? MvWindows.new : MvUnix.new else Cp.new end diff --git a/lib/chef/file_content_management/deploy/mv_windows.rb b/lib/chef/file_content_management/deploy/mv_windows.rb index 132e9635d0..0043d5ce22 100644 --- a/lib/chef/file_content_management/deploy/mv_windows.rb +++ b/lib/chef/file_content_management/deploy/mv_windows.rb @@ -1,6 +1,6 @@ # # Author:: Lamont Granquist () -# Copyright:: Copyright 2013-2016, Chef Software Inc. +# Copyright:: Copyright 2013-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,7 @@ # require_relative "../../platform/query_helpers" -if Chef::Platform.windows? +if ChefUtils.windows? require_relative "../../win32/security" end diff --git a/lib/chef/file_content_management/tempfile.rb b/lib/chef/file_content_management/tempfile.rb index 3e57a131a6..0ec1563f97 100644 --- a/lib/chef/file_content_management/tempfile.rb +++ b/lib/chef/file_content_management/tempfile.rb @@ -67,7 +67,7 @@ class Chef basename = ::File.basename(@new_resource.path, tempfile_extension) # the leading "[.]chef-" here should be considered a public API and should not be changed basename.insert 0, "chef-" - basename.insert 0, "." unless Chef::Platform.windows? # dotfile if we're not on windows + basename.insert 0, "." unless ChefUtils.windows? # dotfile if we're not on windows basename.scrub end diff --git a/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb b/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb index 5141ed89fe..320a03c8aa 100644 --- a/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb +++ b/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb @@ -1,7 +1,7 @@ #-- # Author:: Daniel DeLeo () # Author:: Tyler Cloke () -# Copyright:: Copyright 2012-2016, Chef Software Inc. +# Copyright:: Copyright 2012-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -52,7 +52,7 @@ class Chef error_description.section("Template Context:", "#{exception.source_location}\n#{exception.source_listing}") end - if Chef::Platform.windows? + if ChefUtils.windows? require_relative "../../win32/security" unless Chef::ReservedNames::Win32::Security.has_admin_privileges? diff --git a/lib/chef/http.rb b/lib/chef/http.rb index 5546156031..2c28c8a871 100644 --- a/lib/chef/http.rb +++ b/lib/chef/http.rb @@ -519,7 +519,7 @@ class Chef content_length = response["Content-Length"] if tf.nil? tf = Tempfile.open("chef-rest") - if Chef::Platform.windows? + if ChefUtils.windows? tf.binmode # required for binary files on Windows platforms end end diff --git a/lib/chef/http/socketless_chef_zero_client.rb b/lib/chef/http/socketless_chef_zero_client.rb index b83fdbd41b..fc65b584dd 100644 --- a/lib/chef/http/socketless_chef_zero_client.rb +++ b/lib/chef/http/socketless_chef_zero_client.rb @@ -44,7 +44,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. require "chef_zero/server" -require "chef/dist" +require_relative "../dist" class Chef class HTTP diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb index bc25d48f90..e040de9d57 100644 --- a/lib/chef/knife.rb +++ b/lib/chef/knife.rb @@ -1,7 +1,7 @@ # # Author:: Adam Jacob () # Author:: Christopher Brown () -# Copyright:: Copyright 2009-2018, Chef Software Inc. +# Copyright:: Copyright 2009-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +20,7 @@ require "forwardable" unless defined?(Forwardable) require_relative "version" require "mixlib/cli" unless defined?(Mixlib::CLI) +require "chef-utils/dsl/path_sanity" unless defined?(ChefUtils::DSL::PathSanity) require_relative "workstation_config_loader" require_relative "mixin/convert_to_class_name" require_relative "mixin/path_sanity" @@ -39,7 +40,7 @@ class Chef Chef::HTTP::HTTPRequest.user_agent = "#{Chef::Dist::PRODUCT} Knife#{Chef::HTTP::HTTPRequest::UA_COMMON}" include Mixlib::CLI - include Chef::Mixin::PathSanity + include ChefUtils::DSL::PathSanity extend Chef::Mixin::ConvertToClassName extend Forwardable @@ -479,7 +480,7 @@ class Chef unless respond_to?(:run) ui.error "You need to add a #run method to your knife command before you can use it" end - enforce_path_sanity + ENV["PATH"] = sanitized_path if Chef::Config[:enforce_path_sanity] maybe_setup_fips Chef::LocalMode.with_server_connectivity do run diff --git a/lib/chef/local_mode.rb b/lib/chef/local_mode.rb index fb41cf8b27..8e83d8fa89 100644 --- a/lib/chef/local_mode.rb +++ b/lib/chef/local_mode.rb @@ -16,7 +16,7 @@ # limitations under the License. require_relative "config" -require_relative "monkey_patches/webrick-utils" if Chef::Platform.windows? +require_relative "monkey_patches/webrick-utils" if ChefUtils.windows? require_relative "dist" class Chef diff --git a/lib/chef/mash.rb b/lib/chef/mash.rb index 404d6d622f..64adfa8672 100644 --- a/lib/chef/mash.rb +++ b/lib/chef/mash.rb @@ -1,232 +1,21 @@ -# Copyright 2009-2016, Dan Kubb - -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: - -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -# --- -# --- - -# Some portions of blank.rb and mash.rb are verbatim copies of software -# licensed under the MIT license. That license is included below: - -# Copyright 2005-2016, David Heinemeier Hansson - -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: - -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -# This class has dubious semantics and we only have it so that people can write -# params[:key] instead of params['key']. -class Mash < Hash - - # @param constructor - # The default value for the mash. Defaults to an empty hash. - # - # @details [Alternatives] - # If constructor is a Hash, a new mash will be created based on the keys of - # the hash and no default value will be set. - def initialize(constructor = {}) - if constructor.is_a?(Hash) - super() - update(constructor) - else - super(constructor) - end - end - - # @param orig Mash being copied - # - # @return [Object] A new copied Mash - def initialize_copy(orig) - super - # Handle nested values - each do |k, v| - if v.is_a?(Mash) || v.is_a?(Array) - self[k] = v.dup - end - end - self - end - - # @param key The default value for the mash. Defaults to nil. - # - # @details [Alternatives] - # If key is a Symbol and it is a key in the mash, then the default value will - # be set to the value matching the key. - def default(key = nil) - if key.is_a?(Symbol) && include?(key = key.to_s) - self[key] - else - super - end - end - - alias_method :regular_writer, :[]= unless method_defined?(:regular_writer) - alias_method :regular_update, :update unless method_defined?(:regular_update) - - # @param key The key to set. - # @param value - # The value to set the key to. - # - # @see Mash#convert_key - # @see Mash#convert_value - def []=(key, value) - regular_writer(convert_key(key), convert_value(value)) - end - - # internal API for use by Chef's deep merge cache - # @api private - def internal_set(key, value) - regular_writer(key, convert_value(value)) - end - - # @param other_hash - # A hash to update values in the mash with. The keys and the values will be - # converted to Mash format. - # - # @return [Mash] The updated mash. - def update(other_hash) - other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } - self - end - - alias_method :merge!, :update - - # @param key The key to check for. This will be run through convert_key. - # - # @return [Boolean] True if the key exists in the mash. - def key?(key) - super(convert_key(key)) - end - - # def include? def has_key? def member? - alias_method :include?, :key? - alias_method :has_key?, :key? - alias_method :member?, :key? - - # @param key The key to fetch. This will be run through convert_key. - # @param *extras Default value. - # - # @return [Object] The value at key or the default value. - def fetch(key, *extras) - super(convert_key(key), *extras) - end - - # @param *indices - # The keys to retrieve values for. These will be run through +convert_key+. - # - # @return [Array] The values at each of the provided keys - def values_at(*indices) - indices.collect { |key| self[convert_key(key)] } - end - - # @param hash The hash to merge with the mash. - # - # @return [Mash] A new mash with the hash values merged in. - def merge(hash) - dup.update(hash) - end - - # @param key - # The key to delete from the mash.\ - def delete(key) - super(convert_key(key)) - end - - # @param *rejected 1, :two => 2, :three => 3 }.except(:one) - # #=> { "two" => 2, "three" => 3 } - def except(*keys) - super(*keys.map { |k| convert_key(k) }) - end - - # Used to provide the same interface as Hash. - # - # @return [Mash] This mash unchanged. - def stringify_keys!; self end - - # @return [Hash] The mash as a Hash with symbolized keys. - def symbolize_keys - h = Hash.new(default) - each { |key, val| h[key.to_sym] = val } - h - end - - # @return [Hash] The mash as a Hash with string keys. - def to_hash - Hash.new(default).merge(self) - end - - # @return [Mash] Convert a Hash into a Mash - # The input Hash's default value is maintained - def self.from_hash(hash) - mash = Mash.new(hash) - mash.default = hash.default - mash - end - - protected - - # @param key The key to convert. - # - # @param [Object] - # The converted key. If the key was a symbol, it will be converted to a - # string. - # - # @api private - def convert_key(key) - key.is_a?(Symbol) ? key.to_s : key - end - - # @param value The value to convert. - # - # @return [Object] - # The converted value. A Hash or an Array of hashes, will be converted to - # their Mash equivalents. - # - # @api private - def convert_value(value) - if value.class == Hash - Mash.from_hash(value) - elsif value.is_a?(Array) - value.collect { |e| convert_value(e) } - else - value - end - end -end +# +# Copyright:: Copyright 2018-2019, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "chef-utils/mash" unless defined?(ChefUtils::Mash) + +# For historical reasons we inject Mash directly into the top level class namespace +Mash = ChefUtils::Mash unless defined?(Mash) diff --git a/lib/chef/mixin/file_class.rb b/lib/chef/mixin/file_class.rb index 5c7e690db4..9ca7b0d770 100644 --- a/lib/chef/mixin/file_class.rb +++ b/lib/chef/mixin/file_class.rb @@ -2,7 +2,7 @@ # Author:: Mark Mzyk # Author:: Seth Chisamore # Author:: Bryan McLellan -# Copyright:: Copyright 2011-2016, Chef Software, Inc. +# Copyright:: Copyright 2011-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,7 @@ class Chef module FileClass def file_class - @host_os_file ||= if Chef::Platform.windows? + @host_os_file ||= if ChefUtils.windows? require_relative "../win32/file" Chef::ReservedNames::Win32::File else diff --git a/lib/chef/mixin/lazy_module_include.rb b/lib/chef/mixin/lazy_module_include.rb index 34e1fce4f1..4989493d9c 100644 --- a/lib/chef/mixin/lazy_module_include.rb +++ b/lib/chef/mixin/lazy_module_include.rb @@ -1,5 +1,5 @@ # -# Copyright:: Copyright 2011-2016, Chef Software Inc. +# Copyright:: Copyright 2011-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/lib/chef/mixin/path_sanity.rb b/lib/chef/mixin/path_sanity.rb index c441d0770a..de59c063e9 100644 --- a/lib/chef/mixin/path_sanity.rb +++ b/lib/chef/mixin/path_sanity.rb @@ -1,6 +1,6 @@ # # Author:: Seth Chisamore () -# Copyright:: Copyright 2011-2017, Chef Software Inc. +# Copyright:: Copyright 2011-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,49 +18,13 @@ class Chef module Mixin + # @ deprecated module PathSanity - def enforce_path_sanity(env = ENV) if Chef::Config[:enforce_path_sanity] - env["PATH"] = sanitized_path(env) - end - end - - def sanitized_path(env = ENV) - env_path = env["PATH"].nil? ? "" : env["PATH"].dup - path_separator = Chef::Platform.windows? ? ";" : ":" - # ensure the Ruby and Gem bindirs are included - # mainly for 'full-stack' Chef installs - new_paths = env_path.split(path_separator) - [ ruby_bindir, gem_bindir ].compact.each do |path| - new_paths = [ path ] + new_paths unless new_paths.include?(path) - end - sane_paths.each do |path| - new_paths << path unless new_paths.include?(path) - end - new_paths.join(path_separator).encode("utf-8", invalid: :replace, undef: :replace) - end - - private - - def sane_paths - @sane_paths ||= begin - if Chef::Platform.windows? - %w{} - else - %w{/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin} - end + env["PATH"] = ChefUtils::DSL::PathSanity.sanitized_path(env) end end - - def ruby_bindir - RbConfig::CONFIG["bindir"] - end - - def gem_bindir - Gem.bindir - end - end end end diff --git a/lib/chef/mixin/securable.rb b/lib/chef/mixin/securable.rb index d90b906f91..e6dd5043c8 100644 --- a/lib/chef/mixin/securable.rb +++ b/lib/chef/mixin/securable.rb @@ -49,7 +49,7 @@ class Chef end # Windows does not support the sticky or setuid bits - if Chef::Platform.windows? + if ChefUtils.windows? Integer(m) <= 0777 && Integer(m) >= 0 else Integer(m) <= 07777 && Integer(m) >= 0 diff --git a/lib/chef/mixin/shell_out.rb b/lib/chef/mixin/shell_out.rb index 5fc7c249b9..72aa82fc6c 100644 --- a/lib/chef/mixin/shell_out.rb +++ b/lib/chef/mixin/shell_out.rb @@ -1,6 +1,6 @@ #-- # Author:: Daniel DeLeo () -# Copyright:: Copyright 2010-2018, Chef Software Inc. +# Copyright:: Copyright 2010-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,12 +16,11 @@ # limitations under the License. require "mixlib/shellout" unless defined?(Mixlib::ShellOut::DEFAULT_READ_TIMEOUT) -require_relative "path_sanity" +require "chef-utils/dsl/path_sanity" unless defined?(ChefUtils::DSL::PathSanity) class Chef module Mixin module ShellOut - extend Chef::Mixin::PathSanity # PREFERRED APIS: # @@ -97,7 +96,7 @@ class Chef "LC_ALL" => Chef::Config[:internal_locale], "LANGUAGE" => Chef::Config[:internal_locale], "LANG" => Chef::Config[:internal_locale], - env_path => sanitized_path, + env_path => ChefUtils::DSL::PathSanity.sanitized_path, }.update(options[env_key] || {}) end options @@ -182,7 +181,7 @@ class Chef end def self.env_path - if Chef::Platform.windows? + if ChefUtils.windows? "Path" else "PATH" diff --git a/lib/chef/mixin/template.rb b/lib/chef/mixin/template.rb index 488a80acdb..d584d47d06 100644 --- a/lib/chef/mixin/template.rb +++ b/lib/chef/mixin/template.rb @@ -175,7 +175,7 @@ class Chef # potential issues for the applications that will consume # this template. - if Chef::Platform.windows? + if ChefUtils.windows? output = output.gsub(/\r?\n/, "\r\n") end diff --git a/lib/chef/mixin/train_helpers.rb b/lib/chef/mixin/train_helpers.rb deleted file mode 100644 index 1b031ab338..0000000000 --- a/lib/chef/mixin/train_helpers.rb +++ /dev/null @@ -1,60 +0,0 @@ -#-- -# Author:: Lamont Granquist -# Copyright:: Copyright 2019, 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 "stringio" unless defined?(StringIO) - -class Chef - module Mixin - module TrainHelpers - - # - # FIXME: generally these helpers all use the pattern of checking for target_mode? - # and then if it is we use train. That approach should likely be flipped so that - # even when we're running without target mode we still use inspec in its local - # mode. - # - - # Train wrapper around File.exist? to make it local mode aware. - # - # @param filename filename to check - # @return [Boolean] if it exists - # - def file_exist?(filename) - if Chef::Config.target_mode? - Chef.run_context.transport_connection.file(filename).exist? - else - File.exist?(filename) - end - end - - # XXX: modifications to the StringIO won't get written back - # FIXME: this is very experimental and may be a bad idea and may break at any time - # @api private - # - def file_open(*args, &block) - if Chef::Config.target_mode? - content = Chef.run_context.transport_connection.file(args[0]).content - string_io = StringIO.new content - yield string_io if block_given? - string_io - else - File.open(*args, &block) - end - end - end - end -end diff --git a/lib/chef/mixin/user_context.rb b/lib/chef/mixin/user_context.rb index bd73e818b0..82e8e91669 100644 --- a/lib/chef/mixin/user_context.rb +++ b/lib/chef/mixin/user_context.rb @@ -1,6 +1,6 @@ # # Author:: Adam Edwards () -# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# Copyright:: Copyright (c) 2016-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,7 @@ # limitations under the License. # -require_relative "../util/windows/logon_session" if Chef::Platform.windows? +require_relative "../util/windows/logon_session" if ChefUtils.windows? class Chef module Mixin @@ -26,7 +26,7 @@ class Chef # When authentication = :local, we use the credentials to create a logon session against the local system, and then try to access the files. # When authentication = :remote, we continue with the current user but pass the provided credentials to the remote system. def with_user_context(user, password, domain = nil, authentication = :remote, &block) - unless Chef::Platform.windows? + unless ChefUtils.windows? raise Exceptions::UnsupportedPlatform, "User context impersonation is supported only on the Windows platform" end diff --git a/lib/chef/mixin/which.rb b/lib/chef/mixin/which.rb index a51963b6c2..6f0d096c1b 100644 --- a/lib/chef/mixin/which.rb +++ b/lib/chef/mixin/which.rb @@ -1,6 +1,6 @@ #-- # Author:: Lamont Granquist -# Copyright:: Copyright 2010-2018, Chef Software Inc. +# Copyright:: Copyright 2010-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,49 +15,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +require "chef-utils/dsl/which" unless defined?(ChefUtils::DSL::Which) +require "chef-utils/dsl/path_sanity" unless defined?(ChefUtils::DSL::PathSanity) + class Chef module Mixin module Which - require_relative "../chef_class" - - def which(*cmds, extra_path: nil, &block) - where(*cmds, extra_path: extra_path, &block).first || false - end - - def where(*cmds, extra_path: nil, &block) - # NOTE: unnecessarily duplicates function of path_sanity - extra_path ||= [ "/bin", "/usr/bin", "/sbin", "/usr/sbin" ] - paths = env_path.split(File::PATH_SEPARATOR) + Array(extra_path) - cmds.map do |cmd| - paths.map do |path| - filename = Chef.path_to(File.join(path, cmd)) - filename if valid_executable?(filename, &block) - end.compact - end.flatten - end + include ChefUtils::DSL::Which private - # for test stubbing - def env_path - if Chef::Config.target_mode? - Chef.run_context.transport_connection.run_command("echo $PATH").stdout - else - ENV["PATH"] - end - end - - def valid_executable?(filename, &block) - is_executable = - if Chef::Config.target_mode? - connection = Chef.run_context.transport_connection - connection.file(filename).stat[:mode] & 1 && !connection.file(filename).directory? - else - File.executable?(filename) && !File.directory?(filename) - end - return false unless is_executable - - block ? yield(filename) : true + # we dep-inject path sanity into this API for historical reasons + # + # @api private + def __extra_path + ChefUtils::DSL::PathSanity.sane_paths end end end diff --git a/lib/chef/mixin/windows_architecture_helper.rb b/lib/chef/mixin/windows_architecture_helper.rb index cf05a682b5..87118dfe04 100644 --- a/lib/chef/mixin/windows_architecture_helper.rb +++ b/lib/chef/mixin/windows_architecture_helper.rb @@ -1,6 +1,6 @@ # # Author:: Adam Edwards () -# Copyright:: Copyright 2013-2016, Chef Software Inc. +# Copyright:: Copyright 2013-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,8 +18,8 @@ require_relative "../exceptions" require_relative "../platform/query_helpers" -require_relative "../win32/process" if Chef::Platform.windows? -require_relative "../win32/system" if Chef::Platform.windows? +require_relative "../win32/process" if ChefUtils.windows? +require_relative "../win32/system" if ChefUtils.windows? class Chef module Mixin @@ -89,7 +89,7 @@ class Chef end def is_i386_process_on_x86_64_windows? - if Chef::Platform.windows? + if ChefUtils.windows? Chef::ReservedNames::Win32::Process.is_wow64_process else false @@ -97,13 +97,13 @@ class Chef end def disable_wow64_file_redirection( node ) - if ( node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows? + if ( node_windows_architecture(node) == :x86_64) && ::ChefUtils.windows? Chef::ReservedNames::Win32::System.wow64_disable_wow64_fs_redirection end end def restore_wow64_file_redirection( node, original_redirection_state ) - if (node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows? + if (node_windows_architecture(node) == :x86_64) && ::ChefUtils.windows? Chef::ReservedNames::Win32::System.wow64_revert_wow64_fs_redirection(original_redirection_state) end end diff --git a/lib/chef/mixin/windows_env_helper.rb b/lib/chef/mixin/windows_env_helper.rb index 8036fa2bbe..012b789855 100644 --- a/lib/chef/mixin/windows_env_helper.rb +++ b/lib/chef/mixin/windows_env_helper.rb @@ -1,6 +1,6 @@ # # Author:: Adam Edwards () -# Copyright:: Copyright 2013-2016, Chef Software Inc. +# Copyright:: Copyright 2013-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,16 +19,16 @@ require_relative "../exceptions" require_relative "wide_string" require_relative "../platform/query_helpers" -require_relative "../win32/error" if Chef::Platform.windows? -require_relative "../win32/api/system" if Chef::Platform.windows? -require_relative "../win32/api/unicode" if Chef::Platform.windows? +require_relative "../win32/error" if ChefUtils.windows? +require_relative "../win32/api/system" if ChefUtils.windows? +require_relative "../win32/api/unicode" if ChefUtils.windows? class Chef module Mixin module WindowsEnvHelper include Chef::Mixin::WideString - if Chef::Platform.windows? + if ChefUtils.windows? include Chef::ReservedNames::Win32::API::System end diff --git a/lib/chef/node_map.rb b/lib/chef/node_map.rb index dd118c26cf..3c78d6cb9b 100644 --- a/lib/chef/node_map.rb +++ b/lib/chef/node_map.rb @@ -219,6 +219,11 @@ class Chef private + def platform_family_query_helper?(node, m) + method = "#{m}?".to_sym + ChefUtils::DSL::PlatformFamily.respond_to?(method) && ChefUtils::DSL::PlatformFamily.send(method, node) + end + # # Succeeds if: # - no negative matches (!value) @@ -235,11 +240,19 @@ class Chef # Split the blacklist and whitelist blacklist, whitelist = filter_values.partition { |v| v.is_a?(String) && v.start_with?("!") } - # If any blacklist value matches, we don't match - return false if blacklist.any? { |v| v[1..-1] == value } + if attribute == :platform_family + # If any blacklist value matches, we don't match + return false if blacklist.any? { |v| v[1..-1] == value || platform_family_query_helper?(node, v[1..-1]) } - # If the whitelist is empty, or anything matches, we match. - whitelist.empty? || whitelist.any? { |v| v == :all || v == value } + # If the whitelist is empty, or anything matches, we match. + whitelist.empty? || whitelist.any? { |v| v == :all || v == value || platform_family_query_helper?(node, v) } + else + # If any blacklist value matches, we don't match + return false if blacklist.any? { |v| v[1..-1] == value } + + # If the whitelist is empty, or anything matches, we match. + whitelist.empty? || whitelist.any? { |v| v == :all || v == value } + end end def matches_version_list?(node, filters, attribute) diff --git a/lib/chef/platform/query_helpers.rb b/lib/chef/platform/query_helpers.rb index ffcd7e0bd9..3cce4b5d2c 100644 --- a/lib/chef/platform/query_helpers.rb +++ b/lib/chef/platform/query_helpers.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob () -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,12 +16,14 @@ # limitations under the License. # +require "chef-utils" unless defined?(ChefUtils::CANARY) + class Chef class Platform class << self def windows? - ChefConfig.windows? + ChefUtils.windows? end def windows_nano_server? diff --git a/lib/chef/platform/rebooter.rb b/lib/chef/platform/rebooter.rb index ad17ffad8c..c3378e6313 100644 --- a/lib/chef/platform/rebooter.rb +++ b/lib/chef/platform/rebooter.rb @@ -35,7 +35,7 @@ class Chef reboot_info = node.run_context.reboot_info cmd = case - when Chef::Platform.windows? + when ChefUtils.windows? # should this do /f as well? do we then need a minimum delay to let apps quit? # Use explicit path to shutdown.exe, to protect against https://github.com/chef/chef/issues/5594 windows_shutdown_path = "#{ENV["SYSTEMROOT"]}/System32/shutdown.exe" diff --git a/lib/chef/platform/service_helpers.rb b/lib/chef/platform/service_helpers.rb index 851c3ebffc..a97a6f2ef4 100644 --- a/lib/chef/platform/service_helpers.rb +++ b/lib/chef/platform/service_helpers.rb @@ -1,6 +1,6 @@ # # Author:: Lamont Granquist () -# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# Copyright:: Copyright 2014-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,53 +17,22 @@ # require_relative "../chef_class" -require_relative "../mixin/train_helpers" +require "chef-utils" if defined?(ChefUtils::CANARY) class Chef class Platform + # @deprecated, use ChefUtils::DSL::Service instead (via the ChefUtils Universal DSL) class ServiceHelpers class << self - include Chef::Mixin::TrainHelpers - - # This helper is mostly used to sort out the mess of different - # linux mechanisms that can be used to start services. It does - # not necessarily need to linux-specific, but currently all our - # other service providers are narrowly platform-specific with no - # alternatives. - # - # NOTE: if a system has (for example) chkconfig installed then we - # should report that chkconfig is installed. The fact that a system - # may also have systemd installed does not mean that we do not - # report that systemd is also installed. This module is purely for - # discovery of all the alternatives, handling the priority of the - # different services is NOT a design concern of this module. - # def service_resource_providers providers = [] - if file_exist?(Chef.path_to("/usr/sbin/update-rc.d")) - providers << :debian - end - - if file_exist?(Chef.path_to("/usr/sbin/invoke-rc.d")) - providers << :invokercd - end - - if file_exist?(Chef.path_to("/sbin/initctl")) - providers << :upstart - end - - if file_exist?(Chef.path_to("/sbin/insserv")) - providers << :insserv - end - - if systemd_is_init? - providers << :systemd - end - - if file_exist?(Chef.path_to("/sbin/chkconfig")) - providers << :redhat - end + providers << :debian if ChefUtils::DSL::Service.debianrcd? + providers << :invokercd if ChefUtils::DSL::Service.invokercd? + providers << :upstart if ChefUtils::DSL::Service.upstart? + providers << :insserv if ChefUtils::DSL::Service.insserv? + providers << :systemd if ChefUtils.systemd? + providers << :redhat if ChefUtils::DSL::Service.redhatrcd? providers end @@ -71,54 +40,14 @@ class Chef def config_for_service(service_name) configs = [] - if file_exist?(Chef.path_to("/etc/init.d/#{service_name}")) - configs += %i{initd systemd} - end - - if file_exist?(Chef.path_to("/etc/init/#{service_name}.conf")) - configs << :upstart - end - - if file_exist?(Chef.path_to("/etc/xinetd.d/#{service_name}")) - configs << :xinetd - end - - if file_exist?(Chef.path_to("/etc/rc.d/#{service_name}")) - configs << :etc_rcd - end - - if file_exist?(Chef.path_to("/usr/local/etc/rc.d/#{service_name}")) - configs << :usr_local_etc_rcd - end - - if has_systemd_service_unit?(service_name) || has_systemd_unit?(service_name) - configs << :systemd - end + configs << :initd if ChefUtils::DSL::Service.service_script_exist?(:initd, service_name) + configs << :upstart if ChefUtils::DSL::Service.service_script_exist?(:upstart, service_name) + configs << :xinetd if ChefUtils::DSL::Service.service_script_exist?(:xinetd, service_name) + configs << :systemd if ChefUtils::DSL::Service.service_script_exist?(:systemd, service_name) + configs << :etc_rcd if ChefUtils::DSL::Service.service_script_exist?(:etc_rcd, service_name) configs end - - private - - def systemd_is_init? - file_exist?(Chef.path_to("/proc/1/comm")) && - file_open(Chef.path_to("/proc/1/comm")).gets.chomp == "systemd" - end - - def has_systemd_service_unit?(svc_name) - %w{ /etc /usr/lib /lib /run }.any? do |load_path| - file_exist?( - Chef.path_to("#{load_path}/systemd/system/#{svc_name.gsub(/@.*$/, "@")}.service") - ) - end - end - - def has_systemd_unit?(svc_name) - # TODO: stop supporting non-service units with service resource - %w{ /etc /usr/lib /lib /run }.any? do |load_path| - file_exist?(Chef.path_to("#{load_path}/systemd/system/#{svc_name}")) - end - end end end end diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb index b028f3f276..93d2578414 100644 --- a/lib/chef/provider.rb +++ b/lib/chef/provider.rb @@ -46,6 +46,8 @@ class Chef # includes the "core" DSL and not the "recipe" DSL by design include Chef::DSL::Core + # the class only gets the Universal DSL (no resource_collection at class parsing time) + extend Chef::DSL::Universal # supports the given resource and action (late binding) def self.supports?(resource, action) diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb index 7f4de1eaef..a2b956c282 100644 --- a/lib/chef/provider/file.rb +++ b/lib/chef/provider/file.rb @@ -453,7 +453,7 @@ class Chef end def load_resource_attributes_from_file(resource) - if Chef::Platform.windows? + if ChefUtils.windows? # This is a work around for CHEF-3554. # OC-6534: is tracking the real fix for this workaround. # Add support for Windows equivalent, or implicit resource diff --git a/lib/chef/provider/ifconfig/redhat.rb b/lib/chef/provider/ifconfig/redhat.rb index 9e34ec897b..44cfe31ea7 100644 --- a/lib/chef/provider/ifconfig/redhat.rb +++ b/lib/chef/provider/ifconfig/redhat.rb @@ -22,7 +22,7 @@ class Chef class Provider class Ifconfig class Redhat < Chef::Provider::Ifconfig - provides :ifconfig, platform_family: %w{fedora rhel amazon} + provides :ifconfig, platform_family: "fedora_derived" def initialize(new_resource, run_context) super(new_resource, run_context) diff --git a/lib/chef/provider/link.rb b/lib/chef/provider/link.rb index 7b17891900..f69d5cb01e 100644 --- a/lib/chef/provider/link.rb +++ b/lib/chef/provider/link.rb @@ -82,7 +82,7 @@ class Chef end def canonicalize(path) - Chef::Platform.windows? ? path.tr("/", '\\') : path + ChefUtils.windows? ? path.tr("/", '\\') : path end def action_create @@ -101,7 +101,7 @@ class Chef # However if the new symlink will point to a file and the current symlink is pointing at a # directory we want to throw an exception and calling ::File.unlink on the directory symlink # will throw the correct ones. - if Chef::Platform.windows? && ::File.directory?(new_resource.to) && + if ChefUtils.windows? && ::File.directory?(new_resource.to) && ::File.directory?(current_resource.target_file) converge_by("unlink existing windows symlink to dir at #{new_resource.target_file}") do ::Dir.unlink(new_resource.target_file) @@ -143,7 +143,7 @@ class Chef def action_delete if current_resource.to # Exists - if Chef::Platform.windows? && ::File.directory?(current_resource.target_file) + if ChefUtils.windows? && ::File.directory?(current_resource.target_file) converge_by("delete link to dir at #{new_resource.target_file}") do ::Dir.delete(new_resource.target_file) logger.info("#{new_resource} deleted") diff --git a/lib/chef/provider/mount/solaris.rb b/lib/chef/provider/mount/solaris.rb index 24f3a1f7ec..293d377079 100644 --- a/lib/chef/provider/mount/solaris.rb +++ b/lib/chef/provider/mount/solaris.rb @@ -27,7 +27,7 @@ class Chef class Mount # Mount Solaris File systems class Solaris < Chef::Provider::Mount - provides :mount, platform: %w{openindiana opensolaris nexentacore omnios solaris2 smartos} + provides :mount, platform_family: "solaris_based" extend Forwardable diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb index e32457cc0c..ca24ea2f5b 100644 --- a/lib/chef/provider/package/yum.rb +++ b/lib/chef/provider/package/yum.rb @@ -37,7 +37,7 @@ class Chef use_multipackage_api use_package_name_for_source - provides :package, platform_family: %w{fedora amazon rhel} + provides :package, platform_family: "fedora_derived" provides :yum_package diff --git a/lib/chef/provider/registry_key.rb b/lib/chef/provider/registry_key.rb index 5dcb9f1959..c7489caea8 100644 --- a/lib/chef/provider/registry_key.rb +++ b/lib/chef/provider/registry_key.rb @@ -36,7 +36,7 @@ class Chef include Chef::Mixin::Checksum def running_on_windows! - unless Chef::Platform.windows? + unless ChefUtils.windows? raise Chef::Exceptions::Win32NotWindows, "Attempt to manipulate the windows registry on a non-windows node" end end diff --git a/lib/chef/provider/remote_directory.rb b/lib/chef/provider/remote_directory.rb index e7d470916b..4d6039751d 100644 --- a/lib/chef/provider/remote_directory.rb +++ b/lib/chef/provider/remote_directory.rb @@ -111,7 +111,7 @@ class Chef next if managed_files.include?(file) if ::File.directory?(file) - if !Chef::Platform.windows? && file_class.symlink?(file.dup) + if !ChefUtils.windows? && file_class.symlink?(file.dup) # Unix treats dir symlinks as files purge_file(file) else @@ -208,7 +208,7 @@ class Chef # Set the sensitivity level res.sensitive(new_resource.sensitive) res.source(::File.join(source, relative_source_path)) - if Chef::Platform.windows? && files_rights + if ChefUtils.windows? && files_rights files_rights.each_pair do |permission, *args| res.rights(permission, *args) end @@ -244,7 +244,7 @@ class Chef def directory_resource(dir) res = Chef::Resource::Directory.new(dir, run_context) res.cookbook_name = resource_cookbook - if Chef::Platform.windows? && rights + if ChefUtils.windows? && rights # rights are only meant to be applied to the toppest-level directory; # Windows will handle inheritance. if dir == path diff --git a/lib/chef/provider/remote_file/fetcher.rb b/lib/chef/provider/remote_file/fetcher.rb index f007fe40db..93a5618d4a 100644 --- a/lib/chef/provider/remote_file/fetcher.rb +++ b/lib/chef/provider/remote_file/fetcher.rb @@ -1,7 +1,7 @@ # # Author:: Jesse Campbell () # Author:: Lamont Granquist () -# Copyright:: Copyright 2013-2016, Chef Software Inc. +# Copyright:: Copyright 2013-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,7 @@ class Chef def self.for_resource(uri, new_resource, current_resource) if network_share?(uri) - unless Chef::Platform.windows? + unless ChefUtils.windows? raise Exceptions::UnsupportedPlatform, "Fetching the file on a network share is supported only on the Windows platform. Please change your source: #{uri}" end diff --git a/lib/chef/provider/remote_file/local_file.rb b/lib/chef/provider/remote_file/local_file.rb index d4b71e24fa..f76c475b1e 100644 --- a/lib/chef/provider/remote_file/local_file.rb +++ b/lib/chef/provider/remote_file/local_file.rb @@ -41,7 +41,7 @@ class Chef def source_path @source_path ||= begin path = URI.unescape(uri.path) - Chef::Platform.windows? ? fix_windows_path(path) : path + ChefUtils.windows? ? fix_windows_path(path) : path end end diff --git a/lib/chef/provider/script.rb b/lib/chef/provider/script.rb index 4282825650..6124615eaa 100644 --- a/lib/chef/provider/script.rb +++ b/lib/chef/provider/script.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob () -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,7 @@ require "tempfile" unless defined?(Tempfile) require_relative "execute" -require_relative "../win32/security" if Chef::Platform.windows? +require_relative "../win32/security" if ChefUtils.windows? require "forwardable" unless defined?(Forwardable) class Chef @@ -63,7 +63,7 @@ class Chef end def set_owner_and_group - if Chef::Platform.windows? + if ChefUtils.windows? # And on Windows also this is a no-op if there is no user specified. grant_alternate_user_read_access else diff --git a/lib/chef/provider/service.rb b/lib/chef/provider/service.rb index af96e08b20..c9662b7ba4 100644 --- a/lib/chef/provider/service.rb +++ b/lib/chef/provider/service.rb @@ -1,7 +1,7 @@ # # Author:: AJ Christensen () # Author:: Davide Cavalca () -# Copyright:: Copyright 2008-2017, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,10 +18,13 @@ # require_relative "../provider" +require "chef-utils" unless defined?(ChefUtils::CANARY) class Chef class Provider class Service < Chef::Provider + include ChefUtils::DSL::Service + extend ChefUtils::DSL::Service def supports @supports ||= new_resource.supports.dup @@ -245,7 +248,7 @@ class Chef Chef.set_provider_priority_array :service, [ Systemd, Arch ], platform_family: "arch" Chef.set_provider_priority_array :service, [ Systemd, Gentoo ], platform_family: "gentoo" Chef.set_provider_priority_array :service, [ Systemd, Upstart, Insserv, Debian, Invokercd ], platform_family: "debian" - Chef.set_provider_priority_array :service, [ Systemd, Insserv, Redhat ], platform_family: %w{rhel fedora suse amazon} + Chef.set_provider_priority_array :service, [ Systemd, Insserv, Redhat ], platform_family: "rpm_based" end end end diff --git a/lib/chef/provider/service/arch.rb b/lib/chef/provider/service/arch.rb index bb209e22ae..ee6d3dfacd 100644 --- a/lib/chef/provider/service/arch.rb +++ b/lib/chef/provider/service/arch.rb @@ -23,7 +23,7 @@ class Chef::Provider::Service::Arch < Chef::Provider::Service::Init provides :service, platform_family: "arch" def self.supports?(resource, action) - Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:etc_rcd) + service_script_exist?(:etc_rcd, resource.service_name) end def initialize(new_resource, run_context) diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb index 9f48504d5e..19e8823fb6 100644 --- a/lib/chef/provider/service/debian.rb +++ b/lib/chef/provider/service/debian.rb @@ -1,6 +1,6 @@ # # Author:: AJ Christensen () -# Copyright:: Copyright 2008-2017, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,15 +22,15 @@ class Chef class Provider class Service class Debian < Chef::Provider::Service::Init - provides :service, platform_family: "debian" do |node| - Chef::Platform::ServiceHelpers.service_resource_providers.include?(:debian) + provides :service, platform_family: "debian" do + debianrcd? end UPDATE_RC_D_ENABLED_MATCHES = %r{/rc[\dS].d/S|not installed}i.freeze UPDATE_RC_D_PRIORITIES = %r{/rc([\dS]).d/([SK])(\d\d)}i.freeze def self.supports?(resource, action) - Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd) + service_script_exist?(:initd, resource.service_name) end def load_current_resource diff --git a/lib/chef/provider/service/init.rb b/lib/chef/provider/service/init.rb index 3911ae3216..a413aeb3f3 100644 --- a/lib/chef/provider/service/init.rb +++ b/lib/chef/provider/service/init.rb @@ -29,7 +29,7 @@ class Chef provides :service, os: "!windows" def self.supports?(resource, action) - Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd) + service_script_exist?(:initd, resource.service_name) end def initialize(new_resource, run_context) diff --git a/lib/chef/provider/service/insserv.rb b/lib/chef/provider/service/insserv.rb index 270ce2c274..be4c52b5ca 100644 --- a/lib/chef/provider/service/insserv.rb +++ b/lib/chef/provider/service/insserv.rb @@ -1,6 +1,6 @@ # # Author:: Bryan McLellan -# Copyright:: Copyright 2011-2017, Chef Software Inc. +# Copyright:: Copyright 2011-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,12 +24,12 @@ class Chef class Service class Insserv < Chef::Provider::Service::Init - provides :service, platform_family: %w{debian rhel fedora suse amazon} do |node| - Chef::Platform::ServiceHelpers.service_resource_providers.include?(:insserv) + provides :service, platform_family: %w{debian rhel fedora suse amazon} do + insserv? end def self.supports?(resource, action) - Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd) + service_script_exist?(:initd, resource.service_name) end def load_current_resource diff --git a/lib/chef/provider/service/invokercd.rb b/lib/chef/provider/service/invokercd.rb index a6e744ba8e..d22c91611b 100644 --- a/lib/chef/provider/service/invokercd.rb +++ b/lib/chef/provider/service/invokercd.rb @@ -1,6 +1,6 @@ # # Author:: AJ Christensen () -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,12 +23,12 @@ class Chef class Service class Invokercd < Chef::Provider::Service::Init - provides :service, platform_family: "debian", override: true do |node| - Chef::Platform::ServiceHelpers.service_resource_providers.include?(:invokercd) + provides :service, platform_family: "debian", override: true do + invokercd? end def self.supports?(resource, action) - Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd) + service_script_exist?(:initd, resource.service_name) end def initialize(new_resource, run_context) diff --git a/lib/chef/provider/service/redhat.rb b/lib/chef/provider/service/redhat.rb index 8751090d44..7e27bce290 100644 --- a/lib/chef/provider/service/redhat.rb +++ b/lib/chef/provider/service/redhat.rb @@ -1,6 +1,6 @@ # # Author:: AJ Christensen () -# Copyright:: Copyright 2008-2017, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,15 +28,15 @@ class Chef # @api private attr_accessor :current_run_levels - provides :service, platform_family: %w{rhel fedora suse amazon} do |node| - Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat) + provides :service, platform_family: "rpm_based" do + redhatrcd? end CHKCONFIG_ON = /\d:on/.freeze CHKCONFIG_MISSING = /No such/.freeze def self.supports?(resource, action) - Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:initd) + service_script_exist?(:initd, resource.service_name) end def initialize(new_resource, run_context) diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb index 3b190f0153..c19a3166a4 100644 --- a/lib/chef/provider/service/systemd.rb +++ b/lib/chef/provider/service/systemd.rb @@ -1,7 +1,7 @@ # # Author:: Stephen Haynes () # Author:: Davide Cavalca () -# Copyright:: Copyright 2011-2018, Chef Software Inc. +# Copyright:: Copyright 2011-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,13 +27,13 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple include Chef::Mixin::Which provides :service, os: "linux", target_mode: true do |node| - Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd) + systemd? end attr_accessor :status_check_success def self.supports?(resource, action) - Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:systemd) + service_script_exist?(:systemd, resource.service_name) end def load_current_resource diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb index 8b2db84f35..2feb0edd70 100644 --- a/lib/chef/provider/service/upstart.rb +++ b/lib/chef/provider/service/upstart.rb @@ -28,15 +28,15 @@ class Chef # to maintain a local state of service across restart's internal calls attr_accessor :upstart_service_running - provides :service, platform_family: "debian", override: true do |node| - Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart) + provides :service, platform_family: "debian", override: true do + upstart? end UPSTART_STATE_FORMAT = %r{\S+ \(?(start|stop)?\)? ?[/ ](\w+)}.freeze # Returns true if the configs for the service name has upstart variable def self.supports?(resource, action) - Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:upstart) + service_script_exist?(:upstart, resource.service_name) end # Upstart does more than start or stop a service, creating multiple 'states' [1] that a service can be in. diff --git a/lib/chef/provider/subversion.rb b/lib/chef/provider/subversion.rb index dd3ece4786..2f25ed5fc7 100644 --- a/lib/chef/provider/subversion.rb +++ b/lib/chef/provider/subversion.rb @@ -215,7 +215,7 @@ class Chef def svn_binary new_resource.svn_binary || - (Chef::Platform.windows? ? "svn.exe" : "svn") + (ChefUtils.windows? ? "svn.exe" : "svn") end def assert_target_directory_valid! diff --git a/lib/chef/provider/windows_path.rb b/lib/chef/provider/windows_path.rb index 859efdde38..865aefed20 100644 --- a/lib/chef/provider/windows_path.rb +++ b/lib/chef/provider/windows_path.rb @@ -1,6 +1,6 @@ # # Author:: Nimisha Sharad () -# Copyright:: Copyright 2008-2017, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,14 +16,14 @@ # limitations under the License. # -require_relative "../mixin/windows_env_helper" if Chef::Platform.windows? +require_relative "../mixin/windows_env_helper" if ChefUtils.windows? require_relative "../mixin/wide_string" require_relative "../exceptions" class Chef class Provider class WindowsPath < Chef::Provider - include Chef::Mixin::WindowsEnvHelper if Chef::Platform.windows? + include Chef::Mixin::WindowsEnvHelper if ChefUtils.windows? provides :windows_path diff --git a/lib/chef/provider/windows_task.rb b/lib/chef/provider/windows_task.rb index b94b6b875c..93347027a5 100644 --- a/lib/chef/provider/windows_task.rb +++ b/lib/chef/provider/windows_task.rb @@ -1,6 +1,6 @@ # # Author:: Nimisha Sharad () -# Copyright:: Copyright 2008-2018, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,11 @@ require_relative "../mixin/shell_out" require "rexml/document" unless defined?(REXML::Document) -require "iso8601" if Chef::Platform.windows? +require "iso8601" if ChefUtils.windows? require_relative "../mixin/powershell_out" require_relative "../provider" require_relative "../util/path_helper" -require "win32/taskscheduler" if Chef::Platform.windows? +require "win32/taskscheduler" if ChefUtils.windows? class Chef class Provider @@ -30,7 +30,7 @@ class Chef include Chef::Mixin::ShellOut include Chef::Mixin::PowershellOut - if Chef::Platform.windows? + if ChefUtils.windows? include Win32 provides :windows_task diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index a413e3e8d4..6c7214fdd9 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -59,6 +59,7 @@ class Chef extend Chef::Mixin::Provides include Chef::DSL::Universal + extend Chef::DSL::Universal # Bring in `property` and `property_type` include Chef::Mixin::Properties diff --git a/lib/chef/resource/build_essential.rb b/lib/chef/resource/build_essential.rb index 105173bc88..0fb06486d9 100644 --- a/lib/chef/resource/build_essential.rb +++ b/lib/chef/resource/build_essential.rb @@ -1,5 +1,5 @@ # -# Copyright:: 2008-2019, Chef Software, Inc. +# Copyright:: 2008-2019, Chef Software Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -52,7 +52,7 @@ class Chef case node["platform_family"] when "debian" package %w{ autoconf binutils-doc bison build-essential flex gettext ncurses-dev } - when "amazon", "fedora", "rhel" + when fedora_derived? package %w{ autoconf bison flex gcc gcc-c++ gettext kernel-devel make m4 ncurses-devel patch } # Ensure GCC 4 is available on older pre-6 EL diff --git a/lib/chef/resource/file.rb b/lib/chef/resource/file.rb index 57dc6c42f9..a8e3bd3a88 100644 --- a/lib/chef/resource/file.rb +++ b/lib/chef/resource/file.rb @@ -32,7 +32,7 @@ class Chef description "Use the file resource to manage files directly on a node." - if Platform.windows? + if ChefUtils.windows? # Use Windows rights instead of standard *nix permissions state_attrs :checksum, :rights, :deny_rights else diff --git a/lib/chef/resource/link.rb b/lib/chef/resource/link.rb index b6b2601b6e..df4ab81dd1 100644 --- a/lib/chef/resource/link.rb +++ b/lib/chef/resource/link.rb @@ -1,7 +1,7 @@ # # Author:: Adam Jacob () # Author:: Tyler Cloke () -# Copyright:: Copyright 2008-2018, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -79,7 +79,7 @@ class Chef # On certain versions of windows links are not supported. Make # sure we are not on such a platform. def verify_links_supported! - if Chef::Platform.windows? + if ChefUtils.windows? require_relative "../win32/file" begin Chef::ReservedNames::Win32::File.verify_links_supported! diff --git a/lib/chef/resource/remote_directory.rb b/lib/chef/resource/remote_directory.rb index 0d26d169b3..d05c719ac1 100644 --- a/lib/chef/resource/remote_directory.rb +++ b/lib/chef/resource/remote_directory.rb @@ -1,7 +1,7 @@ # # Author:: Adam Jacob () # Author:: Tyler Cloke () -# Copyright:: Copyright 2008-2018, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,7 +37,7 @@ class Chef @delete = false end - if Chef::Platform.windows? + if ChefUtils.windows? # create a second instance of the 'rights' attribute (property) rights_attribute(:files_rights) end diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb index 89f2a7184b..46054f21d9 100644 --- a/lib/chef/resource/service.rb +++ b/lib/chef/resource/service.rb @@ -1,7 +1,7 @@ # # Author:: AJ Christensen () # Author:: Tyler Cloke () -# Copyright:: Copyright 2008-2018, Chef Software Inc. +# Copyright:: Copyright 2008-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,6 +17,7 @@ # limitations under the License. # +require "chef-utils/dsl/service" unless defined?(ChefUtils::DSL::Service) require_relative "../resource" require "shellwords" unless defined?(Shellwords) require_relative "../dist" @@ -24,7 +25,11 @@ require_relative "../dist" class Chef class Resource class Service < Chef::Resource + include ChefUtils::DSL::Service + extend ChefUtils::DSL::Service + provides :service, target_mode: true + identity_attr :service_name description "Use the service resource to manage a service." diff --git a/lib/chef/resource/solaris_package.rb b/lib/chef/resource/solaris_package.rb index 163621ec5b..c6cda0ef36 100644 --- a/lib/chef/resource/solaris_package.rb +++ b/lib/chef/resource/solaris_package.rb @@ -1,7 +1,7 @@ # # Author:: Toomas Pelberg () # Author:: Prabhu Das () -# Copyright:: Copyright 2013-2016, Chef Software Inc. +# Copyright:: Copyright 2013-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/lib/chef/resource/yum_package.rb b/lib/chef/resource/yum_package.rb index ce9a5654b5..d1d63e64c8 100644 --- a/lib/chef/resource/yum_package.rb +++ b/lib/chef/resource/yum_package.rb @@ -23,7 +23,7 @@ class Chef class Resource class YumPackage < Chef::Resource::Package resource_name :yum_package - provides :package, platform_family: %w{rhel fedora amazon} + provides :package, platform_family: "fedora_derived" description "Use the yum_package resource to install, upgrade, and remove packages with Yum"\ " for the Red Hat and CentOS platforms. The yum_package resource is able to resolve"\ diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb index d849679680..70f403ddb6 100644 --- a/lib/chef/run_context.rb +++ b/lib/chef/run_context.rb @@ -635,7 +635,7 @@ class Chef # @return [Train::Plugins::Transport::BaseConnection] # def transport_connection - @transport_connection ||= transport.connection + @transport_connection ||= transport&.connection end # diff --git a/lib/chef/run_lock.rb b/lib/chef/run_lock.rb index 5f9b1ae06f..b25fb567d0 100644 --- a/lib/chef/run_lock.rb +++ b/lib/chef/run_lock.rb @@ -1,6 +1,6 @@ # # Author:: Daniel DeLeo () -# Copyright:: Copyright 2012-2016, Chef Software Inc. +# Copyright:: Copyright 2012-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,7 @@ require_relative "mixin/create_path" require "fcntl" -if Chef::Platform.windows? +if ChefUtils.windows? require_relative "win32/mutex" end require_relative "config" @@ -97,7 +97,7 @@ class Chef # def wait Chef::Log.warn("#{Chef::Dist::PRODUCT} #{runpid} is running, will wait for it to finish and then run.") - if Chef::Platform.windows? + if ChefUtils.windows? mutex.wait else runlock.flock(File::LOCK_EX) @@ -116,7 +116,7 @@ class Chef # Release the system-wide lock. def release if runlock - if Chef::Platform.windows? + if ChefUtils.windows? mutex.release else runlock.flock(File::LOCK_UN) @@ -138,7 +138,7 @@ class Chef # @api private solely for race condition tests def acquire_lock - if Chef::Platform.windows? + if ChefUtils.windows? acquire_win32_mutex else # If we support FD_CLOEXEC, then use it. diff --git a/lib/chef/train_transport.rb b/lib/chef/train_transport.rb index 6a82e8620e..55fc9068fa 100644 --- a/lib/chef/train_transport.rb +++ b/lib/chef/train_transport.rb @@ -1,5 +1,5 @@ # Author:: Bryan McLellan -# Copyright:: Copyright 2018, Chef Software, Inc. +# Copyright:: Copyright 2018-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -92,6 +92,8 @@ class Chef end def self.build_transport(logger = Chef::Log.with_child(subsystem: "transport")) + return nil unless Chef::Config.target_mode? + # TODO: Consider supporting parsing the protocol from a URI passed to `--target` # train_config = {} diff --git a/lib/chef/util/powershell/ps_credential.rb b/lib/chef/util/powershell/ps_credential.rb index 25159e3486..23e8572a61 100644 --- a/lib/chef/util/powershell/ps_credential.rb +++ b/lib/chef/util/powershell/ps_credential.rb @@ -1,7 +1,7 @@ # # Author:: Jay Mundrawala () # -# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# Copyright:: Copyright 2015-2019, Chef Software Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ # limitations under the License. # -require_relative "../../win32/crypto" if Chef::Platform.windows? +require_relative "../../win32/crypto" if ChefUtils.windows? class Chef::Util::Powershell class PSCredential diff --git a/lib/chef/util/selinux.rb b/lib/chef/util/selinux.rb index 70fa9298b8..7e477b016c 100644 --- a/lib/chef/util/selinux.rb +++ b/lib/chef/util/selinux.rb @@ -3,7 +3,7 @@ # Author:: Kevin Keane # Author:: Lamont Granquist () # -# Copyright:: Copyright 2011-2016, Chef Software Inc. +# Copyright:: Copyright 2011-2019, Chef Software Inc. # Copyright:: Copyright 2013-2016, North County Tech Center, LLC # # License:: Apache License, Version 2.0 diff --git a/lib/chef/util/windows/logon_session.rb b/lib/chef/util/windows/logon_session.rb index b7db9da51c..b24104d61b 100644 --- a/lib/chef/util/windows/logon_session.rb +++ b/lib/chef/util/windows/logon_session.rb @@ -1,7 +1,7 @@ # # Author:: Adam Edwards () # -# Copyright:: Copyright (c) 2015 Chef Software, Inc. +# Copyright:: Copyright (c) 2015-2019, Chef Software Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ # limitations under the License. # -require_relative "../../win32/api/security" if Chef::Platform.windows? +require_relative "../../win32/api/security" if ChefUtils.windows? require_relative "../../mixin/wide_string" class Chef diff --git a/lib/chef/win32/eventlog.rb b/lib/chef/win32/eventlog.rb index ca15acf3d8..da6f487ab1 100644 --- a/lib/chef/win32/eventlog.rb +++ b/lib/chef/win32/eventlog.rb @@ -1,7 +1,7 @@ # # Author:: Jay Mundrawala () # -# Copyright:: Copyright 2015-2016, Chef Software, Inc. +# Copyright:: Copyright 2015-2019, Chef Software Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ # limitations under the License. # -if Chef::Platform.windows? +if ChefUtils.windows? unless defined? Chef::Win32EventLogLoaded if defined? Windows::Constants %i{INFINITE WAIT_FAILED FORMAT_MESSAGE_IGNORE_INSERTS ERROR_INSUFFICIENT_BUFFER}.each do |c| diff --git a/omnibus/config/projects/chef.rb b/omnibus/config/projects/chef.rb index 6c0a5f112b..b3768a58a5 100644 --- a/omnibus/config/projects/chef.rb +++ b/omnibus/config/projects/chef.rb @@ -81,7 +81,7 @@ package :deb do compression_type :xz end -proj_to_work_around_cleanroom = self +proj_to_work_around_cleanroom = self # wat voodoo hackery is this? package :pkg do identifier "com.getchef.pkg.#{proj_to_work_around_cleanroom.name}" signing_identity "Developer ID Installer: Chef Software, Inc. (EU3VF8YLX2)" diff --git a/spec/functional/event_loggers/windows_eventlog_spec.rb b/spec/functional/event_loggers/windows_eventlog_spec.rb index ca15d3e38d..d6c4c481f3 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? +if ChefUtils.windows? require "win32/eventlog" include Win32 end diff --git a/spec/functional/mixin/user_context_spec.rb b/spec/functional/mixin/user_context_spec.rb index b6b8b057d5..0fe5f08824 100644 --- a/spec/functional/mixin/user_context_spec.rb +++ b/spec/functional/mixin/user_context_spec.rb @@ -17,8 +17,8 @@ require "spec_helper" -require "chef/win32/api" if Chef::Platform.windows? -require "chef/win32/api/error" if Chef::Platform.windows? +require "chef/win32/api" if ChefUtils.windows? +require "chef/win32/api/error" if ChefUtils.windows? require "chef/mixin/user_context" describe Chef::Mixin::UserContext, windows_only: true do diff --git a/spec/functional/rebooter_spec.rb b/spec/functional/rebooter_spec.rb index 747978cc96..689570c580 100644 --- a/spec/functional/rebooter_spec.rb +++ b/spec/functional/rebooter_spec.rb @@ -72,7 +72,7 @@ describe Chef::Platform::Rebooter do shared_context "test a reboot method" do def test_rebooter_method(method_sym, is_windows, is_solaris, expected_reboot_str) - allow(ChefConfig).to receive(:windows?).and_return(is_windows) + allow(ChefUtils).to receive(:windows?).and_return(is_windows) node.automatic["os"] = node.automatic["platform"] = node.automatic["platform_family"] = "solaris2" if is_solaris expect(rebooter).to receive(:shell_out!).once.with(expected_reboot_str) expect(rebooter).to receive(:raise).with(Chef::Exceptions::Reboot) diff --git a/spec/functional/resource/cookbook_file_spec.rb b/spec/functional/resource/cookbook_file_spec.rb index 6e964a6499..37d31188ac 100644 --- a/spec/functional/resource/cookbook_file_spec.rb +++ b/spec/functional/resource/cookbook_file_spec.rb @@ -68,11 +68,11 @@ describe Chef::Resource::CookbookFile do let(:path) { File.join(windows_non_temp_dir, make_tmpname(file_base)) } before do - FileUtils.mkdir_p(windows_non_temp_dir) if Chef::Platform.windows? + FileUtils.mkdir_p(windows_non_temp_dir) if ChefUtils.windows? end after do - FileUtils.rm_r(windows_non_temp_dir) if Chef::Platform.windows? && File.exists?(windows_non_temp_dir) + FileUtils.rm_r(windows_non_temp_dir) if ChefUtils.windows? && File.exists?(windows_non_temp_dir) end end diff --git a/spec/functional/resource/template_spec.rb b/spec/functional/resource/template_spec.rb index feef97dd27..63a950db95 100644 --- a/spec/functional/resource/template_spec.rb +++ b/spec/functional/resource/template_spec.rb @@ -203,7 +203,7 @@ describe Chef::Resource::Template do it "output should contain platform's line endings" do resource.run_action(:create) binread(path).each_line do |line| - expect(line).to end_with(Chef::Platform.windows? ? "\r\n" : "\n") + expect(line).to end_with(ChefUtils.windows? ? "\r\n" : "\n") end end end diff --git a/spec/functional/win32/crypto_spec.rb b/spec/functional/win32/crypto_spec.rb index 70d3f42cfb..ab51e4d681 100644 --- a/spec/functional/win32/crypto_spec.rb +++ b/spec/functional/win32/crypto_spec.rb @@ -17,7 +17,7 @@ # require "spec_helper" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/win32/crypto" end diff --git a/spec/functional/win32/security_spec.rb b/spec/functional/win32/security_spec.rb index a72088a079..3eb7bedd48 100644 --- a/spec/functional/win32/security_spec.rb +++ b/spec/functional/win32/security_spec.rb @@ -19,7 +19,7 @@ require "spec_helper" require "mixlib/shellout" require "chef/mixin/user_context" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/win32/security" end diff --git a/spec/functional/win32/service_manager_spec.rb b/spec/functional/win32/service_manager_spec.rb index abc8118835..bb8ed54c0e 100644 --- a/spec/functional/win32/service_manager_spec.rb +++ b/spec/functional/win32/service_manager_spec.rb @@ -17,7 +17,7 @@ # require "spec_helper" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/application/windows_service_manager" end diff --git a/spec/functional/win32/sid_spec.rb b/spec/functional/win32/sid_spec.rb index eac62d88b6..bdc570dfe6 100644 --- a/spec/functional/win32/sid_spec.rb +++ b/spec/functional/win32/sid_spec.rb @@ -17,12 +17,12 @@ # require "spec_helper" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/win32/security" end describe "Chef::ReservedNames::Win32::SID", :windows_only do - if Chef::Platform.windows? + if ChefUtils.windows? SID ||= Chef::ReservedNames::Win32::Security::SID end diff --git a/spec/functional/win32/version_info_spec.rb b/spec/functional/win32/version_info_spec.rb index b5570732a0..988339fd7a 100644 --- a/spec/functional/win32/version_info_spec.rb +++ b/spec/functional/win32/version_info_spec.rb @@ -17,7 +17,7 @@ # require "spec_helper" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/win32/file/version_info" end diff --git a/spec/functional/win32/versions_spec.rb b/spec/functional/win32/versions_spec.rb index 19bd0e3875..9ce21c49f9 100644 --- a/spec/functional/win32/versions_spec.rb +++ b/spec/functional/win32/versions_spec.rb @@ -17,7 +17,7 @@ # require "spec_helper" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/win32/version" end diff --git a/spec/integration/knife/config_get_profile_spec.rb b/spec/integration/knife/config_get_profile_spec.rb index e97b24b869..d17d572f13 100644 --- a/spec/integration/knife/config_get_profile_spec.rb +++ b/spec/integration/knife/config_get_profile_spec.rb @@ -50,7 +50,7 @@ describe "knife config get-profile", :workstation do ENV["KNIFE_HOME"] = old_knife_home ENV["HOME"] = old_home Dir.chdir(old_wd) - ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd + ENV[ChefUtils.windows? ? "CD" : "PWD"] = Dir.pwd ChefConfig::PathHelper.per_tool_home_environment = nil end end @@ -60,7 +60,7 @@ describe "knife config get-profile", :workstation do # because it has to run after the before set in the "with a chef repo" shared context. directory("repo") Dir.chdir(path_to("repo")) - ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd + ENV[ChefUtils.windows? ? "CD" : "PWD"] = Dir.pwd ENV["HOME"] = path_to(".") end diff --git a/spec/integration/knife/config_get_spec.rb b/spec/integration/knife/config_get_spec.rb index 83150a39b8..7719ee2bd0 100644 --- a/spec/integration/knife/config_get_spec.rb +++ b/spec/integration/knife/config_get_spec.rb @@ -54,7 +54,7 @@ describe "knife config get", :workstation do ENV["KNIFE_HOME"] = old_knife_home ENV["HOME"] = old_home Dir.chdir(old_wd) - ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd + ENV[ChefUtils.windows? ? "CD" : "PWD"] = Dir.pwd ChefConfig::PathHelper.per_tool_home_environment = nil end end @@ -64,7 +64,7 @@ describe "knife config get", :workstation do # because it has to run after the before set in the "with a chef repo" shared context. directory("repo") Dir.chdir(path_to("repo")) - ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd + ENV[ChefUtils.windows? ? "CD" : "PWD"] = Dir.pwd ENV["HOME"] = path_to(".") end diff --git a/spec/integration/knife/config_list_profiles_spec.rb b/spec/integration/knife/config_list_profiles_spec.rb index 044b50b5be..7ac4ef755e 100644 --- a/spec/integration/knife/config_list_profiles_spec.rb +++ b/spec/integration/knife/config_list_profiles_spec.rb @@ -44,7 +44,7 @@ describe "knife config list-profiles", :workstation do ensure ENV["HOME"] = old_home Dir.chdir(old_wd) - ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd + ENV[ChefUtils.windows? ? "CD" : "PWD"] = Dir.pwd end end @@ -53,7 +53,7 @@ describe "knife config list-profiles", :workstation do # because it has to run after the before set in the "with a chef repo" shared context. directory("repo") Dir.chdir(path_to("repo")) - ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd + ENV[ChefUtils.windows? ? "CD" : "PWD"] = Dir.pwd ENV["HOME"] = path_to(".") end diff --git a/spec/integration/knife/config_use_profile_spec.rb b/spec/integration/knife/config_use_profile_spec.rb index a021dbbe6f..4ea9012212 100644 --- a/spec/integration/knife/config_use_profile_spec.rb +++ b/spec/integration/knife/config_use_profile_spec.rb @@ -51,7 +51,7 @@ describe "knife config use-profile", :workstation do ENV["KNIFE_HOME"] = old_knife_home ENV["HOME"] = old_home Dir.chdir(old_wd) - ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd + ENV[ChefUtils.windows? ? "CD" : "PWD"] = Dir.pwd ChefConfig::PathHelper.per_tool_home_environment = nil end end @@ -61,7 +61,7 @@ describe "knife config use-profile", :workstation do # because it has to run after the before set in the "with a chef repo" shared context. directory("repo") Dir.chdir(path_to("repo")) - ENV[ChefConfig.windows? ? "CD" : "PWD"] = Dir.pwd + ENV[ChefUtils.windows? ? "CD" : "PWD"] = Dir.pwd ENV["HOME"] = path_to(".") end diff --git a/spec/integration/knife/list_spec.rb b/spec/integration/knife/list_spec.rb index 830dd0e428..9689c9e6c8 100644 --- a/spec/integration/knife/list_spec.rb +++ b/spec/integration/knife/list_spec.rb @@ -466,7 +466,7 @@ describe "knife list", :workstation do end end - when_the_repository "has a cookbooks directory and a symlinked cookbooks directory", skip: (Chef::Platform.windows?) do + when_the_repository "has a cookbooks directory and a symlinked cookbooks directory", skip: (ChefUtils.windows?) do before do directory "cookbooks" symlink "symlinked", "cookbooks" @@ -503,7 +503,7 @@ describe "knife list", :workstation do end end - when_the_repository "has a real_cookbooks directory and a cookbooks symlink to it", skip: (Chef::Platform.windows?) do + when_the_repository "has a real_cookbooks directory and a cookbooks symlink to it", skip: (ChefUtils.windows?) do before do directory "real_cookbooks" symlink "cookbooks", "real_cookbooks" diff --git a/spec/integration/solo/solo_spec.rb b/spec/integration/solo/solo_spec.rb index 451943e225..c62b2ec6b0 100644 --- a/spec/integration/solo/solo_spec.rb +++ b/spec/integration/solo/solo_spec.rb @@ -4,7 +4,7 @@ require "chef/run_lock" require "chef/config" require "timeout" require "fileutils" -require "chef/win32/security" if Chef::Platform.windows? +require "chef/win32/security" if ChefUtils.windows? require "chef/dist" describe Chef::Dist::SOLOEXEC do diff --git a/spec/support/matchers/leak.rb b/spec/support/matchers/leak.rb index 5f22c1c151..6b456af934 100644 --- a/spec/support/matchers/leak.rb +++ b/spec/support/matchers/leak.rb @@ -60,7 +60,7 @@ module Matchers def profiler @profiler ||= begin - if Chef::Platform.windows? + if ChefUtils.windows? require File.join(File.dirname(__FILE__), "..", "platforms", "prof", "win32") RSpec::Prof::Win32::Profiler.new else diff --git a/spec/support/mock/platform.rb b/spec/support/mock/platform.rb index 2cf605c741..b0a6258276 100644 --- a/spec/support/mock/platform.rb +++ b/spec/support/mock/platform.rb @@ -6,7 +6,7 @@ # testing code that mixes in platform specific modules like +Chef::Mixin::Securable+ # or +Chef::FileAccessControl+ def platform_mock(platform = :unix) - allow(ChefConfig).to receive(:windows?).and_return(platform == :windows ? true : false) + allow(ChefUtils).to receive(:windows?).and_return(platform == :windows ? true : false) ENV["SYSTEMDRIVE"] = (platform == :windows ? "C:" : nil) if platform == :windows diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb index 3ac657d84e..7c2edc426d 100644 --- a/spec/support/platform_helpers.rb +++ b/spec/support/platform_helpers.rb @@ -35,6 +35,8 @@ def ruby_32bit? end def windows? + # NOTE this deliberately does not use ChefUtils.windows? because otherwise it would + # pick up the node out of tests, while this tests the hosts running the specs. !!(RUBY_PLATFORM =~ /mswin|mingw|windows/) end diff --git a/spec/support/shared/integration/integration_helper.rb b/spec/support/shared/integration/integration_helper.rb index f0dfd1dc43..af57e21c73 100644 --- a/spec/support/shared/integration/integration_helper.rb +++ b/spec/support/shared/integration/integration_helper.rb @@ -128,7 +128,7 @@ module IntegrationSupport # TODO: "force" actually means "silence all exceptions". this # silences a weird permissions error on Windows that we should track # down, but for now there's no reason for it to blow up our CI. - FileUtils.remove_entry_secure(@repository_dir, force = Chef::Platform.windows?) + FileUtils.remove_entry_secure(@repository_dir, force = ChefUtils.windows?) ensure @repository_dir = nil end diff --git a/spec/support/shared/integration/knife_support.rb b/spec/support/shared/integration/knife_support.rb index 07d95f17cc..8de665c370 100644 --- a/spec/support/shared/integration/knife_support.rb +++ b/spec/support/shared/integration/knife_support.rb @@ -181,7 +181,7 @@ module KnifeSupport expect(stderr_actual).to eq(expected[:stderr]) end stdout_actual = @stdout - if Chef::Platform.windows? + if ChefUtils.windows? stderr_actual = stderr_actual.gsub("\r\n", "\n") stdout_actual = stdout_actual.gsub("\r\n", "\n") end diff --git a/spec/support/shared/unit/provider/file.rb b/spec/support/shared/unit/provider/file.rb index 2771a371d4..36b19675c2 100644 --- a/spec/support/shared/unit/provider/file.rb +++ b/spec/support/shared/unit/provider/file.rb @@ -1,6 +1,6 @@ # # Author:: Lamont Granquist () -# Copyright:: Copyright 2013-2016, Chef Software, Inc. +# Copyright:: Copyright 2013-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -256,7 +256,7 @@ shared_examples_for Chef::Provider::File do context "examining file security metadata on Unix with a file that exists" do before do # fake that we're on unix even if we're on windows - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) # mock up the filesystem to behave like unix setup_normal_file stat_struct = double("::File.stat", mode: 0600, uid: 0, gid: 0, mtime: 10000) @@ -332,7 +332,7 @@ shared_examples_for Chef::Provider::File do context "examining file security metadata on Unix with a file that does not exist" do before do # fake that we're on unix even if we're on windows - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) setup_missing_file end @@ -381,7 +381,7 @@ shared_examples_for Chef::Provider::File do before do # fake that we're on unix even if we're on windows - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) # mock up the filesystem to behave like unix setup_normal_file stat_struct = double("::File.stat", mode: 0600, uid: 0, gid: 0, mtime: 10000) diff --git a/spec/unit/application/client_spec.rb b/spec/unit/application/client_spec.rb index d4ed403197..b99f1b0126 100644 --- a/spec/unit/application/client_spec.rb +++ b/spec/unit/application/client_spec.rb @@ -323,7 +323,7 @@ describe Chef::Application::Client, "reconfigure" do it "should terminate with message when interval is given" do Chef::Config[:interval] = 600 - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) expect(Chef::Application).to receive(:fatal!).with( /Unforked .* interval runs are disabled by default\. Configuration settings: @@ -336,7 +336,7 @@ Enable .* interval runs by setting `:client_fork = true` in your config file or context "when interval is given on windows" do before do Chef::Config[:interval] = 600 - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) end it "should terminate" do diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb index 7a787d1f3f..24a453a240 100644 --- a/spec/unit/application_spec.rb +++ b/spec/unit/application_spec.rb @@ -277,7 +277,7 @@ describe Chef::Application do end end - if Chef::Platform.windows? + if ChefUtils.windows? it_behaves_like "sets log_location", :win_evt, Chef::Log::WinEvt it_behaves_like "sets log_location", "win_evt", Chef::Log::WinEvt else diff --git a/spec/unit/chef_fs/file_pattern_spec.rb b/spec/unit/chef_fs/file_pattern_spec.rb index 58cdbb28c2..856be5de0d 100644 --- a/spec/unit/chef_fs/file_pattern_spec.rb +++ b/spec/unit/chef_fs/file_pattern_spec.rb @@ -157,7 +157,7 @@ describe Chef::ChefFS::FilePattern do end end - context 'with simple pattern "a\*\b"', skip: (Chef::Platform.windows?) do + context 'with simple pattern "a\*\b"', skip: (ChefUtils.windows?) do let(:pattern) { Chef::ChefFS::FilePattern.new('a\*\b') } it "match?" do expect(pattern.match?("a*b")).to be_truthy @@ -264,7 +264,7 @@ describe Chef::ChefFS::FilePattern do end end - context 'with star pattern "/abc/d[a-z][0-9]f/ghi"', skip: (Chef::Platform.windows?) do + context 'with star pattern "/abc/d[a-z][0-9]f/ghi"', skip: (ChefUtils.windows?) do let(:pattern) { Chef::ChefFS::FilePattern.new("/abc/d[a-z][0-9]f/ghi") } it "match?" do expect(pattern.match?("/abc/de1f/ghi")).to be_truthy diff --git a/spec/unit/chef_fs/path_util_spec.rb b/spec/unit/chef_fs/path_util_spec.rb index 93205a1815..70679a5d07 100644 --- a/spec/unit/chef_fs/path_util_spec.rb +++ b/spec/unit/chef_fs/path_util_spec.rb @@ -1,6 +1,6 @@ # # Author:: Kartik Null Cating-Subramanian () -# Copyright:: Copyright 2015-2016, Chef Software Inc. +# Copyright:: Copyright 2015-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -81,7 +81,7 @@ describe Chef::ChefFS::PathUtils do end it "handles root correctly" do - if Chef::Platform.windows? + if ChefUtils.windows? expect(Chef::ChefFS::PathUtils.realest_path("C:/")).to eq("C:/") else expect(Chef::ChefFS::PathUtils.realest_path("/")).to eq("/") @@ -91,7 +91,7 @@ describe Chef::ChefFS::PathUtils do context "invoking descendant_path" do it "handles paths with various casing on windows" do - allow(Chef::ChefFS).to receive(:windows?) { true } + allow(ChefUtils).to receive(:windows?) { true } expect(Chef::ChefFS::PathUtils.descendant_path("C:/ab/b/c", "C:/AB/B")).to eq("c") expect(Chef::ChefFS::PathUtils.descendant_path("C:/ab/b/c", "c:/ab/B")).to eq("c") end diff --git a/spec/unit/client_spec.rb b/spec/unit/client_spec.rb index 5182717af8..3a400575c0 100644 --- a/spec/unit/client_spec.rb +++ b/spec/unit/client_spec.rb @@ -670,7 +670,7 @@ describe Chef::Client do describe "windows_admin_check" do context "platform is not windows" do before do - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) end it "shouldn't be called" do @@ -681,7 +681,7 @@ describe Chef::Client do context "platform is windows" do before do - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) end it "should be called" do diff --git a/spec/unit/cookbook/cookbook_version_loader_spec.rb b/spec/unit/cookbook/cookbook_version_loader_spec.rb index c38af059f5..2cd86877cb 100644 --- a/spec/unit/cookbook/cookbook_version_loader_spec.rb +++ b/spec/unit/cookbook/cookbook_version_loader_spec.rb @@ -20,7 +20,7 @@ require "spec_helper" describe Chef::Cookbook::CookbookVersionLoader do before do - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } end describe "loading a cookbook" do diff --git a/spec/unit/cookbook/syntax_check_spec.rb b/spec/unit/cookbook/syntax_check_spec.rb index a24fa3ab2a..54dfab84b8 100644 --- a/spec/unit/cookbook/syntax_check_spec.rb +++ b/spec/unit/cookbook/syntax_check_spec.rb @@ -1,6 +1,6 @@ # # Author:: Daniel DeLeo () -# Copyright:: Copyright 2010-2016, Chef Software Inc. +# Copyright:: Copyright 2010-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ require "chef/cookbook/syntax_check" describe Chef::Cookbook::SyntaxCheck do before do - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } end let(:cookbook_path) { File.join(CHEF_SPEC_DATA, "cookbooks", "openldap") } diff --git a/spec/unit/cookbook_loader_spec.rb b/spec/unit/cookbook_loader_spec.rb index a09bbd043f..f382c5d2dd 100644 --- a/spec/unit/cookbook_loader_spec.rb +++ b/spec/unit/cookbook_loader_spec.rb @@ -20,7 +20,7 @@ require "spec_helper" describe Chef::CookbookLoader do before do - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } end let(:repo_paths) do [ diff --git a/spec/unit/data_bag_spec.rb b/spec/unit/data_bag_spec.rb index 4b0ba42172..a0b6971efe 100644 --- a/spec/unit/data_bag_spec.rb +++ b/spec/unit/data_bag_spec.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob () -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,7 @@ require "chef/data_bag" describe Chef::DataBag do before(:each) do @data_bag = Chef::DataBag.new - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } end describe "initialize" do diff --git a/spec/unit/dsl/platform_introspection_spec.rb b/spec/unit/dsl/platform_introspection_spec.rb index 7af233a769..227585a889 100644 --- a/spec/unit/dsl/platform_introspection_spec.rb +++ b/spec/unit/dsl/platform_introspection_spec.rb @@ -1,6 +1,6 @@ # # Author:: Seth Falcon () -# Copyright:: Copyright 2010-2016, Chef Software Inc. +# Copyright:: Copyright 2010-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -127,3 +127,33 @@ describe Chef::DSL::PlatformIntrospection::PlatformFamilyDependentValue do end end + +describe "ChefHelper functions mixed into classes" do + METHODS = %i{windows? fedora_derived? bsd_based? rhel? aix? gentoo?}.freeze + + METHODS.each do |method| + it "mixes #{method} into Chef::Resource instances" do + expect(Chef::Resource.instance_methods.include?(method)).to be true + end + + it "mixes #{method} into Chef::Resource classes (provides lines, etc)" do + expect(Chef::Resource.respond_to?(method)).to be true + end + + it "mixes #{method} into Chef::Provider instances (actions)" do + expect(Chef::Provider.instance_methods.include?(method)).to be true + end + + it "mixes #{method} into Chef::Provider classes (provides lines, etc)" do + expect(Chef::Provider.respond_to?(method)).to be true + end + + it "mixes #{method} into Chef::Recipe instances (recipe files)" do + expect(Chef::Recipe.instance_methods.include?(method)).to be true + end + + it "mixes #{method} into Chef::Node instances (attribute files)" do + expect(Chef::Recipe.instance_methods.include?(method)).to be true + end + end +end diff --git a/spec/unit/file_content_management/deploy/mv_windows_spec.rb b/spec/unit/file_content_management/deploy/mv_windows_spec.rb index 1aadf89d2d..51c3ff051e 100644 --- a/spec/unit/file_content_management/deploy/mv_windows_spec.rb +++ b/spec/unit/file_content_management/deploy/mv_windows_spec.rb @@ -18,7 +18,7 @@ require "spec_helper" -unless Chef::Platform.windows? +unless ChefUtils.windows? class Chef module ReservedNames module Win32 diff --git a/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb b/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb index 209d987e78..22ff5515f0 100644 --- a/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb +++ b/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb @@ -1,6 +1,6 @@ # # Author:: Daniel DeLeo () -# Copyright:: Copyright 2012-2016, Chef Software Inc. +# Copyright:: Copyright 2012-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/spec/unit/knife/core/gem_glob_loader_spec.rb b/spec/unit/knife/core/gem_glob_loader_spec.rb index c8bd34d4a9..c761216733 100644 --- a/spec/unit/knife/core/gem_glob_loader_spec.rb +++ b/spec/unit/knife/core/gem_glob_loader_spec.rb @@ -23,7 +23,7 @@ describe Chef::Knife::SubcommandLoader::GemGlobLoader do let(:plugin_dir) { File.join(home, ".chef", "plugins", "knife") } before do - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } Chef::Util::PathHelper.class_variable_set(:@@home_dir, home) end diff --git a/spec/unit/knife/core/hashed_command_loader_spec.rb b/spec/unit/knife/core/hashed_command_loader_spec.rb index c463a36fb4..aa2ea3be51 100644 --- a/spec/unit/knife/core/hashed_command_loader_spec.rb +++ b/spec/unit/knife/core/hashed_command_loader_spec.rb @@ -19,7 +19,7 @@ require "spec_helper" describe Chef::Knife::SubcommandLoader::HashedCommandLoader do before do - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } end let(:plugin_manifest) do diff --git a/spec/unit/knife/core/subcommand_loader_spec.rb b/spec/unit/knife/core/subcommand_loader_spec.rb index 5db0bb73e5..3ab24d9a18 100644 --- a/spec/unit/knife/core/subcommand_loader_spec.rb +++ b/spec/unit/knife/core/subcommand_loader_spec.rb @@ -23,7 +23,7 @@ describe Chef::Knife::SubcommandLoader do let(:plugin_dir) { File.join(home, ".chef", "plugins", "knife") } before do - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } Chef::Util::PathHelper.class_variable_set(:@@home_dir, home) end diff --git a/spec/unit/knife/core/ui_spec.rb b/spec/unit/knife/core/ui_spec.rb index e5f19a4837..dfe906fdc1 100644 --- a/spec/unit/knife/core/ui_spec.rb +++ b/spec/unit/knife/core/ui_spec.rb @@ -3,7 +3,7 @@ # Author:: Tim Hinderliter () # Author:: Daniel DeLeo () # Author:: John Keiser () -# Copyright:: Copyright 2008-2017, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -482,7 +482,7 @@ describe Chef::Knife::UI do before(:each) do stdout = double("StringIO", tty?: true) allow(@ui).to receive(:stdout).and_return(stdout) - allow(ChefConfig).to receive(:windows?) { true } + allow(ChefUtils).to receive(:windows?) { true } Chef::Config.reset end diff --git a/spec/unit/knife/data_bag_from_file_spec.rb b/spec/unit/knife/data_bag_from_file_spec.rb index bc0ca330e8..86a60d858e 100644 --- a/spec/unit/knife/data_bag_from_file_spec.rb +++ b/spec/unit/knife/data_bag_from_file_spec.rb @@ -1,6 +1,6 @@ # # Author:: Seth Falcon () -# Copyright:: Copyright 2010-2016, Chef Software Inc. +# Copyright:: Copyright 2010-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +26,7 @@ Chef::Knife::DataBagFromFile.load_deps describe Chef::Knife::DataBagFromFile do before :each do - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } Chef::Config[:node_name] = "webmonkey.example.com" FileUtils.mkdir_p([db_folder, db_folder2]) db_file.write(Chef::JSONCompat.to_json(plain_data)) diff --git a/spec/unit/knife/environment_from_file_spec.rb b/spec/unit/knife/environment_from_file_spec.rb index 11e05cb922..477db36a4c 100644 --- a/spec/unit/knife/environment_from_file_spec.rb +++ b/spec/unit/knife/environment_from_file_spec.rb @@ -1,7 +1,7 @@ # # Author:: Stephen Delano () # Author:: Seth Falcon () -# Copyright:: Copyright 2010-2016, Chef Software Inc. +# Copyright:: Copyright 2010-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,7 @@ Chef::Knife::EnvironmentFromFile.load_deps describe Chef::Knife::EnvironmentFromFile do before(:each) do - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } @knife = Chef::Knife::EnvironmentFromFile.new @stdout = StringIO.new allow(@knife.ui).to receive(:stdout).and_return(@stdout) diff --git a/spec/unit/knife/supermarket_install_spec.rb b/spec/unit/knife/supermarket_install_spec.rb index 9c969106fc..3a43e78397 100644 --- a/spec/unit/knife/supermarket_install_spec.rb +++ b/spec/unit/knife/supermarket_install_spec.rb @@ -31,7 +31,7 @@ describe Chef::Knife::SupermarketInstall do merge_updates_from: true) end let(:install_path) do - if Chef::Platform.windows? + if ChefUtils.windows? "C:/tmp/chef" else "/var/tmp/chef" diff --git a/spec/unit/mash_spec.rb b/spec/unit/mash_spec.rb deleted file mode 100644 index 0797e80f2c..0000000000 --- a/spec/unit/mash_spec.rb +++ /dev/null @@ -1,51 +0,0 @@ -# -# Author:: Matthew Kent () -# Copyright:: Copyright 2011-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/mash" - -describe Mash do - it "should duplicate a simple key/value mash to a new mash" do - data = { x: "one", y: "two", z: "three" } - @orig = Mash.new(data) - @copy = @orig.dup - expect(@copy.to_hash).to eq(Mash.new(data).to_hash) - @copy[:x] = "four" - expect(@orig[:x]).to eq("one") - end - - it "should duplicate a mash with an array to a new mash" do - data = { x: "one", y: "two", z: [1, 2, 3] } - @orig = Mash.new(data) - @copy = @orig.dup - expect(@copy.to_hash).to eq(Mash.new(data).to_hash) - @copy[:z] << 4 - expect(@orig[:z]).to eq([1, 2, 3]) - end - - it "should duplicate a nested mash to a new mash" do - data = { x: "one", y: "two", z: Mash.new({ a: [1, 2, 3] }) } - @orig = Mash.new(data) - @copy = @orig.dup - expect(@copy.to_hash).to eq(Mash.new(data).to_hash) - @copy[:z][:a] << 4 - expect(@orig[:z][:a]).to eq([1, 2, 3]) - end - - # add more! -end diff --git a/spec/unit/mixin/path_sanity_spec.rb b/spec/unit/mixin/path_sanity_spec.rb index c9ed4e2595..ecea92c294 100644 --- a/spec/unit/mixin/path_sanity_spec.rb +++ b/spec/unit/mixin/path_sanity_spec.rb @@ -1,6 +1,6 @@ # # Author:: Seth Chisamore () -# Copyright:: Copyright 2011-2017, Chef Software Inc. +# Copyright:: Copyright 2011-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,7 +35,7 @@ describe Chef::Mixin::PathSanity do @gem_bindir = "/some/gem/bin" allow(Gem).to receive(:bindir).and_return(@gem_bindir) allow(RbConfig::CONFIG).to receive(:[]).with("bindir").and_return(@ruby_bindir) - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) end it "adds all useful PATHs even if environment is an empty hash" do @@ -83,7 +83,7 @@ describe Chef::Mixin::PathSanity do gem_bindir = 'C:\gems\bin' allow(Gem).to receive(:bindir).and_return(gem_bindir) allow(RbConfig::CONFIG).to receive(:[]).with("bindir").and_return(ruby_bindir) - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) env = { "PATH" => 'C:\Windows\system32;C:\mr\softie' } @sanity.enforce_path_sanity(env) expect(env["PATH"]).to eq("#{gem_bindir};#{ruby_bindir};C:\\Windows\\system32;C:\\mr\\softie") diff --git a/spec/unit/mixin/shell_out_spec.rb b/spec/unit/mixin/shell_out_spec.rb index 1c4f59b50b..afa3687a15 100644 --- a/spec/unit/mixin/shell_out_spec.rb +++ b/spec/unit/mixin/shell_out_spec.rb @@ -24,13 +24,12 @@ require "spec_helper" require "chef/mixin/path_sanity" describe Chef::Mixin::ShellOut do - include Chef::Mixin::PathSanity - + include ChefUtils::DSL::PathSanity let(:shell_out_class) { Class.new { include Chef::Mixin::ShellOut } } subject(:shell_out_obj) { shell_out_class.new } def env_path - if Chef::Platform.windows? + if ChefUtils.windows? "Path" else "PATH" diff --git a/spec/unit/mixin/template_spec.rb b/spec/unit/mixin/template_spec.rb index 04071988ad..f629e7ee0f 100644 --- a/spec/unit/mixin/template_spec.rb +++ b/spec/unit/mixin/template_spec.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob () -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ require "spec_helper" require "cgi" describe Chef::Mixin::Template, "render_template" do - let(:sep) { Chef::Platform.windows? ? "\r\n" : "\n" } + let(:sep) { ChefUtils.windows? ? "\r\n" : "\n" } before :each do @context = Chef::Mixin::Template::TemplateContext.new({}) @@ -39,7 +39,7 @@ describe Chef::Mixin::Template, "render_template" do describe "when running on windows" do before do - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) end it "should render the templates with windows line endings" do @@ -54,7 +54,7 @@ describe Chef::Mixin::Template, "render_template" do describe "when running on unix" do before do - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) end it "should render the templates with unix line endings" do diff --git a/spec/unit/mixin/user_context_spec.rb b/spec/unit/mixin/user_context_spec.rb index 31e182d042..c8add8a434 100644 --- a/spec/unit/mixin/user_context_spec.rb +++ b/spec/unit/mixin/user_context_spec.rb @@ -1,6 +1,6 @@ # # Author:: Adam Edwards () -# Copyright:: Copyright (c) 2015 Chef Software, Inc. +# Copyright:: Copyright (c) 2015-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,7 +39,7 @@ describe "a class that mixes in user_context" do context "when running on Windows" do before do - allow(::Chef::Platform).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) allow(::Chef::Util::Windows::LogonSession).to receive(:new).and_return(logon_session) end @@ -97,7 +97,7 @@ describe "a class that mixes in user_context" do context "when not running on Windows" do before do - allow(::Chef::Platform).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) end it "raises a ::Chef::Exceptions::UnsupportedPlatform exception" do diff --git a/spec/unit/node_map_spec.rb b/spec/unit/node_map_spec.rb index 2b38f8cea5..444b297ea0 100644 --- a/spec/unit/node_map_spec.rb +++ b/spec/unit/node_map_spec.rb @@ -104,8 +104,8 @@ describe Chef::NodeMap do end it "returns nil when the platform_family does not match" do - allow(node).to receive(:[]).with(:os).and_return("linux") - allow(node).to receive(:[]).with(:platform_family).and_return("debian") + node.automatic["os"] = "linux" + node.automatic["platform_family"] = "debian" expect(node_map.get(node, :thing)).to eql(nil) end end @@ -174,26 +174,26 @@ describe Chef::NodeMap do end it "returns the value when the node matches" do - allow(node).to receive(:[]).with(:platform_family).and_return("rhel") - allow(node).to receive(:[]).with(:platform_version).and_return("7.0") + node.automatic["platform_family"] = "rhel" + node.automatic["platform_version"] = "7.0" expect(node_map.get(node, :thing)).to eql(:foo) end it "returns nil when the block does not match" do - allow(node).to receive(:[]).with(:platform_family).and_return("rhel") - allow(node).to receive(:[]).with(:platform_version).and_return("6.4") + node.automatic["platform_family"] = "rhel" + node.automatic["platform_version"] = "6.4" expect(node_map.get(node, :thing)).to eql(nil) end it "returns nil when the platform_family filter does not match" do - allow(node).to receive(:[]).with(:platform_family).and_return("debian") - allow(node).to receive(:[]).with(:platform_version).and_return("7.0") + node.automatic["platform_family"] = "debian" + node.automatic["platform_version"] = "7.0" expect(node_map.get(node, :thing)).to eql(nil) end it "returns nil when both do not match" do - allow(node).to receive(:[]).with(:platform_family).and_return("debian") - allow(node).to receive(:[]).with(:platform_version).and_return("6.0") + node.automatic["platform_family"] = "debian" + node.automatic["platform_version"] = "6.0" expect(node_map.get(node, :thing)).to eql(nil) end @@ -203,8 +203,8 @@ describe Chef::NodeMap do end it "returns the value when the node matches" do - allow(node).to receive(:[]).with(:platform_family).and_return("rhel") - allow(node).to receive(:[]).with(:platform_version).and_return("7.0") + node.automatic["platform_family"] = "rhel" + node.automatic["platform_version"] = "7.0" expect(node_map.get(node, :thing)).to eql(:foo) end end diff --git a/spec/unit/platform/query_helpers_spec.rb b/spec/unit/platform/query_helpers_spec.rb index 22bfd150ee..d5e4d09029 100644 --- a/spec/unit/platform/query_helpers_spec.rb +++ b/spec/unit/platform/query_helpers_spec.rb @@ -1,6 +1,6 @@ # # Author:: Bryan McLellan -# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# Copyright:: Copyright 2014-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,13 +43,13 @@ describe "Chef::Platform#windows_nano_server?" do end it "returns false early when not on windows" do - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) expect(Chef::Platform).to_not receive(:require) expect(Chef::Platform.windows_nano_server?).to be false end it "returns true when the registry value is 1" do - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) allow(Chef::Platform).to receive(:require).with("win32/registry") expect(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open) .with(key, access) @@ -59,7 +59,7 @@ describe "Chef::Platform#windows_nano_server?" do end it "returns false when the registry value is not 1" do - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) allow(Chef::Platform).to receive(:require).with("win32/registry") expect(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open) .with(key, access) @@ -69,7 +69,7 @@ describe "Chef::Platform#windows_nano_server?" do end it "returns false when the registry value does not exist" do - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) allow(Chef::Platform).to receive(:require).with("win32/registry") expect(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open) .with(key, access) @@ -80,7 +80,7 @@ describe "Chef::Platform#windows_nano_server?" do end it "returns false when the registry key does not exist" do - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) allow(Chef::Platform).to receive(:require).with("win32/registry") expect(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open) .with(key, access) @@ -114,13 +114,13 @@ describe "Chef::Platform#supports_msi?" do end it "returns false early when not on windows" do - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) expect(Chef::Platform).to_not receive(:require) expect(Chef::Platform.supports_msi?).to be false end it "returns true when the registry key exists" do - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) allow(Chef::Platform).to receive(:require).with("win32/registry") expect(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open) .with(key, access) @@ -129,7 +129,7 @@ describe "Chef::Platform#supports_msi?" do end it "returns false when the registry key does not exist" do - allow(ChefConfig).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) allow(Chef::Platform).to receive(:require).with("win32/registry") expect(Win32::Registry::HKEY_LOCAL_MACHINE).to receive(:open) .with(key, access) diff --git a/spec/unit/provider/execute_spec.rb b/spec/unit/provider/execute_spec.rb index 11eb70e396..60f2070c1c 100644 --- a/spec/unit/provider/execute_spec.rb +++ b/spec/unit/provider/execute_spec.rb @@ -42,7 +42,7 @@ describe Chef::Provider::Execute do before do allow(Chef::EventDispatch::EventsOutputStream).to receive(:new) { @live_stream } - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } @original_log_level = Chef::Log.level Chef::Log.level = :info allow(STDOUT).to receive(:tty?).and_return(false) diff --git a/spec/unit/provider/link_spec.rb b/spec/unit/provider/link_spec.rb index fff2c1ffa8..154197e730 100644 --- a/spec/unit/provider/link_spec.rb +++ b/spec/unit/provider/link_spec.rb @@ -1,7 +1,7 @@ # # Author:: AJ Christensen () # Author:: John Keiser () -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ require "ostruct" require "spec_helper" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/win32/file" # probably need this in spec_helper end @@ -41,7 +41,7 @@ describe Chef::Resource::Link do end def canonicalize(path) - Chef::Platform.windows? ? path.tr("/", '\\') : path + ChefUtils.windows? ? path.tr("/", '\\') : path end describe "when the target is a symlink" do @@ -359,7 +359,7 @@ describe Chef::Resource::Link do provider.new_resource.name ).and_return(resource_link) allow(resource_link).to receive(:verify_links_supported!) - allow(Chef::Platform).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) end context "soft links" do @@ -389,7 +389,7 @@ describe Chef::Resource::Link do context "on Linux platform" do before(:each) do - allow(Chef::Platform).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) end context "soft links" do diff --git a/spec/unit/provider/package/windows/exe_spec.rb b/spec/unit/provider/package/windows/exe_spec.rb index 6e39ddc78a..2ed4c03905 100644 --- a/spec/unit/provider/package/windows/exe_spec.rb +++ b/spec/unit/provider/package/windows/exe_spec.rb @@ -19,7 +19,7 @@ require "spec_helper" require "chef/provider/package/windows/exe" -unless Chef::Platform.windows? +unless ChefUtils.windows? class Chef module ReservedNames::Win32 class File diff --git a/spec/unit/provider/package/windows_spec.rb b/spec/unit/provider/package/windows_spec.rb index 2fafb3bd0e..ddb2448801 100644 --- a/spec/unit/provider/package/windows_spec.rb +++ b/spec/unit/provider/package/windows_spec.rb @@ -1,6 +1,6 @@ # # Author:: Bryan McLellan -# Copyright:: Copyright 2014-2017, Chef Software Inc. +# Copyright:: Copyright 2014-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,7 @@ require "chef/provider/package/windows/msi" describe Chef::Provider::Package::Windows, :windows_only do before(:each) do - allow(Chef::Util::PathHelper).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) allow(Chef::FileCache).to receive(:create_cache_path).with("package/").and_return(cache_path) end diff --git a/spec/unit/provider/remote_file/fetcher_spec.rb b/spec/unit/provider/remote_file/fetcher_spec.rb index b110e2c03a..254a9d36ec 100644 --- a/spec/unit/provider/remote_file/fetcher_spec.rb +++ b/spec/unit/provider/remote_file/fetcher_spec.rb @@ -1,6 +1,6 @@ # # Author:: Lamont Granquist () -# Copyright:: Copyright 2013-2016, Chef Software Inc. +# Copyright:: Copyright 2013-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +27,7 @@ describe Chef::Provider::RemoteFile::Fetcher do describe "when passed a network share" do before do expect(Chef::Provider::RemoteFile::NetworkFile).to receive(:new).and_return(fetcher_instance) - allow(Chef::Platform).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) end context "when host is a name" do diff --git a/spec/unit/provider/remote_file/local_file_spec.rb b/spec/unit/provider/remote_file/local_file_spec.rb index 6dad6a57f2..cfca09ad18 100644 --- a/spec/unit/provider/remote_file/local_file_spec.rb +++ b/spec/unit/provider/remote_file/local_file_spec.rb @@ -31,7 +31,7 @@ describe Chef::Provider::RemoteFile::LocalFile do context "when parsing source path on windows" do before do - allow(Chef::Platform).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) end describe "when given local unix path" do diff --git a/spec/unit/provider/remote_file/network_file_spec.rb b/spec/unit/provider/remote_file/network_file_spec.rb index 1c2bcc5911..5eb8c8e3e5 100644 --- a/spec/unit/provider/remote_file/network_file_spec.rb +++ b/spec/unit/provider/remote_file/network_file_spec.rb @@ -33,7 +33,7 @@ describe Chef::Provider::RemoteFile::NetworkFile do let(:source_file) { double("::File", read: nil) } before do - allow(Chef::Platform).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) end it "stages the local file to a temporary file" do diff --git a/spec/unit/provider/script_spec.rb b/spec/unit/provider/script_spec.rb index 08b19730a7..68d6bdb697 100644 --- a/spec/unit/provider/script_spec.rb +++ b/spec/unit/provider/script_spec.rb @@ -59,7 +59,7 @@ describe Chef::Provider::Script, "action_run" do context "when configuring the script file's security" do context "when not running on Windows" do before do - allow(::Chef::Platform).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) end context "#set_owner_and_group" do it "sets the owner and group for the script file" do @@ -73,7 +73,7 @@ describe Chef::Provider::Script, "action_run" do context "when running on Windows" do before do - allow(::Chef::Platform).to receive(:windows?).and_return(true) + allow(ChefUtils).to receive(:windows?).and_return(true) expect(new_resource.user).to eq(nil) stub_const("Chef::ReservedNames::Win32::API::Security::GENERIC_READ", 1) stub_const("Chef::ReservedNames::Win32::API::Security::GENERIC_EXECUTE", 4) diff --git a/spec/unit/provider/subversion_spec.rb b/spec/unit/provider/subversion_spec.rb index a70b7cd48b..9f5ffacec6 100644 --- a/spec/unit/provider/subversion_spec.rb +++ b/spec/unit/provider/subversion_spec.rb @@ -1,6 +1,6 @@ # # Author:: Daniel DeLeo () -# Copyright:: Copyright 2008-2017, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -274,7 +274,7 @@ describe Chef::Provider::Subversion do it "selects 'svn' as the binary by default" do @resource.svn_binary nil - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } expect(@provider).to receive(:svn_binary).and_return("svn") expect(@provider.export_command).to eql( "svn export --force -q -r12345 http://svn.example.org/trunk/ /my/deploy/dir" @@ -283,7 +283,7 @@ describe Chef::Provider::Subversion do it "selects an svn binary with an exe extension on windows" do @resource.svn_binary nil - allow(ChefConfig).to receive(:windows?) { true } + allow(ChefUtils).to receive(:windows?) { true } expect(@provider).to receive(:svn_binary).and_return("svn.exe") expect(@provider.export_command).to eql( "svn.exe export --force -q -r12345 http://svn.example.org/trunk/ /my/deploy/dir" diff --git a/spec/unit/provider/user/dscl_spec.rb b/spec/unit/provider/user/dscl_spec.rb index e20873dc92..5ef47170c0 100644 --- a/spec/unit/provider/user/dscl_spec.rb +++ b/spec/unit/provider/user/dscl_spec.rb @@ -21,7 +21,7 @@ require "ostruct" describe Chef::Provider::User::Dscl do before do - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } end let(:shellcmdresult) { Struct.new(:stdout, :stderr, :exitstatus) } diff --git a/spec/unit/provider_resolver_spec.rb b/spec/unit/provider_resolver_spec.rb index 94e0d6074b..c8eb18b5b6 100644 --- a/spec/unit/provider_resolver_spec.rb +++ b/spec/unit/provider_resolver_spec.rb @@ -35,9 +35,8 @@ describe Chef::ProviderResolver do # Root the filesystem under a temp directory so Chef.path_to will point at it when_the_repository "is empty" do before do - allow(Chef).to receive(:path_to) { |path| File.join(path_to(""), path) } + allow(Chef::Resource::DnfPackage).to receive(:which).with("dnf").and_return(nil) end - let(:resource_name) { :service } let(:provider) { nil } let(:action) { :start } @@ -145,51 +144,36 @@ describe Chef::ProviderResolver do describe "resolving service resource" do def stub_service_providers(*services) - services.each do |service| - case service - when :debian - file "usr/sbin/update-rc.d", "" - when :invokercd - file "usr/sbin/invoke-rc.d", "" - when :insserv - file "sbin/insserv", "" - when :upstart - file "sbin/initctl", "" - when :redhat - file "sbin/chkconfig", "" - when :systemd - file "proc/1/comm", "systemd\n" - else - raise ArgumentError, service - end + allowed = %i{debianrcd invokercd insserv upstart redhatrcd systemd} + + (allowed - services).each do |api| + allow(Chef::Provider::Service).to receive(:"#{api}?").and_return(false) + end + + raise ArgumentError unless (services - allowed).empty? + + services.each do |api| + allow(Chef::Provider::Service).to receive(:"#{api}?").and_return(true) end end def stub_service_configs(*configs) - configs.each do |config| - case config - when :initd - file "etc/init.d/#{service_name}", "" - when :upstart - file "etc/init/#{service_name}.conf", "" - when :xinetd - file "etc/xinetd.d/#{service_name}", "" - when :etc_rcd - file "etc/rc.d/#{service_name}", "" - when :usr_local_etc_rcd - file "usr/local/etc/rc.d/#{service_name}", "" - when :systemd - file "proc/1/comm", "systemd\n" - file "etc/systemd/system/#{service_name}.service", "" - else - raise ArgumentError, config - end + allowed = %i{initd upstart xinetd systemd etc_rcd} + + (allowed - configs).each do |type| + allow(Chef::Provider::Service).to receive(:service_script_exist?).with(type, service_name).and_return(false) + end + + raise ArgumentError unless (configs - allowed).empty? + + configs.each do |type| + allow(Chef::Provider::Service).to receive(:service_script_exist?).with(type, service_name).and_return(true) end end shared_examples_for "an ubuntu platform with upstart, update-rc.d and systemd" do before do - stub_service_providers(:debian, :invokercd, :upstart, :systemd) + stub_service_providers(:debianrcd, :invokercd, :upstart, :systemd) end it "when both the SysV init and Systemd script exists, it returns a Service::Debian provider" do @@ -213,12 +197,12 @@ describe Chef::ProviderResolver do end it "when only the SysV init script exists, it returns a Service::Systemd provider" do - stub_service_configs(:initd) + stub_service_configs(:initd, :systemd) expect(resolved_provider).to eql(Chef::Provider::Service::Systemd) end it "when both SysV and Upstart scripts exist, it returns a Service::Systemd provider" do - stub_service_configs(:initd, :upstart) + stub_service_configs(:initd, :systemd, :upstart) expect(resolved_provider).to eql(Chef::Provider::Service::Systemd) end @@ -235,7 +219,7 @@ describe Chef::ProviderResolver do shared_examples_for "an ubuntu platform with upstart and update-rc.d" do before do - stub_service_providers(:debian, :invokercd, :upstart) + stub_service_providers(:debianrcd, :invokercd, :upstart) end # needs to be handled by the highest priority init.d handler @@ -362,7 +346,7 @@ describe Chef::ProviderResolver do shared_examples_for "a debian platform using the insserv provider" do context "with a default install" do before do - stub_service_providers(:debian, :invokercd, :insserv) + stub_service_providers(:debianrcd, :invokercd, :insserv) end it "uses the Service::Insserv Provider to manage sysv init scripts" do @@ -378,7 +362,7 @@ describe Chef::ProviderResolver do context "when the user has installed upstart" do before do - stub_service_providers(:debian, :invokercd, :insserv, :upstart) + stub_service_providers(:debianrcd, :invokercd, :insserv, :upstart) end it "when only the SysV init script exists, it returns an Insserv provider" do @@ -407,8 +391,8 @@ describe Chef::ProviderResolver do it_behaves_like "an ubuntu platform with upstart, update-rc.d and systemd" it "when the unit-files are missing and system-ctl list-unit-files returns an error" do - stub_service_providers(:debian, :invokercd, :upstart, :systemd) - stub_service_configs(:initd, :upstart) + stub_service_providers(:debianrcd, :invokercd, :upstart, :systemd) + stub_service_configs(:initd, :upstart, :systemd) mock_shellout_command("/bin/systemctl list-unit-files", exitstatus: 1) expect(resolved_provider).to eql(Chef::Provider::Service::Systemd) end @@ -445,8 +429,8 @@ describe Chef::ProviderResolver do it "always returns a Solaris provider" do # no matter what we stub on the next two lines we should get a Solaris provider - stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) - stub_service_configs(:initd, :upstart, :xinetd, :usr_local_etc_rcd, :systemd) + stub_service_providers(:debianrcd, :invokercd, :insserv, :upstart, :redhatrcd, :systemd) + stub_service_configs(:initd, :upstart, :xinetd, :systemd) expect(resolved_provider).to eql(Chef::Provider::Service::Solaris) end end @@ -460,8 +444,8 @@ describe Chef::ProviderResolver do it "always returns a Windows provider" do # no matter what we stub on the next two lines we should get a Windows provider - stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) - stub_service_configs(:initd, :upstart, :xinetd, :usr_local_etc_rcd, :systemd) + stub_service_providers(:debianrcd, :invokercd, :insserv, :upstart, :redhatrcd, :systemd) + stub_service_configs(:initd, :upstart, :xinetd, :systemd) expect(resolved_provider).to eql(Chef::Provider::Service::Windows) end end @@ -475,8 +459,8 @@ describe Chef::ProviderResolver do it "always returns a Macosx provider" do # no matter what we stub on the next two lines we should get a Macosx provider - stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) - stub_service_configs(:initd, :upstart, :xinetd, :usr_local_etc_rcd, :systemd) + stub_service_providers(:debianrcd, :invokercd, :insserv, :upstart, :redhatrcd, :systemd) + stub_service_configs(:initd, :upstart, :xinetd, :systemd) expect(resolved_provider).to eql(Chef::Provider::Service::Macosx) end end @@ -484,7 +468,6 @@ describe Chef::ProviderResolver do on_platform "freebsd", os: "freebsd", platform_version: "10.3" do it "returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do stub_service_providers - stub_service_configs(:usr_local_etc_rcd) expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) end @@ -495,15 +478,14 @@ describe Chef::ProviderResolver do end it "always returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do - # should only care about :usr_local_etc_rcd stub in the service configs - stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) - stub_service_configs(:usr_local_etc_rcd, :initd, :upstart, :xinetd, :systemd) + stub_service_providers(:debianrcd, :invokercd, :insserv, :upstart, :redhatrcd, :systemd) + stub_service_configs(:initd, :upstart, :xinetd, :systemd) expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) end it "always returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do # should only care about :etc_rcd stub in the service configs - stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) + stub_service_providers(:debianrcd, :invokercd, :insserv, :upstart, :redhatrcd, :systemd) stub_service_configs(:etc_rcd, :initd, :upstart, :xinetd, :systemd) expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) end @@ -518,7 +500,6 @@ describe Chef::ProviderResolver do on_platform "netbsd", os: "netbsd", platform_version: "7.0.1" do it "returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do stub_service_providers - stub_service_configs(:usr_local_etc_rcd) expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) end @@ -529,15 +510,14 @@ describe Chef::ProviderResolver do end it "always returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do - # should only care about :usr_local_etc_rcd stub in the service configs - stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) - stub_service_configs(:usr_local_etc_rcd, :initd, :upstart, :xinetd, :systemd) + stub_service_providers(:debianrcd, :invokercd, :insserv, :upstart, :redhatrcd, :systemd) + stub_service_configs(:initd, :upstart, :xinetd, :systemd) expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) end it "always returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do # should only care about :etc_rcd stub in the service configs - stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) + stub_service_providers(:debianrcd, :invokercd, :insserv, :upstart, :redhatrcd, :systemd) stub_service_configs(:etc_rcd, :initd, :upstart, :xinetd, :systemd) expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) end diff --git a/spec/unit/resource/cookbook_file_spec.rb b/spec/unit/resource/cookbook_file_spec.rb index b35233649d..655cebaf01 100644 --- a/spec/unit/resource/cookbook_file_spec.rb +++ b/spec/unit/resource/cookbook_file_spec.rb @@ -53,7 +53,7 @@ describe Chef::Resource::CookbookFile do describe "when it has a backup number, group, mode, owner, source, checksum, and cookbook on nix or path, rights, deny_rights, checksum on windows" do before do - if Chef::Platform.windows? + if ChefUtils.windows? resource.path("C:/temp/origin/file.txt") resource.rights(:read, "Everyone") resource.deny_rights(:full_control, "Clumsy_Sam") @@ -70,7 +70,7 @@ describe Chef::Resource::CookbookFile do it "describes the state" do state = resource.state_for_resource_reporter - if Chef::Platform.windows? + if ChefUtils.windows? puts state expect(state[:rights]).to eq([{ permissions: :read, principals: "Everyone" }]) expect(state[:deny_rights]).to eq([{ permissions: :full_control, principals: "Clumsy_Sam" }]) @@ -83,7 +83,7 @@ describe Chef::Resource::CookbookFile do end it "returns the path as its identity" do - if Chef::Platform.windows? + if ChefUtils.windows? expect(resource.identity).to eq("C:/temp/origin/file.txt") else expect(resource.identity).to eq("/tmp/origin/file.txt") diff --git a/spec/unit/resource/remote_file_spec.rb b/spec/unit/resource/remote_file_spec.rb index 39d34d9a96..27b889ea9e 100644 --- a/spec/unit/resource/remote_file_spec.rb +++ b/spec/unit/resource/remote_file_spec.rb @@ -181,7 +181,7 @@ describe Chef::Resource::RemoteFile do describe "when it has group, mode, owner, source, and checksum" do before do - if Chef::Platform.windows? + if ChefUtils.windows? resource.path("C:/temp/origin/file.txt") resource.rights(:read, "Everyone") resource.deny_rights(:full_control, "Clumsy_Sam") @@ -197,7 +197,7 @@ describe Chef::Resource::RemoteFile do it "describes its state" do state = resource.state_for_resource_reporter - if Chef::Platform.windows? + if ChefUtils.windows? puts state expect(state[:rights]).to eq([{ permissions: :read, principals: "Everyone" }]) expect(state[:deny_rights]).to eq([{ permissions: :full_control, principals: "Clumsy_Sam" }]) @@ -210,7 +210,7 @@ describe Chef::Resource::RemoteFile do end it "returns the path as its identity" do - if Chef::Platform.windows? + if ChefUtils.windows? expect(resource.identity).to eq("C:/temp/origin/file.txt") else expect(resource.identity).to eq("/this/path/") diff --git a/spec/unit/role_spec.rb b/spec/unit/role_spec.rb index 13932ab3ee..8a67913d60 100644 --- a/spec/unit/role_spec.rb +++ b/spec/unit/role_spec.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob () -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ require "chef/role" describe Chef::Role do before(:each) do - allow(ChefConfig).to receive(:windows?) { false } + allow(ChefUtils).to receive(:windows?) { false } @role = Chef::Role.new @role.name("ops_master") end diff --git a/spec/unit/shell_spec.rb b/spec/unit/shell_spec.rb index aa573706b1..6dba848084 100644 --- a/spec/unit/shell_spec.rb +++ b/spec/unit/shell_spec.rb @@ -42,7 +42,7 @@ describe Shell do before do Shell.irb_conf = {} allow(Shell::ShellSession.instance).to receive(:reset!) - allow(ChefConfig).to receive(:windows?).and_return(false) + allow(ChefUtils).to receive(:windows?).and_return(false) allow(Chef::Util::PathHelper).to receive(:home).and_return("/home/foo") end diff --git a/spec/unit/util/selinux_spec.rb b/spec/unit/util/selinux_spec.rb index 0d2d1aeb3f..18774aee2c 100644 --- a/spec/unit/util/selinux_spec.rb +++ b/spec/unit/util/selinux_spec.rb @@ -1,6 +1,6 @@ # # Author:: Serdar Sutay () -# Copyright:: Copyright 2013-2018, Chef Software Inc. +# Copyright:: Copyright 2013-2019, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,7 +41,7 @@ describe Chef::Util::Selinux do it "each part of ENV['PATH'] should be checked" do expected_paths = ENV["PATH"].split(File::PATH_SEPARATOR) + [ "/bin", "/usr/bin", "/sbin", "/usr/sbin" ] - expected_paths.each do |bin_path| + expected_paths.uniq.each do |bin_path| selinux_path = File.join(bin_path, "selinuxenabled") expect(File).to receive(:executable?).with(selinux_path).and_return(false) end diff --git a/spec/unit/win32/error_spec.rb b/spec/unit/win32/error_spec.rb index 316303ab4f..8980293be7 100644 --- a/spec/unit/win32/error_spec.rb +++ b/spec/unit/win32/error_spec.rb @@ -17,7 +17,7 @@ # require "spec_helper" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/win32/error" require "chef/win32/api/error" end diff --git a/spec/unit/win32/link_spec.rb b/spec/unit/win32/link_spec.rb index 5f749c034e..de7b165dd0 100644 --- a/spec/unit/win32/link_spec.rb +++ b/spec/unit/win32/link_spec.rb @@ -16,7 +16,7 @@ # require "spec_helper" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/win32/api/file" require "chef/win32/file" require "chef/win32/version" diff --git a/spec/unit/win32/security_spec.rb b/spec/unit/win32/security_spec.rb index efbb290adf..6dc330dddd 100644 --- a/spec/unit/win32/security_spec.rb +++ b/spec/unit/win32/security_spec.rb @@ -17,7 +17,7 @@ # require "spec_helper" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/win32/error" require "chef/win32/security" require "chef/win32/api/error" diff --git a/spec/unit/windows_service_spec.rb b/spec/unit/windows_service_spec.rb index 45af0f9d9f..d046b67c5b 100644 --- a/spec/unit/windows_service_spec.rb +++ b/spec/unit/windows_service_spec.rb @@ -16,7 +16,7 @@ # limitations under the License. # require "spec_helper" -if Chef::Platform.windows? +if ChefUtils.windows? require "chef/application/windows_service" end diff --git a/tasks/rspec.rb b/tasks/rspec.rb index 2d20a0ffa7..3906228416 100644 --- a/tasks/rspec.rb +++ b/tasks/rspec.rb @@ -1,7 +1,7 @@ # # Author:: Adam Jacob () # Author:: Daniel DeLeo () -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,12 +25,14 @@ CHEF_ROOT = File.join(File.dirname(__FILE__), "..") begin require "rspec/core/rake_task" - desc "Run specs for Chef's Components (chef-config)" + desc "Run specs for Chef's Components" task :component_specs do - Dir.chdir("chef-config") do - Bundler.with_clean_env do - sh("bundle install") - sh("bundle exec rake spec") + %w{chef-utils chef-config}.each do |gem| + Dir.chdir(gem) do + Bundler.with_clean_env do + sh("bundle install") + sh("bundle exec rake spec") + end end end end -- cgit v1.2.1