diff options
Diffstat (limited to 'lib/chef')
201 files changed, 1918 insertions, 2648 deletions
diff --git a/lib/chef/api_client.rb b/lib/chef/api_client.rb index 087de3fdf9..551d9a6035 100644 --- a/lib/chef/api_client.rb +++ b/lib/chef/api_client.rb @@ -47,7 +47,7 @@ class Chef # Gets or sets the client name. # - # @params [Optional String] The name must be alpha-numeric plus - and _. + # @param [Optional String] The name must be alpha-numeric plus - and _. # @return [String] The current value of the name. def name(arg = nil) set_or_return( @@ -59,7 +59,7 @@ class Chef # Gets or sets whether this client is an admin. # - # @params [Optional True/False] Should be true or false - default is false. + # @param [Optional True/False] Should be true or false - default is false. # @return [True/False] The current value def admin(arg = nil) set_or_return( @@ -71,7 +71,7 @@ class Chef # Gets or sets the public key. # - # @params [Optional String] The string representation of the public key. + # @param [Optional String] The string representation of the public key. # @return [String] The current value. def public_key(arg = nil) set_or_return( @@ -83,7 +83,7 @@ class Chef # Gets or sets whether this client is a validator. # - # @params [Boolean] whether or not the client is a validator. If + # @param [Boolean] whether or not the client is a validator. If # `nil`, retrieves the already-set value. # @return [Boolean] The current value def validator(arg = nil) @@ -96,7 +96,7 @@ class Chef # Gets or sets the private key. # - # @params [Optional String] The string representation of the private key. + # @param [Optional String] The string representation of the private key. # @return [String] The current value. def private_key(arg = nil) set_or_return( diff --git a/lib/chef/api_client_v1.rb b/lib/chef/api_client_v1.rb index a1b9b8317e..a3a5780cc2 100644 --- a/lib/chef/api_client_v1.rb +++ b/lib/chef/api_client_v1.rb @@ -70,7 +70,7 @@ class Chef # Gets or sets the client name. # - # @params [Optional String] The name must be alpha-numeric plus - and _. + # @param [Optional String] The name must be alpha-numeric plus - and _. # @return [String] The current value of the name. def name(arg = nil) set_or_return( @@ -82,7 +82,7 @@ class Chef # Gets or sets whether this client is an admin. # - # @params [Optional True/False] Should be true or false - default is false. + # @param [Optional True/False] Should be true or false - default is false. # @return [True/False] The current value def admin(arg = nil) set_or_return( @@ -94,7 +94,7 @@ class Chef # Gets or sets the public key. # - # @params [Optional String] The string representation of the public key. + # @param [Optional String] The string representation of the public key. # @return [String] The current value. def public_key(arg = nil) set_or_return( @@ -106,7 +106,7 @@ class Chef # Gets or sets whether this client is a validator. # - # @params [Boolean] whether or not the client is a validator. If + # @param [Boolean] whether or not the client is a validator. If # `nil`, retrieves the already-set value. # @return [Boolean] The current value def validator(arg = nil) @@ -120,7 +120,7 @@ class Chef # Private key. The server will return it as a string. # Set to true under API V0 to have the server regenerate the default key. # - # @params [Optional String] The string representation of the private key. + # @param [Optional String] The string representation of the private key. # @return [String] The current value. def private_key(arg = nil) set_or_return( @@ -132,7 +132,7 @@ class Chef # Used to ask server to generate key pair under api V1 # - # @params [Optional True/False] Should be true or false - default is false. + # @param [Optional True/False] Should be true or false - default is false. # @return [True/False] The current value def create_key(arg = nil) set_or_return( diff --git a/lib/chef/application.rb b/lib/chef/application.rb index 096ce9c392..b20766c8b5 100644 --- a/lib/chef/application.rb +++ b/lib/chef/application.rb @@ -1,7 +1,7 @@ # # Author:: AJ Christensen (<aj@chef.io>) # Author:: Mark Mzyk (mmzyk@chef.io) -# 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"); @@ -90,6 +90,7 @@ class Chef load_config_file Chef::Config.export_proxies Chef::Config.init_openssl + File.umask Chef::Config[:umask] end # Parse the config file @@ -176,7 +177,7 @@ class Chef # Based on config and whether or not STDOUT is a tty, should we setup a # secondary logger for stdout? def want_additional_logger? - ( Chef::Config[:log_location] != STDOUT ) && STDOUT.tty? && !Chef::Config[:daemonize] + !( Chef::Config[:log_location].is_a?(IO) && Chef::Config[:log_location].tty? ) && !Chef::Config[:daemonize] end def configure_stdout_logger diff --git a/lib/chef/application/knife.rb b/lib/chef/application/knife.rb index 6a09427ccd..c972e9313e 100644 --- a/lib/chef/application/knife.rb +++ b/lib/chef/application/knife.rb @@ -148,6 +148,10 @@ class Chef::Application::Knife < Chef::Application :boolean => true, :default => nil + option :profile, + :long => "--profile PROFILE", + :description => "The credentials profile to select" + # Run knife def run Mixlib::Log::Formatter.show_time = false diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb index f246b1946a..6b4aef42b4 100644 --- a/lib/chef/application/solo.rb +++ b/lib/chef/application/solo.rb @@ -1,7 +1,7 @@ # # Author:: AJ Christensen (<aj@chef.io>) # Author:: Mark Mzyk (mmzyk@chef.io) -# 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"); @@ -238,17 +238,10 @@ class Chef::Application::Solo < Chef::Application Chef::Config[:solo] = true - Chef::Log.deprecation("-r MUST be changed to --recipe-url, the -r option will be changed in Chef 13.0") if ARGV.include?("-r") - if !Chef::Config[:solo_legacy_mode] # Because we re-parse ARGV when we move to chef-client, we need to tidy up some options first. ARGV.delete("--ez") - # -r means something entirely different in chef-client land, so let's replace it with a "safe" value - if dash_r = ARGV.index("-r") - ARGV[dash_r] = "--recipe-url" - end - # For back compat reasons, we need to ensure that we try and use the cache_path as a repo first Chef::Log.debug "Current chef_repo_path is #{Chef::Config.chef_repo_path}" diff --git a/lib/chef/audit/audit_reporter.rb b/lib/chef/audit/audit_reporter.rb index 8546a21bb4..80ae3a8dd4 100644 --- a/lib/chef/audit/audit_reporter.rb +++ b/lib/chef/audit/audit_reporter.rb @@ -1,7 +1,7 @@ # # Author:: Tyler Ball (<tball@chef.io>) # -# 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"); @@ -49,7 +49,7 @@ class Chef def audit_phase_complete(audit_output) Chef::Log.debug("Audit Reporter completed successfully without errors.") - ordered_control_groups.each do |name, control_group| + ordered_control_groups.each_value do |control_group| audit_data.add_control_group(control_group) end end @@ -62,7 +62,7 @@ class Chef # The stacktrace information has already been logged elsewhere @audit_phase_error = error Chef::Log.debug("Audit Reporter failed.") - ordered_control_groups.each do |name, control_group| + ordered_control_groups.each_value do |control_group| audit_data.add_control_group(control_group) end end diff --git a/lib/chef/audit/runner.rb b/lib/chef/audit/runner.rb index 837346381c..f6fed3fc64 100644 --- a/lib/chef/audit/runner.rb +++ b/lib/chef/audit/runner.rb @@ -1,6 +1,6 @@ # # Author:: Claire McQuin (<claire@chef.io>) -# 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"); @@ -163,7 +163,7 @@ class Chef # or use example group filters. def register_control_groups add_example_group_methods - run_context.audits.each do |name, group| + run_context.audits.each do |name, group| # rubocop:disable Performance/HashEachMethods ctl_grp = RSpec::Core::ExampleGroup.__control_group__(*group.args, &group.block) RSpec.world.record(ctl_grp) end diff --git a/lib/chef/chef_class.rb b/lib/chef/chef_class.rb index e61fd5e1d2..bfea51609a 100644 --- a/lib/chef/chef_class.rb +++ b/lib/chef/chef_class.rb @@ -200,8 +200,8 @@ class Chef # # Emit a deprecation message. # - # @param type The message to send. This should be a symbol, referring to - # a class defined in Chef::Deprecated + # @param [Symbol] type The message to send. This should refer to a class + # defined in Chef::Deprecated # @param message An explicit message to display, rather than the generic one # associated with the deprecation. # @param location The location. Defaults to the caller who called you (since diff --git a/lib/chef/chef_fs/data_handler/acl_data_handler.rb b/lib/chef/chef_fs/data_handler/acl_data_handler.rb index 6c8833004a..834fc5ca0b 100644 --- a/lib/chef/chef_fs/data_handler/acl_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/acl_data_handler.rb @@ -13,7 +13,7 @@ class Chef "delete" => {}, "grant" => {}, }) - result.keys.each do |key| + result.each_key do |key| result[key] = normalize_hash(result[key], { "actors" => [], "groups" => [] }) result[key]["actors"] = result[key]["actors"].sort result[key]["groups"] = result[key]["groups"].sort diff --git a/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb b/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb index 4b272daabc..3b1fb53da6 100644 --- a/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb +++ b/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb @@ -5,7 +5,7 @@ class Chef module ChefFS module DataHandler class DataBagItemDataHandler < DataHandlerBase - RESERVED_NAMES = /node|role|environment|client/ + RESERVED_NAMES = /^(node|role|environment|client)$/ def normalize(data_bag_item, entry) # If it's wrapped with raw_data, unwrap it. diff --git a/lib/chef/chef_fs/data_handler/data_handler_base.rb b/lib/chef/chef_fs/data_handler/data_handler_base.rb index 3668f77dd5..4b4696ce5e 100644 --- a/lib/chef/chef_fs/data_handler/data_handler_base.rb +++ b/lib/chef/chef_fs/data_handler/data_handler_base.rb @@ -56,8 +56,7 @@ class Chef # 2. Put the actual values in the order of the defaults # 3. Move any other values to the end # - # == Example - # + # @example # normalize_hash({x: 100, c: 2, a: 1}, { a: 10, b: 20, c: 30}) # -> { a: 1, b: 20, c: 2, x: 100} # @@ -140,8 +139,7 @@ class Chef # the keys specified in "keys"; anything else must be emitted by the # caller. # - # == Example - # + # @example # to_ruby_keys({"name" => "foo", "environment" => "desert", "foo": "bar"}, [ "name", "environment" ]) # -> # 'name "foo" diff --git a/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb b/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb index 64488ed705..9b0ea18cd8 100644 --- a/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb @@ -1,6 +1,6 @@ # # Author:: John Keiser (<jkeiser@chef.io>) -# 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"); @@ -76,7 +76,7 @@ class Chef if @children.nil? @children = [] manifest = chef_object.cookbook_manifest - manifest.by_parent_directory.each do |segment, files| + manifest.by_parent_directory.each_value do |files| files.each do |file| parts = file[:path].split("/") # Get or create the path to the file diff --git a/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb b/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb index a4add1378d..8259db473d 100644 --- a/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb +++ b/lib/chef/chef_fs/file_system/chef_server/policies_dir.rb @@ -1,6 +1,6 @@ # # Author:: John Keiser (<jkeiser@chef.io>) -# 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"); @@ -71,7 +71,7 @@ class Chef result = [] data = root.get_json(api_path) data.keys.sort.each do |policy_name| - data[policy_name]["revisions"].keys.each do |policy_revision| + data[policy_name]["revisions"].each_key do |policy_revision| filename = "#{policy_name}-#{policy_revision}.json" result << make_child_entry(filename, true) end diff --git a/lib/chef/client.rb b/lib/chef/client.rb index 786ed2c4fc..6ff2d78ee6 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -3,7 +3,7 @@ # Author:: Christopher Walters (<cw@chef.io>) # Author:: Christopher Brown (<cb@chef.io>) # Author:: Tim Hinderliter (<tim@chef.io>) -# 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"); @@ -100,14 +100,6 @@ class Chef attr_reader :rest # - # A rest object with validate_utf8 set to false. This will not throw exceptions - # on non-UTF8 strings in JSON but will sanitize them so that e.g. POSTs will - # never fail. Cannot be configured on a request-by-request basis, so we carry - # around another rest object for it. - # - attr_reader :rest_clean - - # # The runner used to converge. # # @return [Chef::Runner] @@ -398,8 +390,10 @@ class Chef end end - # Rest client for use by API reporters. This rest client will not fail with an exception if - # it is fed non-UTF8 data. + # A rest object with validate_utf8 set to false. This will not throw exceptions + # on non-UTF8 strings in JSON but will sanitize them so that e.g. POSTs will + # never fail. Cannot be configured on a request-by-request basis, so we carry + # around another rest object for it. # # @api private def rest_clean(client_name = node_name, config = Chef::Config) diff --git a/lib/chef/cookbook/chefignore.rb b/lib/chef/cookbook/chefignore.rb index dce58ecdb8..a27af68cb0 100644 --- a/lib/chef/cookbook/chefignore.rb +++ b/lib/chef/cookbook/chefignore.rb @@ -33,12 +33,16 @@ class Chef @ignores = parse_ignore_file end + # @param [Array] list the list of cookbook files + # @return [Array] list of cookbook files with chefignore files removed def remove_ignores_from(file_list) Array(file_list).inject([]) do |unignored, file| ignored?(file) ? unignored : unignored << file end end + # @param [String] file_name the file name to check ignored status for + # @return [Boolean] is the file ignored or not def ignored?(file_name) @ignores.any? { |glob| File.fnmatch?(glob, file_name) } end diff --git a/lib/chef/cookbook/cookbook_collection.rb b/lib/chef/cookbook/cookbook_collection.rb index d06b8fd042..b2a4d5884a 100644 --- a/lib/chef/cookbook/cookbook_collection.rb +++ b/lib/chef/cookbook/cookbook_collection.rb @@ -1,7 +1,7 @@ #-- # Author:: Tim Hinderliter (<tim@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) -# Copyright:: Copyright 2010-2016 Chef Software, Inc. +# Copyright:: Copyright 2010-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,10 +47,10 @@ class Chef # Currently checks chef_version and ohai_version in the cookbook metadata # against the running Chef::VERSION and Ohai::VERSION. # - # @raises [Chef::Exceptions::CookbookChefVersionMismatch] if the Chef::VERSION fails validation - # @raises [Chef::Exceptions::CookbookOhaiVersionMismatch] if the Ohai::VERSION fails validation + # @raise [Chef::Exceptions::CookbookChefVersionMismatch] if the Chef::VERSION fails validation + # @raise [Chef::Exceptions::CookbookOhaiVersionMismatch] if the Ohai::VERSION fails validation def validate! - each do |cookbook_name, cookbook_version| + each_value do |cookbook_version| cookbook_version.metadata.validate_chef_version! cookbook_version.metadata.validate_ohai_version! end diff --git a/lib/chef/cookbook/cookbook_version_loader.rb b/lib/chef/cookbook/cookbook_version_loader.rb index 35dac27fa5..b139a8d489 100644 --- a/lib/chef/cookbook/cookbook_version_loader.rb +++ b/lib/chef/cookbook/cookbook_version_loader.rb @@ -13,7 +13,6 @@ class Chef attr_reader :cookbook_settings attr_reader :cookbook_paths - attr_reader :metadata_filenames attr_reader :frozen attr_reader :uploaded_cookbook_version_file diff --git a/lib/chef/cookbook/gem_installer.rb b/lib/chef/cookbook/gem_installer.rb index 5b1426e4e8..0b64d3354f 100644 --- a/lib/chef/cookbook/gem_installer.rb +++ b/lib/chef/cookbook/gem_installer.rb @@ -1,5 +1,5 @@ #-- -# Copyright:: Copyright (c) 2010-2017, Chef Software Inc. +# Copyright:: Copyright (c) 2010-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,7 +38,7 @@ class Chef def install cookbook_gems = Hash.new { |h, k| h[k] = [] } - cookbook_collection.each do |cookbook_name, cookbook_version| + cookbook_collection.each_value do |cookbook_version| cookbook_version.metadata.gems.each do |args| cookbook_gems[args.first] += args[1..-1] end diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb index b23c01e622..22f006640d 100644 --- a/lib/chef/cookbook/metadata.rb +++ b/lib/chef/cookbook/metadata.rb @@ -2,7 +2,7 @@ # Author:: Adam Jacob (<adam@chef.io>) # Author:: AJ Christensen (<aj@chef.io>) # Author:: Seth Falcon (<seth@chef.io>) -# 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"); @@ -74,7 +74,6 @@ class Chef attr_reader :providing attr_reader :attributes attr_reader :recipes - attr_reader :version # @return [Array<Gem::Dependency>] Array of supported Chef versions attr_reader :chef_versions @@ -596,7 +595,7 @@ class Chef # Validates that the Ohai::VERSION of the running chef-client matches one of the # configured ohai_version statements in this cookbooks metadata. # - # @raises [Chef::Exceptions::CookbookOhaiVersionMismatch] if the cookbook fails validation + # @raise [Chef::Exceptions::CookbookOhaiVersionMismatch] if the cookbook fails validation def validate_ohai_version! unless gem_dep_matches?("ohai", Gem::Version.new(Ohai::VERSION), *ohai_versions) raise Exceptions::CookbookOhaiVersionMismatch.new(Ohai::VERSION, name, version, *ohai_versions) @@ -606,7 +605,7 @@ class Chef # Validates that the Chef::VERSION of the running chef-client matches one of the # configured chef_version statements in this cookbooks metadata. # - # @raises [Chef::Exceptions::CookbookChefVersionMismatch] if the cookbook fails validation + # @raise [Chef::Exceptions::CookbookChefVersionMismatch] if the cookbook fails validation def validate_chef_version! unless gem_dep_matches?("chef", Gem::Version.new(Chef::VERSION), *chef_versions) raise Exceptions::CookbookChefVersionMismatch.new(Chef::VERSION, name, version, *chef_versions) diff --git a/lib/chef/cookbook_loader.rb b/lib/chef/cookbook_loader.rb index a965b43c61..1cd498496a 100644 --- a/lib/chef/cookbook_loader.rb +++ b/lib/chef/cookbook_loader.rb @@ -2,7 +2,7 @@ # Author:: Adam Jacob (<adam@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) # Author:: Daniel DeLeo (<dan@kallistec.com>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # Copyright:: Copyright 2009-2016, Daniel DeLeo # License:: Apache License, Version 2.0 # @@ -78,7 +78,7 @@ class Chef # @api private def load_cookbooks_without_shadow_warning preload_cookbooks - @loaders_by_name.each do |cookbook_name, _loaders| + @loaders_by_name.each_key do |cookbook_name| load_cookbook(cookbook_name) end @cookbooks_by_name @@ -142,6 +142,14 @@ class Chef end end + def each_key(&block) + cookbook_names.each(&block) + end + + def each_value(&block) + values.each(&block) + end + def cookbook_names @cookbooks_by_name.keys.sort end diff --git a/lib/chef/cookbook_uploader.rb b/lib/chef/cookbook_uploader.rb index 5e11314190..470d7be5b6 100644 --- a/lib/chef/cookbook_uploader.rb +++ b/lib/chef/cookbook_uploader.rb @@ -145,7 +145,6 @@ class Chef Chef::Log.info("Validating templates") exit(1) unless syntax_checker.validate_templates Chef::Log.info("Syntax OK") - true end end diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb index dcb8c97548..99438ade82 100644 --- a/lib/chef/cookbook_version.rb +++ b/lib/chef/cookbook_version.rb @@ -4,7 +4,7 @@ # Author:: Tim Hinderliter (<tim@chef.io>) # Author:: Seth Falcon (<seth@chef.io>) # Author:: Daniel DeLeo (<dan@chef.io>) -# 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"); @@ -54,11 +54,6 @@ class Chef # CookbookVersion. attr_reader :metadata - attr_reader :recipe_filenames_by_name - attr_reader :attribute_filenames_by_short_filename - - attr_accessor :chef_server_rest - # The `identifier` field is used for cookbook_artifacts, which are # organized on the chef server according to their content. If the # policy_mode option to CookbookManifest is set to true it will include @@ -157,7 +152,6 @@ class Chef def metadata=(metadata) @metadata = metadata @metadata.recipes_from_cookbook_version(self) - @metadata end def manifest diff --git a/lib/chef/data_bag.rb b/lib/chef/data_bag.rb index 82eb03fbd7..c5e2b38c94 100644 --- a/lib/chef/data_bag.rb +++ b/lib/chef/data_bag.rb @@ -2,7 +2,7 @@ # Author:: Adam Jacob (<adam@chef.io>) # Author:: Nuo Yan (<nuo@chef.io>) # Author:: Christopher Brown (<cb@chef.io>) -# Copyright:: Copyright 2009-2016, Chef Software Inc. +# Copyright:: Copyright 2009-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,9 +33,7 @@ class Chef include Chef::Mixin::ParamsValidate VALID_NAME = /^[\.\-[:alnum:]_]+$/ - RESERVED_NAMES = /node|role|environment|client/ - - attr_accessor :chef_server_rest + RESERVED_NAMES = /^(node|role|environment|client)$/ def self.validate_name!(name) unless name =~ VALID_NAME diff --git a/lib/chef/data_bag_item.rb b/lib/chef/data_bag_item.rb index d0fca26125..388da78dad 100644 --- a/lib/chef/data_bag_item.rb +++ b/lib/chef/data_bag_item.rb @@ -2,7 +2,7 @@ # Author:: Adam Jacob (<adam@chef.io>) # Author:: Nuo Yan (<nuo@chef.io>) # Author:: Christopher Brown (<cb@chef.io>) -# Copyright:: Copyright 2009-2016, Chef Software, Inc. +# Copyright:: Copyright 2009-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,8 +38,6 @@ class Chef VALID_ID = /^[\.\-[:alnum:]_]+$/ - attr_accessor :chef_server_rest - def self.validate_id!(id_str) if id_str.nil? || ( id_str !~ VALID_ID ) raise Exceptions::InvalidDataBagItemID, "Data Bag items must have an id matching #{VALID_ID.inspect}, you gave: #{id_str.inspect}" @@ -66,10 +64,6 @@ class Chef Chef::ServerAPI.new(Chef::Config[:chef_server_url]) end - def raw_data - @raw_data - end - def validate_id!(id_str) self.class.validate_id!(id_str) end diff --git a/lib/chef/data_collector/messages.rb b/lib/chef/data_collector/messages.rb index ca854957d1..b4e30e8b5a 100644 --- a/lib/chef/data_collector/messages.rb +++ b/lib/chef/data_collector/messages.rb @@ -36,7 +36,7 @@ class Chef # def self.run_start_message(run_status) { - "chef_server_fqdn" => chef_server_fqdn(run_status), + "chef_server_fqdn" => chef_server_fqdn, "entity_uuid" => node_uuid, "id" => run_status.run_id, "message_version" => "1.0.0", @@ -61,7 +61,7 @@ class Chef run_status = reporter_data[:run_status] message = { - "chef_server_fqdn" => chef_server_fqdn(run_status), + "chef_server_fqdn" => chef_server_fqdn, "entity_uuid" => node_uuid, "expanded_run_list" => reporter_data[:expanded_run_list], "id" => run_status.run_id, diff --git a/lib/chef/data_collector/messages/helpers.rb b/lib/chef/data_collector/messages/helpers.rb index f42ddaaa4e..d9a3394265 100644 --- a/lib/chef/data_collector/messages/helpers.rb +++ b/lib/chef/data_collector/messages/helpers.rb @@ -31,7 +31,7 @@ class Chef # # @return [String] FQDN of the configured Chef Server, or node/localhost if not found. # - def chef_server_fqdn(run_status) + def chef_server_fqdn if !Chef::Config[:chef_server_url].nil? URI(Chef::Config[:chef_server_url]).host elsif !Chef::Config[:node_name].nil? diff --git a/lib/chef/deprecated.rb b/lib/chef/deprecated.rb index 183f8e4c24..ac4440f6db 100644 --- a/lib/chef/deprecated.rb +++ b/lib/chef/deprecated.rb @@ -268,6 +268,16 @@ class Chef end end + class ErlResource < Base + def id + 22 + end + + def target + "erl_resource.html" + end + end + # id 3694 was deleted class Generic < Base diff --git a/lib/chef/dsl/data_query.rb b/lib/chef/dsl/data_query.rb index b966885724..8ec466ea35 100644 --- a/lib/chef/dsl/data_query.rb +++ b/lib/chef/dsl/data_query.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# 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"); @@ -83,7 +83,3 @@ class Chef end end end - -# **DEPRECATED** -# This used to be part of chef/mixin/language. Load the file to activate the deprecation code. -require "chef/mixin/language" diff --git a/lib/chef/dsl/include_attribute.rb b/lib/chef/dsl/include_attribute.rb index 6d27fefc25..9f73143722 100644 --- a/lib/chef/dsl/include_attribute.rb +++ b/lib/chef/dsl/include_attribute.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# 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"); @@ -55,7 +55,3 @@ class Chef end end end - -# **DEPRECATED** -# This used to be part of chef/mixin/language_include_attribute. Load the file to activate the deprecation code. -require "chef/mixin/language_include_attribute" diff --git a/lib/chef/dsl/include_recipe.rb b/lib/chef/dsl/include_recipe.rb index 9abd7d135b..d217c91d4b 100644 --- a/lib/chef/dsl/include_recipe.rb +++ b/lib/chef/dsl/include_recipe.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# 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"); @@ -38,7 +38,3 @@ class Chef end end end - -# **DEPRECATED** -# This used to be part of chef/mixin/language_include_recipe. Load the file to activate the deprecation code. -require "chef/mixin/language_include_recipe" diff --git a/lib/chef/dsl/platform_introspection.rb b/lib/chef/dsl/platform_introspection.rb index dc309f9acb..2e31e0b95b 100644 --- a/lib/chef/dsl/platform_introspection.rb +++ b/lib/chef/dsl/platform_introspection.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# 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"); @@ -262,7 +262,3 @@ class Chef end end end - -# **DEPRECATED** -# This used to be part of chef/mixin/language. Load the file to activate the deprecation code. -require "chef/mixin/language" diff --git a/lib/chef/dsl/recipe.rb b/lib/chef/dsl/recipe.rb index dedf291857..9da812cec0 100644 --- a/lib/chef/dsl/recipe.rb +++ b/lib/chef/dsl/recipe.rb @@ -1,7 +1,7 @@ -#-- +# # Author:: Adam Jacob (<adam@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) -# 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"); @@ -74,19 +74,9 @@ class Chef def exec(args) raise Chef::Exceptions::ResourceNotFound, "exec was called, but you probably meant to use an execute resource. If not, please call Kernel#exec explicitly. The exec block called was \"#{args}\"" end - - # @deprecated Use Chef::DSL::Recipe instead, will be removed in Chef 13 - module FullDSL - include Chef::DSL::Recipe - extend Chef::Mixin::LazyModuleInclude - end end end end # Avoid circular references for things that are only used in instance methods require "chef/resource" - -# **DEPRECATED** -# This used to be part of chef/mixin/recipe_definition_dsl_core. Load the file to activate the deprecation code. -require "chef/mixin/recipe_definition_dsl_core" diff --git a/lib/chef/environment.rb b/lib/chef/environment.rb index 621a122440..be05b58989 100644 --- a/lib/chef/environment.rb +++ b/lib/chef/environment.rb @@ -3,7 +3,7 @@ # Author:: Seth Falcon (<seth@chef.io>) # Author:: John Keiser (<jkeiser@ospcode.com>) # Author:: Kyle Goodwin (<kgoodwin@primerevenue.com>) -# 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"); @@ -34,8 +34,6 @@ class Chef include Chef::Mixin::ParamsValidate include Chef::Mixin::FromFile - attr_accessor :chef_server_rest - COMBINED_COOKBOOK_CONSTRAINT = /(.+)(?:[\s]+)((?:#{Chef::VersionConstraint::OPS.join('|')})(?:[\s]+).+)$/ def initialize(chef_server_rest: nil) @@ -297,7 +295,7 @@ class Chef def self.validate_cookbook_versions(cv) return false unless cv.kind_of?(Hash) - cv.each do |cookbook, version| + cv.each_value do |version| return false unless Chef::Environment.validate_cookbook_version(version) end true diff --git a/lib/chef/guard_interpreter/resource_guard_interpreter.rb b/lib/chef/guard_interpreter/resource_guard_interpreter.rb index 6df60aec89..e245eab2c7 100644 --- a/lib/chef/guard_interpreter/resource_guard_interpreter.rb +++ b/lib/chef/guard_interpreter/resource_guard_interpreter.rb @@ -1,6 +1,6 @@ # # Author:: Adam Edwards (<adamed@chef.io>) -# 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"); @@ -108,7 +108,7 @@ class Chef def block_from_attributes(attributes) Proc.new do - attributes.keys.each do |attribute_name| + attributes.each_key do |attribute_name| send(attribute_name, attributes[attribute_name]) if respond_to?(attribute_name) end end diff --git a/lib/chef/handler/json_file.rb b/lib/chef/handler/json_file.rb index 9ba3d70383..7f29b91449 100644 --- a/lib/chef/handler/json_file.rb +++ b/lib/chef/handler/json_file.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# 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"); @@ -28,7 +28,6 @@ class Chef def initialize(config = {}) @config = config @config[:path] ||= "/var/chef/reports" - @config end def report diff --git a/lib/chef/http.rb b/lib/chef/http.rb index 14dd8b93a5..c9df4e1235 100644 --- a/lib/chef/http.rb +++ b/lib/chef/http.rb @@ -170,11 +170,10 @@ class Chef raise end - def streaming_request_with_progress(path, headers = {}, &progress_block) + def streaming_request_with_progress(path, headers = {}, tempfile = nil, &progress_block) http_attempts ||= 0 url = create_url(path) response, rest_request, return_value = nil, nil, nil - tempfile = nil data = nil method = :GET @@ -182,7 +181,7 @@ class Chef response, rest_request, return_value = send_http_request(method, url, processed_headers, data) do |http_response| if http_response.kind_of?(Net::HTTPSuccess) - tempfile = stream_to_tempfile(url, http_response, &progress_block) + tempfile = stream_to_tempfile(url, http_response, tempfile, &progress_block) end apply_stream_complete_middleware(http_response, rest_request, return_value) end @@ -217,11 +216,10 @@ class Chef # # @yield [tempfile] block to process the tempfile # @yieldparams [tempfile<Tempfile>] tempfile - def streaming_request(path, headers = {}) + def streaming_request(path, headers = {}, tempfile = nil) http_attempts ||= 0 url = create_url(path) response, rest_request, return_value = nil, nil, nil - tempfile = nil data = nil method = :GET @@ -229,7 +227,7 @@ class Chef response, rest_request, return_value = send_http_request(method, url, processed_headers, data) do |http_response| if http_response.kind_of?(Net::HTTPSuccess) - tempfile = stream_to_tempfile(url, http_response) + tempfile = stream_to_tempfile(url, http_response, tempfile) end apply_stream_complete_middleware(http_response, rest_request, return_value) end @@ -500,11 +498,13 @@ class Chef end # @api private - def stream_to_tempfile(url, response, &progress_block) + def stream_to_tempfile(url, response, tf = nil, &progress_block) content_length = response["Content-Length"] - tf = Tempfile.open("chef-rest") - if Chef::Platform.windows? - tf.binmode # required for binary files on Windows platforms + if tf.nil? + tf = Tempfile.open("chef-rest") + if Chef::Platform.windows? + tf.binmode # required for binary files on Windows platforms + end end Chef::Log.debug("Streaming download from #{url} to tempfile #{tf.path}") # Stolen from http://www.ruby-forum.com/topic/166423 diff --git a/lib/chef/http/basic_client.rb b/lib/chef/http/basic_client.rb index 9a000136e6..1539770aa8 100644 --- a/lib/chef/http/basic_client.rb +++ b/lib/chef/http/basic_client.rb @@ -5,7 +5,7 @@ # Author:: Christopher Brown (<cb@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) # Author:: Daniel DeLeo (<dan@chef.io>) -# Copyright:: Copyright 2009-2016, Chef Software Inc. +# Copyright:: Copyright 2009-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,7 +32,6 @@ class Chef HTTPS = "https".freeze attr_reader :url - attr_reader :http_client attr_reader :ssl_policy attr_reader :keepalives diff --git a/lib/chef/http/http_request.rb b/lib/chef/http/http_request.rb index 7fc1acb889..bd999d8f86 100644 --- a/lib/chef/http/http_request.rb +++ b/lib/chef/http/http_request.rb @@ -5,7 +5,7 @@ # Author:: Christopher Brown (<cb@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) # Author:: Daniel DeLeo (<dan@chef.io>) -# Copyright:: Copyright 2009-2016, 2010-2016 Chef Software, Inc. +# Copyright:: Copyright 2009-2016, 2010-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -71,7 +71,7 @@ class Chef @user_agent ||= DEFAULT_UA end - attr_reader :method, :url, :headers, :http_client, :http_request + attr_reader :method, :url, :headers, :http_request def initialize(method, url, req_body, base_headers = {}) @method, @url = method, url diff --git a/lib/chef/http/socketless_chef_zero_client.rb b/lib/chef/http/socketless_chef_zero_client.rb index 296330815a..34a5dbb083 100644 --- a/lib/chef/http/socketless_chef_zero_client.rb +++ b/lib/chef/http/socketless_chef_zero_client.rb @@ -1,6 +1,6 @@ #-- # Author:: Daniel DeLeo (<dan@chef.io>) -# 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"); @@ -133,7 +133,7 @@ class Chef 511 => "Network Authentication Required", } - STATUS_MESSAGE.values.each { |v| v.freeze } + STATUS_MESSAGE.each_value { |v| v.freeze } STATUS_MESSAGE.freeze def initialize(base_url) diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb index aa30f2e2ed..663649f32f 100644 --- a/lib/chef/knife.rb +++ b/lib/chef/knife.rb @@ -42,9 +42,9 @@ class Chef extend Chef::Mixin::ConvertToClassName extend Forwardable - # Backwards Compat: - # Ideally, we should not vomit all of these methods into this base class; - # instead, they should be accessed by hitting the ui object directly. + # @note Backwards Compat: + # Ideally, we should not vomit all of these methods into this base class; + # instead, they should be accessed by hitting the ui object directly. def_delegator :@ui, :stdout def_delegator :@ui, :stderr def_delegator :@ui, :stdin @@ -105,12 +105,11 @@ class Chef # Explicitly set the category for the current command to +new_category+ # The category is normally determined from the first word of the command # name, but some commands make more sense using two or more words - # ===Arguments - # new_category::: A String to set the category to (see examples) - # ===Examples: - # Data bag commands would be in the 'data' category by default. To put them - # in the 'data bag' category: - # category('data bag') + # @param new_category [String] value to set the category to (see examples) + # + # @example Data bag commands would be in the 'data' category by default. To + # put them in the 'data bag' category: + # category('data bag') def self.category(new_category) @category = new_category end @@ -178,8 +177,9 @@ class Chef @config_loader ||= WorkstationConfigLoader.new(nil, Chef::Log) end - def self.load_config(explicit_config_file) + def self.load_config(explicit_config_file, profile) config_loader.explicit_config_file = explicit_config_file + config_loader.profile = profile config_loader.load ui.warn("No knife configuration file found") if config_loader.no_config_found? @@ -196,10 +196,11 @@ class Chef # Run knife for the given +args+ (ARGV), adding +options+ to the list of # CLI options that the subcommand knows how to handle. - # ===Arguments - # args::: usually ARGV - # options::: A Mixlib::CLI option parser hash. These +options+ are how - # subcommands know about global knife CLI options + # + # @param args [Array] The arguments. Usually ARGV + # @param options [Mixlib::CLI option parser hash] These +options+ are how + # subcommands know about global knife CLI options + # def self.run(args, options = {}) # Fallback debug logging. Normally the logger isn't configured until we # read the config, but this means any logging that happens before the @@ -404,7 +405,7 @@ class Chef def configure_chef # knife needs to send logger output to STDERR by default Chef::Config[:log_location] = STDERR - config_loader = self.class.load_config(config[:config_file]) + config_loader = self.class.load_config(config[:config_file], config[:profile]) config[:config_file] = config_loader.config_location # For CLI options like `--config-option key=value`. These have to get diff --git a/lib/chef/knife/configure.rb b/lib/chef/knife/configure.rb index 967a18de87..10ae62b6c9 100644 --- a/lib/chef/knife/configure.rb +++ b/lib/chef/knife/configure.rb @@ -17,6 +17,7 @@ # require "chef/knife" +require "chef/util/path_helper" class Chef class Knife @@ -67,24 +68,22 @@ class Chef end def run - ask_user_for_config_path - FileUtils.mkdir_p(chef_config_path) + config_file = File.join(chef_config_path, "credentials") ask_user_for_config - ::File.open(config[:config_file], "w") do |f| + config_file = File.expand_path(config_file) + if File.exist?(config_file) + confirm("Overwrite #{config_file}?") + end + ::File.open(config_file, "w") do |f| f.puts <<-EOH -node_name '#{new_client_name}' -client_key '#{new_client_key}' -validation_client_name '#{validation_client_name}' -validation_key '#{validation_key}' -chef_server_url '#{chef_server}' -syntax_check_cache_path '#{File.join(chef_config_path, "syntax_check_cache")}' +[default] +client_name = '#{new_client_name}' +client_key = '#{new_client_key}' +chef_server_url = '#{chef_server}' EOH - unless chef_repo.empty? - f.puts "cookbook_path [ '#{chef_repo}/cookbooks' ]" - end end if config[:initial] @@ -109,26 +108,11 @@ EOH ui.msg("Before running commands with Knife") ui.msg("") ui.msg("*****") - ui.msg("") - ui.msg("You must place your validation key in:") - ui.msg(" #{validation_key}") - ui.msg("Before generating instance data with Knife") - ui.msg("") - ui.msg("*****") end ui.msg("Configuration file written to #{config[:config_file]}") end - def ask_user_for_config_path - config[:config_file] ||= ask_question("Where should I put the config file? ", :default => "#{Chef::Config[:user_home]}/.chef/knife.rb") - # have to use expand path to expand the tilde character to the user's home - config[:config_file] = File.expand_path(config[:config_file]) - if File.exists?(config[:config_file]) - confirm("Overwrite #{config[:config_file]}") - end - end - def ask_user_for_config server_name = guess_servername @chef_server = config[:chef_server_url] || ask_question("Please enter the chef server URL: ", :default => "https://#{server_name}/organizations/myorg") @@ -140,10 +124,6 @@ EOH else @new_client_name = config[:node_name] || ask_question("Please enter an existing username or clientname for the API: ", :default => Etc.getlogin) end - @validation_client_name = config[:validation_client_name] || ask_question("Please enter the validation clientname: ", :default => "chef-validator") - @validation_key = config[:validation_key] || ask_question("Please enter the location of the validation key: ", :default => "/etc/chef-server/chef-validator.pem") - @validation_key = File.expand_path(@validation_key) - @chef_repo = config[:repository] || ask_question("Please enter the path to a chef repository (or leave blank): ") @new_client_key = config[:client_key] || File.join(chef_config_path, "#{@new_client_name}.pem") @new_client_key = File.expand_path(@new_client_key) @@ -157,12 +137,8 @@ EOH o[:fqdn] || o[:machinename] || o[:hostname] || "localhost" end - def config_file - config[:config_file] - end - def chef_config_path - File.dirname(config_file) + Chef::Util::PathHelper.home(".chef") end end end diff --git a/lib/chef/knife/cookbook_metadata.rb b/lib/chef/knife/cookbook_metadata.rb index 29eba6a36a..e089c4b777 100644 --- a/lib/chef/knife/cookbook_metadata.rb +++ b/lib/chef/knife/cookbook_metadata.rb @@ -1,7 +1,7 @@ # # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2009-2016, Chef Software Inc. +# Copyright:: Copyright 2009-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -47,7 +47,7 @@ class Chef if config[:all] cl = Chef::CookbookLoader.new(config[:cookbook_path]) cl.load_cookbooks - cl.each do |cname, cookbook| + cl.each_key do |cname| generate_metadata(cname.to_s) end else diff --git a/lib/chef/knife/cookbook_site_install.rb b/lib/chef/knife/cookbook_site_install.rb index 72fb426554..f4d692e13c 100644 --- a/lib/chef/knife/cookbook_site_install.rb +++ b/lib/chef/knife/cookbook_site_install.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# 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"); @@ -116,7 +116,7 @@ class Chef end unless config[:no_deps] - preferred_metadata.dependencies.each do |cookbook, version_list| + preferred_metadata.dependencies.each_key do |cookbook| # Doesn't do versions.. yet nv = self.class.new nv.config = config diff --git a/lib/chef/knife/cookbook_test.rb b/lib/chef/knife/cookbook_test.rb index 5c6dd32f37..f3a4981c95 100644 --- a/lib/chef/knife/cookbook_test.rb +++ b/lib/chef/knife/cookbook_test.rb @@ -2,7 +2,7 @@ # # Author:: Adam Jacob (<adam@chef.io>) # Author:: Matthew Kent (<mkent@magoazul.com>) -# Copyright:: Copyright 2009-2016, Chef Software Inc. +# Copyright:: Copyright 2009-2018, Chef Software Inc. # Copyright:: Copyright 2010-2016, Matthew Kent # License:: Apache License, Version 2.0 # @@ -50,7 +50,7 @@ class Chef if config[:all] cl = cookbook_loader cl.load_cookbooks - cl.each do |key, cookbook| + cl.each_key do |key| checked_a_cookbook = true test_cookbook(key) end diff --git a/lib/chef/knife/cookbook_upload.rb b/lib/chef/knife/cookbook_upload.rb index 6938ac280d..f67a26dc9a 100644 --- a/lib/chef/knife/cookbook_upload.rb +++ b/lib/chef/knife/cookbook_upload.rb @@ -2,7 +2,7 @@ # Author:: Adam Jacob (<adam@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) # Author:: Nuo Yan (<yan.nuo@gmail.com>) -# Copyright:: Copyright 2009-2016, Chef Software Inc. +# Copyright:: Copyright 2009-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -146,12 +146,12 @@ class Chef end if upload_failures == 0 - ui.info "Uploaded #{upload_ok} cookbook#{upload_ok > 1 ? "s" : ""}." + ui.info "Uploaded #{upload_ok} cookbook#{upload_ok == 1 ? "" : "s"}." elsif upload_failures > 0 && upload_ok > 0 - ui.warn "Uploaded #{upload_ok} cookbook#{upload_ok > 1 ? "s" : ""} ok but #{upload_failures} " + - "cookbook#{upload_failures > 1 ? "s" : ""} upload failed." + ui.warn "Uploaded #{upload_ok} cookbook#{upload_ok == 1 ? "" : "s"} ok but #{upload_failures} " + + "cookbook#{upload_failures == 1 ? "" : "s"} upload failed." elsif upload_failures > 0 && upload_ok == 0 - ui.error "Failed to upload #{upload_failures} cookbook#{upload_failures > 1 ? "s" : ""}." + ui.error "Failed to upload #{upload_failures} cookbook#{upload_failures == 1 ? "" : "s"}." exit 1 end end @@ -172,7 +172,7 @@ class Chef if ! upload_set.has_key?(cookbook_name) upload_set[cookbook_name] = cookbook_repo[cookbook_name] if config[:depends] - upload_set[cookbook_name].metadata.dependencies.each { |dep, ver| @name_args << dep } + upload_set[cookbook_name].metadata.dependencies.each_key { |dep| @name_args << dep } end end rescue Exceptions::CookbookNotFoundInRepo => e diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb index 9b16b94910..adbdee1858 100644 --- a/lib/chef/knife/core/bootstrap_context.rb +++ b/lib/chef/knife/core/bootstrap_context.rb @@ -255,7 +255,7 @@ validation_client_name "#{@chef_config[:validation_client_name]}" content << "mkdir #{file_on_node}\n" else content << "cat > #{file_on_node} <<'EOP'\n" + - f.read + "\nEOP\n" + f.read.gsub("'", "'\\\\''") + "\nEOP\n" end end end diff --git a/lib/chef/knife/core/status_presenter.rb b/lib/chef/knife/core/status_presenter.rb index f55f9abcbb..bb6766c6ac 100644 --- a/lib/chef/knife/core/status_presenter.rb +++ b/lib/chef/knife/core/status_presenter.rb @@ -101,9 +101,10 @@ class Chef fqdn = (node[:ec2] && node[:ec2][:public_hostname]) || node[:fqdn] name = node["name"] || node.name - hours, minutes, = time_difference_in_hms(node["ohai_time"]) + hours, minutes, seconds = time_difference_in_hms(node["ohai_time"]) hours_text = "#{hours} hour#{hours == 1 ? ' ' : 's'}" minutes_text = "#{minutes} minute#{minutes == 1 ? ' ' : 's'}" + seconds_text = "#{seconds} second#{seconds == 1 ? ' ' : 's'}" run_list = "#{node['run_list']}" if config[:run_list] if hours > 24 color = :red @@ -111,9 +112,12 @@ class Chef elsif hours >= 1 color = :yellow text = hours_text - else + elsif minutes >= 1 color = :green text = minutes_text + else + color = :green + text = seconds_text end line_parts = Array.new diff --git a/lib/chef/knife/core/ui.rb b/lib/chef/knife/core/ui.rb index 484c3ab3de..b2efbd8b8f 100644 --- a/lib/chef/knife/core/ui.rb +++ b/lib/chef/knife/core/ui.rb @@ -172,7 +172,7 @@ class Chef tf.sync = true tf.puts output tf.close - raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_using.html for details." unless system("#{config[:editor]} #{tf.path}") + raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_setup.html for details." unless system("#{config[:editor]} #{tf.path}") output = IO.read(tf.path) end diff --git a/lib/chef/knife/data_bag_secret_options.rb b/lib/chef/knife/data_bag_secret_options.rb index 4246c9edfa..a612004e15 100644 --- a/lib/chef/knife/data_bag_secret_options.rb +++ b/lib/chef/knife/data_bag_secret_options.rb @@ -95,7 +95,7 @@ class Chef ## # Determine if the user has specified an appropriate secret for encrypting data bag items. - # @returns boolean + # @return boolean def base_encryption_secret_provided?(need_encrypt_flag = true) validate_secrets diff --git a/lib/chef/knife/edit.rb b/lib/chef/knife/edit.rb index 46903e7420..4d7338f9f6 100644 --- a/lib/chef/knife/edit.rb +++ b/lib/chef/knife/edit.rb @@ -58,7 +58,7 @@ class Chef # Let the user edit the temporary file if !system("#{config[:editor]} #{file.path}") - raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_using.html for details." + raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_setup.html for details." end result_text = IO.read(file.path) diff --git a/lib/chef/knife/environment_compare.rb b/lib/chef/knife/environment_compare.rb index 8a2ef853d3..2e70783d3f 100644 --- a/lib/chef/knife/environment_compare.rb +++ b/lib/chef/knife/environment_compare.rb @@ -94,17 +94,17 @@ class Chef def cookbook_list(constraints) result = {} - constraints.each { |env, cb| result.merge!(cb) } + constraints.each_value { |cb| result.merge!(cb) } result end def matrix_output(cookbooks, constraints) rows = [ "" ] environments = [] - constraints.each { |e, v| environments << e.to_s } + constraints.each_key { |e| environments << e.to_s } columns = environments.count + 1 environments.each { |env| rows << ui.color(env, :bold) } - cookbooks.each do |c, v| + cookbooks.each_key do |c| total = [] environments.each { |n| total << constraints[n][c] } if total.uniq.count == 1 diff --git a/lib/chef/knife/index_rebuild.rb b/lib/chef/knife/index_rebuild.rb deleted file mode 100644 index 206b7b0fbf..0000000000 --- a/lib/chef/knife/index_rebuild.rb +++ /dev/null @@ -1,133 +0,0 @@ -# -# Author:: Daniel DeLeo (<dan@kallistec.com>) -# Copyright:: Copyright 2009-2016, Daniel DeLeo -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require "chef/knife" - -class Chef - class Knife - class IndexRebuild < Knife - - banner "knife index rebuild (options)" - option :yes, - :short => "-y", - :long => "--yes", - :boolean => true, - :description => "don't bother to ask if I'm sure" - - def run - api_info = grab_api_info - - if unsupported_version?(api_info) - unsupported_server_message(api_info) - exit 1 - else - deprecated_server_message - nag - output rest.post("/search/reindex", {}) - end - end - - def grab_api_info - # Since we don't yet have any endpoints that implement an - # OPTIONS handler, we need to get our version header - # information in a more roundabout way. We'll try to query - # for a node we know won't exist; the 404 response that comes - # back will give us what we want - dummy_node = "knife_index_rebuild_test_#{rand(1000000)}" - rest.get("/nodes/#{dummy_node}") - rescue Net::HTTPServerException => exception - r = exception.response - parse_api_info(r) - end - - # Only Chef 11+ servers will have version information in their - # headers, and only those servers will lack an API endpoint for - # index rebuilding. - def unsupported_version?(api_info) - !!api_info["version"] - end - - def unsupported_server_message(api_info) - ui.error("Rebuilding the index is not available via knife for #{server_type(api_info)}s version 11.0.0 and above.") - ui.info("Instead, run the '#{ctl_command(api_info)} reindex' command on the server itself.") - end - - def deprecated_server_message - ui.warn("'knife index rebuild' has been removed for Chef 11+ servers. It will continue to work for prior versions, however.") - end - - def nag - ui.info("This operation is destructive. Rebuilding the index may take some time.") - ui.confirm("Continue") - end - - # Chef 11 (and above) servers return various pieces of - # information about the server in an +x-ops-api-info+ header. - # This is a +;+ delimited string of key / value pairs, separated - # by +=+. - # - # Given a Net::HTTPResponse object, this method extracts this - # information (if present), and returns it as a hash. If no - # such header is found, an empty hash is returned. - def parse_api_info(response) - value = response["x-ops-api-info"] - if value - kv = value.split(";") - kv.inject({}) do |acc, pair| - k, v = pair.split("=") - acc[k] = v - acc - end - else - {} - end - end - - # Given an API info hash (see +#parse_api_info(response)+), - # return a string describing the kind of server we're - # interacting with (based on the +flavor+ field) - def server_type(api_info) - case api_info["flavor"] - when "osc" - "Open Source Chef Server" - when "opc" - "Private Chef Server" - else - # Generic fallback - "Chef Server" - end - end - - # Given an API info hash (see +#parse_api_info(response)+), - # return the name of the "server-ctl" command for the kind of - # server we're interacting with (based on the +flavor+ field) - def ctl_command(api_info) - case api_info["flavor"] - when "osc" - "chef-server-ctl" - when "opc" - "private-chef-ctl" - else - # Generic fallback - "chef-server-ctl" - end - end - - end - end -end diff --git a/lib/chef/knife/search.rb b/lib/chef/knife/search.rb index 2a68ec5108..94c33aa594 100644 --- a/lib/chef/knife/search.rb +++ b/lib/chef/knife/search.rb @@ -98,7 +98,9 @@ class Chef begin q.search(@type, @query, search_args) do |item| formatted_item = Hash.new - if item.is_a?(Hash) + if config[:id_only] + formatted_item = format_for_display({ "id" => item["__display_name"] }) + elsif item.is_a?(Hash) # doing a little magic here to set the correct name formatted_item[item["__display_name"]] = item.reject { |k| k == "__display_name" } else diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb index f4a025dba3..6d79cd10fd 100644 --- a/lib/chef/knife/ssh.rb +++ b/lib/chef/knife/ssh.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2009-2017, Chef Software Inc. +# Copyright:: Copyright 2009-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -46,11 +46,10 @@ class Chef :default => nil, :proc => lambda { |o| o.to_i } - option :attribute, + option :ssh_attribute, :short => "-a ATTR", :long => "--attribute ATTR", - :description => "The attribute to use for opening the connection - default depends on the context", - :proc => Proc.new { |key| Chef::Config[:knife][:ssh_attribute] = key.strip } + :description => "The attribute to use for opening the connection - default depends on the context" option :manual, :short => "-m", @@ -59,6 +58,10 @@ class Chef :description => "QUERY is a space separated list of servers", :default => false + option :prefix_attribute, + :long => "--prefix-attribute ATTR", + :description => "The attribute to use for prefixing the ouput - default depends on the context" + option :ssh_user, :short => "-x USERNAME", :long => "--ssh-user USERNAME", @@ -102,10 +105,6 @@ class Chef :description => "Enable SSH agent forwarding", :boolean => true - option :identity_file, - :long => "--identity-file IDENTITY_FILE", - :description => "The SSH identity file used for authentication. [DEPRECATED] Use --ssh-identity-file instead." - option :ssh_identity_file, :short => "-i IDENTITY_FILE", :long => "--ssh-identity-file IDENTITY_FILE", @@ -181,27 +180,34 @@ class Chef session_from_list(list) end - def get_ssh_attribute(node) + def get_prefix_attribute(item) + # Order of precedence for prefix + # 1) config value (cli or knife config) + # 2) nil + msg = "Using node attribute '%s' as the prefix: %s" + if item["prefix"] + Chef::Log.debug(sprintf(msg, config[:prefix_attribute], item["prefix"])) + item["prefix"] + else + nil + end + end + + def get_ssh_attribute(item) # Order of precedence for ssh target - # 1) command line attribute - # 2) configuration file - # 3) cloud attribute - # 4) fqdn - if node["config"] - Chef::Log.debug("Using node attribute '#{config[:attribute]}' as the ssh target: #{node["config"]}") - node["config"] - elsif Chef::Config[:knife][:ssh_attribute] - Chef::Log.debug("Using node attribute #{Chef::Config[:knife][:ssh_attribute]}: #{node["knife_config"]}") - node["knife_config"] - elsif node["cloud"] && - node["cloud"]["public_hostname"] && - !node["cloud"]["public_hostname"].empty? - Chef::Log.debug("Using node attribute 'cloud[:public_hostname]' automatically as the ssh target: #{node["cloud"]["public_hostname"]}") - node["cloud"]["public_hostname"] + # 1) config value (cli or knife config) + # 2) cloud attribute + # 3) fqdn + msg = "Using node attribute '%s' as the ssh target: %s" + if item["target"] + Chef::Log.debug(sprintf(msg, config[:ssh_attribute], item["target"])) + item["target"] + elsif !item.dig("cloud", "public_hostname").to_s.empty? + Chef::Log.debug(sprintf(msg, "cloud.public_hostname", item["cloud"]["public_hostname"])) + item["cloud"]["public_hostname"] else - # falling back to default of fqdn - Chef::Log.debug("Using node attribute 'fqdn' as the ssh target: #{node["fqdn"]}") - node["fqdn"] + Chef::Log.debug(sprintf(msg, "fqdn", item["fqdn"])) + item["fqdn"] end end @@ -212,14 +218,12 @@ class Chef separator = ui.presenter.attribute_field_separator - # if we've set an attribute to use on the command line - if config[:attribute] - required_attributes[:config] = config[:attribute].split(separator) + if config[:prefix_attribute] + required_attributes[:prefix] = config[:prefix_attribute].split(separator) end - # if we've configured an attribute in our config - if Chef::Config[:knife][:ssh_attribute] - required_attributes[:knife_config] = Chef::Config[:knife][:ssh_attribute].split(separator) + if config[:ssh_attribute] + required_attributes[:target] = config[:ssh_attribute].split(separator) end @search_count = 0 @@ -232,8 +236,9 @@ class Chef # returned node object host = get_ssh_attribute(item) next if host.nil? - ssh_port = item[:cloud].nil? ? nil : item[:cloud][:public_ssh_port] - srv = [host, ssh_port] + prefix = get_prefix_attribute(item) + ssh_port = item.dig("cloud", "public_ssh_port") + srv = [host, ssh_port, prefix] list.push(srv) end @@ -282,7 +287,8 @@ class Chef def session_from_list(list) list.each do |item| - host, ssh_port = item + host, ssh_port, prefix = item + prefix = host unless prefix Chef::Log.debug("Adding #{host}") session_opts = session_options(host, ssh_port) # Handle port overrides for the main connection. @@ -291,19 +297,21 @@ class Chef # Handle connection timeout session_opts[:timeout] = Chef::Config[:knife][:ssh_timeout] if Chef::Config[:knife][:ssh_timeout] session_opts[:timeout] = config[:ssh_timeout] if config[:ssh_timeout] + # Handle session prefix + session_opts[:properties] = { prefix: prefix } # Create the hostspec. hostspec = session_opts[:user] ? "#{session_opts.delete(:user)}@#{host}" : host # Connect a new session on the multi. session.use(hostspec, session_opts) - @longest = host.length if host.length > @longest + @longest = prefix.length if prefix.length > @longest end session end def fixup_sudo(command) - command.sub(/^sudo/, 'sudo -p \'knife sudo password: \'') + command.sub(/^sudo/, "sudo -p 'knife sudo password: '") end def print_data(host, data) @@ -342,9 +350,9 @@ class Chef chan.exec command do |ch, success| raise ArgumentError, "Cannot execute #{command}" unless success ch.on_data do |ichannel, data| - print_data(ichannel[:host], data) + print_data(ichannel.connection[:prefix], data) if data =~ /^knife sudo password: / - print_data(ichannel[:host], "\n") + print_data(ichannel.connection[:prefix], "\n") ichannel.send_data("#{get_password}\n") end end @@ -557,8 +565,7 @@ class Chef end def configure_ssh_identity_file - # config[:identity_file] is DEPRECATED in favor of :ssh_identity_file - config[:ssh_identity_file] = get_stripped_unfrozen_value(config[:ssh_identity_file] || config[:identity_file] || Chef::Config[:knife][:ssh_identity_file]) + config[:ssh_identity_file] = get_stripped_unfrozen_value(config[:ssh_identity_file] || Chef::Config[:knife][:ssh_identity_file]) end def configure_ssh_gateway_identity @@ -588,10 +595,6 @@ class Chef macterm when "cssh" cssh - when "csshx" - Chef::Log.warn("knife ssh csshx will be deprecated in a future release") - Chef::Log.warn("please use knife ssh cssh instead") - cssh else ssh_command(@name_args[1..-1].join(" ")) end diff --git a/lib/chef/knife/user_create.rb b/lib/chef/knife/user_create.rb index d21afb1059..c4a89f3707 100644 --- a/lib/chef/knife/user_create.rb +++ b/lib/chef/knife/user_create.rb @@ -78,6 +78,8 @@ knife user create for Open Source 11 Server is being deprecated. Open Source 11 Server user commands now live under the knife osc_user namespace. For backwards compatibility, we will forward this request to knife osc_user create. If you are using an Open Source 11 Server, please use that command to avoid this warning. +NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed +in Chef 15 which will be released April 2019. EOF end diff --git a/lib/chef/knife/user_delete.rb b/lib/chef/knife/user_delete.rb index cc92b4b36c..abfb45253e 100644 --- a/lib/chef/knife/user_delete.rb +++ b/lib/chef/knife/user_delete.rb @@ -37,6 +37,8 @@ knife user delete for Open Source 11 Server is being deprecated. Open Source 11 Server user commands now live under the knife osc_user namespace. For backwards compatibility, we will forward this request to knife osc_user delete. If you are using an Open Source 11 Server, please use that command to avoid this warning. +NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed +in Chef 15 which will be released April 2019. EOF end diff --git a/lib/chef/knife/user_edit.rb b/lib/chef/knife/user_edit.rb index bb80ede267..d184b85a6c 100644 --- a/lib/chef/knife/user_edit.rb +++ b/lib/chef/knife/user_edit.rb @@ -37,6 +37,8 @@ knife user edit for Open Source 11 Server is being deprecated. Open Source 11 Server user commands now live under the knife oc_user namespace. For backwards compatibility, we will forward this request to knife osc_user edit. If you are using an Open Source 11 Server, please use that command to avoid this warning. +NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed +in Chef 15 which will be released April 2019. EOF end diff --git a/lib/chef/knife/user_reregister.rb b/lib/chef/knife/user_reregister.rb index 8d2f2c1e73..172629faea 100644 --- a/lib/chef/knife/user_reregister.rb +++ b/lib/chef/knife/user_reregister.rb @@ -37,6 +37,8 @@ knife user reregister for Open Source 11 Server is being deprecated. Open Source 11 Server user commands now live under the knife osc_user namespace. For backwards compatibility, we will forward this request to knife osc_user reregister. If you are using an Open Source 11 Server, please use that command to avoid this warning. +NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed +in Chef 15 which will be released April 2019. EOF end diff --git a/lib/chef/knife/user_show.rb b/lib/chef/knife/user_show.rb index 04251c0863..6ba4ab5016 100644 --- a/lib/chef/knife/user_show.rb +++ b/lib/chef/knife/user_show.rb @@ -39,6 +39,8 @@ knife user show for Open Source 11 Server is being deprecated. Open Source 11 Server user commands now live under the knife osc_user namespace. For backwards compatibility, we will forward this request to knife osc_user show. If you are using an Open Source 11 Server, please use that command to avoid this warning. +NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed +in Chef 15 which will be released April 2019. EOF end diff --git a/lib/chef/knife/xargs.rb b/lib/chef/knife/xargs.rb index 7f436d7936..a316fb8cf7 100644 --- a/lib/chef/knife/xargs.rb +++ b/lib/chef/knife/xargs.rb @@ -181,7 +181,7 @@ class Chef def destroy_tempfiles(tempfiles) # Unlink the files now that we're done with them - tempfiles.keys.each { |tempfile| tempfile.close! } + tempfiles.each_key { |tempfile| tempfile.close! } end def xargs_files(command, tempfiles) diff --git a/lib/chef/mixin/language.rb b/lib/chef/mixin/language.rb deleted file mode 100644 index 3f53645a55..0000000000 --- a/lib/chef/mixin/language.rb +++ /dev/null @@ -1,48 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-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 "chef/dsl/platform_introspection" -require "chef/dsl/data_query" -require "chef/mixin/deprecation" - -class Chef - module Mixin - - # == [DEPRECATED] Chef::Mixin::DeprecatedLanguageModule - # This module is a temporary replacement for the previous - # Chef::Mixin::Language. That module's functionality was split into two - # modules, Chef::DSL::PlatformIntrospection, and Chef::DSL::DataQuery. - # - # This module includes both PlatformIntrospection and DataQuery to provide - # the same interfaces and behavior as the prior Mixin::Language. - # - # This module is loaded via const_missing hook when Chef::Mixin::Language - # is accessed. See chef/mixin/deprecation for details. - module DeprecatedLanguageModule - - include Chef::DSL::PlatformIntrospection - include Chef::DSL::DataQuery - - end - - deprecate_constant(:Language, DeprecatedLanguageModule, <<-EOM) -Chef::Mixin::Language is deprecated. Use either (or both) -Chef::DSL::PlatformIntrospection or Chef::DSL::DataQuery instead. -EOM - end -end diff --git a/lib/chef/mixin/language_include_attribute.rb b/lib/chef/mixin/language_include_attribute.rb deleted file mode 100644 index 7cb66dc272..0000000000 --- a/lib/chef/mixin/language_include_attribute.rb +++ /dev/null @@ -1,34 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-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 "chef/dsl/include_attribute" -require "chef/mixin/deprecation" - -class Chef - module Mixin - - # DEPRECATED: This is just here for compatibility, use - # Chef::DSL::IncludeAttribute instead. - - deprecate_constant(:LanguageIncludeAttribute, Chef::DSL::IncludeAttribute, <<-EOM) -Chef::Mixin::LanguageIncludeAttribute is deprecated. Use -Chef::DSL::IncludeAttribute instead. -EOM - - end -end diff --git a/lib/chef/mixin/language_include_recipe.rb b/lib/chef/mixin/language_include_recipe.rb deleted file mode 100644 index 97e384c7c4..0000000000 --- a/lib/chef/mixin/language_include_recipe.rb +++ /dev/null @@ -1,31 +0,0 @@ -# -# Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-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 "chef/dsl/include_recipe" -require "chef/mixin/deprecation" - -class Chef - module Mixin - - deprecate_constant(:LanguageIncludeRecipe, Chef::DSL::IncludeRecipe, <<-EOM) -Chef::Mixin::LanguageIncludeRecipe is deprecated, use Chef::DSL::IncludeRecipe -instead. -EOM - - end -end diff --git a/lib/chef/mixin/openssl.rb b/lib/chef/mixin/openssl.rb new file mode 100644 index 0000000000..e868da9ac4 --- /dev/null +++ b/lib/chef/mixin/openssl.rb @@ -0,0 +1,118 @@ +# +# Copyright:: Copyright 2013-2018, Chef Software Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +class Chef + module Mixin + module OpenSSL + def self.included(_base) + require "openssl" unless defined?(::OpenSSL) + end + + # determine the key filename from the cert filename + # @param [String] cert_filename the path to the certfile + # @return [String] the path to the keyfile + def get_key_filename(cert_filename) + cert_file_path, cert_filename = ::File.split(cert_filename) + cert_filename = ::File.basename(cert_filename, ::File.extname(cert_filename)) + cert_file_path + ::File::SEPARATOR + cert_filename + ".key" + end + + # is the key length a valid key length + # @param [Integer] number + # @return [Boolean] is length valid + def key_length_valid?(number) + number >= 1024 && ( number & (number - 1) == 0 ) + end + + # validate a dhparam file from path + # @param [String] dhparam_pem_path the path to the pem file + # @return [Boolean] is the key valid + def dhparam_pem_valid?(dhparam_pem_path) + # Check if the dhparam.pem file exists + # Verify the dhparam.pem file contains a key + return false unless ::File.exist?(dhparam_pem_path) + dhparam = ::OpenSSL::PKey::DH.new File.read(dhparam_pem_path) + dhparam.params_ok? + end + + # given either a key file path or key file content see if it's actually + # a private key + # @param [String] key_file the path to the keyfile or the key contents + # @param [String] key_password optional password to the keyfile + # @return [Boolean] is the key valid? + def priv_key_file_valid?(key_file, key_password = nil) + # if the file exists try to read the content + # if not assume we were passed the key and set the string to the content + key_content = ::File.exist?(key_file) ? File.read(key_file) : key_file + + begin + key = ::OpenSSL::PKey::RSA.new key_content, key_password + rescue ::OpenSSL::PKey::RSAError + return false + end + key.private? + end + + # generate a dhparam file + # @param [String] key_length the length of the key + # @param [Integer] generator the dhparam generator to use + # @return [OpenSSL::PKey::DH] + def gen_dhparam(key_length, generator) + raise ArgumentError, "Key length must be a power of 2 greater than or equal to 1024" unless key_length_valid?(key_length) + raise TypeError, "Generator must be an integer" unless generator.is_a?(Integer) + + ::OpenSSL::PKey::DH.new(key_length, generator) + end + + # generate an RSA private key given key length + # @param [Integer] key_length the key length of the private key + # @return [OpenSSL::PKey::DH] + def gen_rsa_priv_key(key_length) + raise ArgumentError, "Key length must be a power of 2 greater than or equal to 1024" unless key_length_valid?(key_length) + + ::OpenSSL::PKey::RSA.new(key_length) + end + + # generate pem format of the public key given a private key + # @param [String] priv_key either the contents of the private key or the path to the file + # @param [String] priv_key_password optional password for the private key + # @return [String] pem format of the public key + def gen_rsa_pub_key(priv_key, priv_key_password = nil) + # if the file exists try to read the content + # if not assume we were passed the key and set the string to the content + key_content = ::File.exist?(priv_key) ? File.read(priv_key) : priv_key + key = ::OpenSSL::PKey::RSA.new key_content, priv_key_password + key.public_key.to_pem + end + + # generate a pem file given a cipher, key, an optional key_password + # @param [OpenSSL::PKey::RSA] rsa_key the private key object + # @param [String] key_password the password for the private key + # @param [String] key_cipher the cipher to use + # @return [String] pem contents + def encrypt_rsa_key(rsa_key, key_password, key_cipher) + raise TypeError, "rsa_key must be a Ruby OpenSSL::PKey::RSA object" unless rsa_key.is_a?(::OpenSSL::PKey::RSA) + raise TypeError, "key_password must be a string" unless key_password.is_a?(String) + raise TypeError, "key_cipher must be a string" unless key_cipher.is_a?(String) + raise ArgumentError, "Specified key_cipher is not available on this system" unless ::OpenSSL::Cipher.ciphers.include?(key_cipher) + + cipher = ::OpenSSL::Cipher.new(key_cipher) + rsa_key.to_pem(cipher, key_password) + end + end + end +end diff --git a/lib/chef/mixin/powershell_out.rb b/lib/chef/mixin/powershell_out.rb index ab7cf00a72..1a757074c2 100644 --- a/lib/chef/mixin/powershell_out.rb +++ b/lib/chef/mixin/powershell_out.rb @@ -74,7 +74,7 @@ class Chef # Helper to build a powershell command around the script to run. # # @param script [String] script to run - # @retrurn [String] powershell command to execute + # @return [String] powershell command to execute def build_powershell_command(script) flags = [ # Hides the copyright banner at startup. diff --git a/lib/chef/mixin/recipe_definition_dsl_core.rb b/lib/chef/mixin/recipe_definition_dsl_core.rb deleted file mode 100644 index 6a9b12d31a..0000000000 --- a/lib/chef/mixin/recipe_definition_dsl_core.rb +++ /dev/null @@ -1,35 +0,0 @@ -#-- -# Author:: Adam Jacob (<adam@chef.io>) -# Author:: Christopher Walters (<cw@chef.io>) -# Copyright:: Copyright 2008-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. -# - -### -# NOTE: This file and constant are here only for backwards compatibility. -# New code should use Chef::DSL::Recipe instead. -# -# This constant (module name) will eventually be deprecated and then removed. -### - -require "chef/mixin/deprecation" - -class Chef - module Mixin - deprecate_constant(:RecipeDefinitionDSLCore, Chef::DSL::Recipe, <<-EOM) -Chef::Mixin::RecipeDefinitionDSLCore is deprecated. Use Chef::DSL::Recipe instead. -EOM - end -end diff --git a/lib/chef/node.rb b/lib/chef/node.rb index 549bde0dbb..20134ca11b 100644 --- a/lib/chef/node.rb +++ b/lib/chef/node.rb @@ -2,7 +2,7 @@ # Author:: Christopher Brown (<cb@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) # Author:: Tim Hinderliter (<tim@chef.io>) -# 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"); @@ -47,9 +47,7 @@ class Chef def_delegators :attributes, :default_unless, :normal_unless, :override_unless, :set_unless def_delegators :attributes, :read, :read!, :write, :write!, :unlink, :unlink! - attr_accessor :recipe_list, :run_state, :override_runlist - - attr_accessor :chef_server_rest + attr_accessor :recipe_list, :run_state # RunContext will set itself as run_context via this setter when # initialized. This is needed so DSL::IncludeAttribute (in particular, @@ -300,6 +298,7 @@ class Chef @primary_runlist end + attr_writer :override_runlist def override_runlist(*args) args.length > 0 ? @override_runlist.reset!(args) : @override_runlist end diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb index 2998866bb2..389968f543 100644 --- a/lib/chef/node/attribute.rb +++ b/lib/chef/node/attribute.rb @@ -17,7 +17,6 @@ # limitations under the License. # -require "chef/node/mixin/deep_merge_cache" require "chef/node/mixin/immutablize_hash" require "chef/node/mixin/state_tracking" require "chef/node/immutable_collections" @@ -45,7 +44,6 @@ class Chef # expects. This include should probably be deleted? include Enumerable - include Chef::Node::Mixin::DeepMergeCache include Chef::Node::Mixin::StateTracking include Chef::Node::Mixin::ImmutablizeHash @@ -187,6 +185,9 @@ class Chef # return the automatic level attribute component attr_reader :automatic + # return the immutablemash deep merge cache + attr_reader :deep_merge_cache + def initialize(normal, default, override, automatic, node = nil) @default = VividMash.new(default, self, node, :default) @env_default = VividMash.new({}, self, node, :env_default) @@ -202,7 +203,8 @@ class Chef @automatic = VividMash.new(automatic, self, node, :automatic) - super(nil, self, node, :merged) + @deep_merge_cache = ImmutableMash.new({}, self, node, :merged) + @__node__ = node end # Debug what's going on with an attribute. +args+ is a path spec to the @@ -226,6 +228,22 @@ class Chef end end + def reset + @deep_merge_cache = ImmutableMash.new({}, self, @__node__, :merged) + end + + def reset_cache(*path) + if path.empty? + reset + else + container = read(*path) + case container + when Hash, Array + container.reset + end + end + end + # Set the cookbook level default attribute component to +new_data+. def default=(new_data) reset @@ -290,7 +308,7 @@ class Chef # clears attributes from all precedence levels def rm(*args) - with_deep_merged_return_value(self, *args) do + with_deep_merged_return_value(combined_all, *args) do rm_default(*args) rm_normal(*args) rm_override(*args) @@ -337,6 +355,9 @@ class Chef def with_deep_merged_return_value(obj, *path, last) hash = obj.read(*path) return nil unless hash.is_a?(Hash) + # coerce from immutablemash/vividmash to plain-old Hash + # also de-immutablizes and dup's the return value correctly in chef-13 + hash = hash.to_hash ret = hash[last] yield ret @@ -398,16 +419,16 @@ class Chef # all of node['foo'] even if the user only requires node['foo']['bar']['baz']. # - def merged_attributes(*path) - merge_all(path) + def combined_override(*path) + merge_overrides(path) end - def combined_override(*path) - immutablize(merge_overrides(path)) + def combined_all(*path) + path.empty? ? self : read(*path) end def combined_default(*path) - immutablize(merge_defaults(path)) + merge_defaults(path) end def normal_unless(*args) @@ -476,6 +497,14 @@ class Chef merged_attributes.to_s end + def [](key) + @deep_merge_cache[key] + end + + def merged_attributes + @deep_merge_cache + end + def inspect "#<#{self.class} " << (COMPONENTS + [:@merged_attributes, :@properties]).map do |iv| "#{iv}=#{instance_variable_get(iv).inspect}" @@ -484,7 +513,14 @@ class Chef private - # Helper method for merge_all/merge_defaults/merge_overrides. + # For elements like Fixnums, true, nil... + def safe_dup(e) + e.dup + rescue TypeError + e + end + + # Helper method for merge_defaults/merge_overrides. # # apply_path(thing, [ "foo", "bar", "baz" ]) = thing["foo"]["bar"]["baz"] # @@ -514,34 +550,6 @@ class Chef end end - # For elements like Fixnums, true, nil... - def safe_dup(e) - e.dup - rescue TypeError - e - end - - # Deep merge all attribute levels using hash-only merging between different precidence - # levels (so override arrays completely replace arrays set at any default level). - # - # The path allows for selectively deep-merging a subtree of the node object. - # - # @param path [Array] Array of args to method chain to descend into the node object - # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object - def merge_all(path) - components = [ - merge_defaults(path), - apply_path(@normal, path), - merge_overrides(path), - apply_path(@automatic, path), - ] - - ret = components.inject(NIL) do |merged, component| - hash_only_merge!(merged, component) - end - ret == NIL ? nil : ret - end - # Deep merge the default attribute levels with array merging. # # The path allows for selectively deep-merging a subtree of the node object. @@ -613,38 +621,6 @@ class Chef end end - # @api private - def hash_only_merge!(merge_onto, merge_with) - # If there are two Hashes, recursively merge. - if merge_onto.kind_of?(Hash) && merge_with.kind_of?(Hash) - merge_with.each do |key, merge_with_value| - value = - if merge_onto.has_key?(key) - hash_only_merge!(safe_dup(merge_onto[key]), merge_with_value) - else - merge_with_value - end - - # internal_set bypasses converting keys, does convert values and allows writing to immutable mashes - merge_onto.internal_set(key, value) - end - merge_onto - - # If merge_with is nil, don't replace merge_onto - elsif merge_with.nil? - merge_onto - - # In all other cases, replace merge_onto with merge_with - else - if merge_with.kind_of?(Hash) - Chef::Node::ImmutableMash.new(merge_with) - elsif merge_with.kind_of?(Array) - Chef::Node::ImmutableArray.new(merge_with) - else - merge_with - end - end - end end end end diff --git a/lib/chef/node/attribute_collections.rb b/lib/chef/node/attribute_collections.rb index a31b2d2b9b..6922bcf200 100644 --- a/lib/chef/node/attribute_collections.rb +++ b/lib/chef/node/attribute_collections.rb @@ -1,6 +1,6 @@ #-- # Author:: Daniel DeLeo (<dan@chef.io>) -# Copyright:: Copyright 2012-2017, 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"); @@ -63,13 +63,13 @@ class Chef MUTATOR_METHODS.each do |mutator| define_method(mutator) do |*args, &block| ret = super(*args, &block) - send_reset_cache + send_reset_cache(__path__) ret end end def delete(key, &block) - send_reset_cache(__path__, key) + send_reset_cache(__path__) super end @@ -147,13 +147,13 @@ class Chef # object. def delete(key, &block) - send_reset_cache(__path__, key) + send_reset_cache(__path__) super end MUTATOR_METHODS.each do |mutator| define_method(mutator) do |*args, &block| - send_reset_cache + send_reset_cache(__path__) super(*args, &block) end end @@ -174,8 +174,8 @@ class Chef def []=(key, value) ret = super - send_reset_cache(__path__, key) - ret + send_reset_cache(__path__) + ret # rubocop:disable Lint/Void end alias :attribute? :has_key? diff --git a/lib/chef/node/common_api.rb b/lib/chef/node/common_api.rb index a703c1ef54..fc0ffc57a5 100644 --- a/lib/chef/node/common_api.rb +++ b/lib/chef/node/common_api.rb @@ -1,5 +1,5 @@ #-- -# Copyright:: Copyright 2016, Chef Software, Inc. +# Copyright:: Copyright 2016-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/lib/chef/node/immutable_collections.rb b/lib/chef/node/immutable_collections.rb index 848e12d2df..dc8ead9176 100644 --- a/lib/chef/node/immutable_collections.rb +++ b/lib/chef/node/immutable_collections.rb @@ -1,5 +1,5 @@ #-- -# Copyright:: Copyright 2012-2017, 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"); @@ -30,22 +30,16 @@ class Chef e end - def convert_value(value) + def convert_value(value, path = nil) case value when Hash - ImmutableMash.new(value, __root__, __node__, __precedence__) + ImmutableMash.new({}, __root__, __node__, __precedence__, path) when Array - ImmutableArray.new(value, __root__, __node__, __precedence__) - when ImmutableMash, ImmutableArray - value + ImmutableArray.new([], __root__, __node__, __precedence__, path) else safe_dup(value).freeze end end - - def immutablize(value) - convert_value(value) - end end # == ImmutableArray @@ -59,17 +53,51 @@ class Chef # Chef::Node::Attribute's values, it overrides all reader methods to # detect staleness and raise an error if accessed when stale. class ImmutableArray < Array + alias_method :internal_clear, :clear + alias_method :internal_replace, :replace + alias_method :internal_push, :<< + alias_method :internal_to_a, :to_a + alias_method :internal_each, :each + private :internal_push, :internal_replace, :internal_clear, :internal_each + protected :internal_to_a + include Immutablize - alias :internal_push :<< - private :internal_push + methods = Array.instance_methods - Object.instance_methods + + [ :!, :!=, :<=>, :==, :===, :eql?, :to_s, :hash, :key, :has_key?, :inspect, :pretty_print, :pretty_print_inspect, :pretty_print_cycle, :pretty_print_instance_variables ] - def initialize(array_data = []) - array_data.each do |value| - internal_push(immutablize(value)) + methods.each do |method| + define_method method do |*args, &block| + ensure_generated_cache! + super(*args, &block) + end + end + + def each + ensure_generated_cache! + # aggressively pre generate the cache, works around ruby being too smart and fiddling with internals + internal_each { |i| i.ensure_generated_cache! if i.respond_to?(:ensure_generated_cache!) } + super + end + + # because sometimes ruby gives us back Arrays or ImmutableArrays out of objects from things like #uniq or array slices + def return_normal_array(array) + if array.respond_to?(:internal_to_a, true) + array.internal_to_a + else + array.to_a end end + def uniq + ensure_generated_cache! + return_normal_array(super) + end + + def initialize(array_data = []) + # Immutable collections no longer have initialized state + end + # For elements like Fixnums, true, nil... def safe_dup(e) e.dup @@ -96,8 +124,81 @@ class Chef alias_method :to_array, :to_a + def [](*args) + ensure_generated_cache! + args.length > 1 ? return_normal_array(super) : super # correctly handle array slices + end + + def reset + @generated_cache = false + @short_circuit_attr_level = nil + internal_clear # redundant? + end + + # @api private + def ensure_generated_cache! + generate_cache unless @generated_cache + @generated_cache = true + end + + # This can be set to e.g. [ :@default ] by the parent container to cause this container + # to only use the default level and to bypass deep merging (the common case is either + # default-level or automatic-level and we aren't doing any deep merging). Right now it + # "optimized" for the case where we're no longer merging anything and only tracking a + # single level, and setting this to anything other than a size=1 array would behave + # in a broken fashion. That could be fixed, but the perf boost would likely not be + # that large in the typical case. + # + # @api private + attr_accessor :short_circuit_attr_levels + private + # deep merging of array attribute within normal and override where they are merged together + def combined_components(components) + combined_values = nil + components.each do |component| + values = __node__.attributes.instance_variable_get(component).read(*__path__) + next unless values.is_a?(Array) + @tracked_components << component + combined_values ||= [] + combined_values += values + end + combined_values + end + + def get_array(component) + array = __node__.attributes.instance_variable_get(component).read(*__path__) + if array.is_a?(Array) + @tracked_components << component + array + end # else nil + end + + def generate_cache + internal_clear + components = [] + @tracked_components = [] + if short_circuit_attr_levels + components << get_array(short_circuit_attr_levels.first) + else + components << combined_components(Attribute::DEFAULT_COMPONENTS) + components << get_array(:@normal) + components << combined_components(Attribute::OVERRIDE_COMPONENTS) + components << get_array(:@automatic) + end + highest = components.compact.last + if highest.is_a?(Array) + internal_replace( highest.each_with_index.map { |x, i| convert_value(x, __path__ + [ i ] ) } ) + end + if @tracked_components.size == 1 + # tracked_components is accurate enough to tell us if we're not really merging + internal_each do |key, value| + value.short_circuit_attr_levels = @tracked_components if value.respond_to?(:short_circuit_attr_levels) + end + end + end + # needed for __path__ def convert_key(key) key @@ -120,19 +221,31 @@ class Chef # it is stale. # * Values can be accessed in attr_reader-like fashion via method_missing. class ImmutableMash < Mash + alias_method :internal_clear, :clear + alias_method :internal_key?, :key? # FIXME: could bypass convert_key in Mash for perf + alias_method :internal_each, :each + include Immutablize include CommonAPI + methods = Hash.instance_methods - Object.instance_methods + + [ :!, :!=, :<=>, :==, :===, :eql?, :to_s, :hash, :key, :has_key?, :inspect, :pretty_print, :pretty_print_inspect, :pretty_print_cycle, :pretty_print_instance_variables ] + + methods.each do |method| + define_method method do |*args, &block| + ensure_generated_cache! + super(*args, &block) + end + end + # this is for deep_merge usage, chef users must never touch this API # @api private def internal_set(key, value) - regular_writer(key, convert_value(value)) + regular_writer(key, convert_value(value, __path__ + [ key ])) end def initialize(mash_data = {}) - mash_data.each do |key, value| - internal_set(key, value) - end + # Immutable collections no longer have initialized state end alias :attribute? :has_key? @@ -168,11 +281,53 @@ class Chef alias_method :to_hash, :to_h - # For elements like Fixnums, true, nil... - def safe_dup(e) - e.dup - rescue TypeError - e + def [](key) + ensure_generated_cache! + super + end + + def reset + @generated_cache = false + @short_circuit_attr_level = nil + internal_clear # redundant? + end + + # @api private + def ensure_generated_cache! + generate_cache unless @generated_cache + @generated_cache = true + end + + # @api private + attr_accessor :short_circuit_attr_levels + + private + + def generate_cache + internal_clear + components = short_circuit_attr_levels ? short_circuit_attr_levels : Attribute::COMPONENTS.reverse + # tracked_components is not entirely accurate due to the short-circuit + tracked_components = [] + components.each do |component| + subhash = __node__.attributes.instance_variable_get(component).read(*__path__) + unless subhash.nil? # FIXME: nil is used for not present + tracked_components << component + if subhash.kind_of?(Hash) + subhash.each_key do |key| + next if internal_key?(key) + internal_set(key, subhash[key]) + end + else + break + end + end + end + if tracked_components.size == 1 + # tracked_components is accurate enough to tell us if we're not really merging + internal_each do |key, value| + value.short_circuit_attr_levels = tracked_components if value.respond_to?(:short_circuit_attr_levels) + end + end end prepend Chef::Node::Mixin::StateTracking diff --git a/lib/chef/node/mixin/state_tracking.rb b/lib/chef/node/mixin/state_tracking.rb index 5958973024..690d261df6 100644 --- a/lib/chef/node/mixin/state_tracking.rb +++ b/lib/chef/node/mixin/state_tracking.rb @@ -1,5 +1,5 @@ #-- -# Copyright:: Copyright 2016, Chef Software, Inc. +# Copyright:: Copyright 2016-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,11 +24,12 @@ class Chef attr_reader :__node__ attr_reader :__precedence__ - def initialize(data = nil, root = self, node = nil, precedence = nil) + def initialize(data = nil, root = self, node = nil, precedence = nil, path = nil) # __path__ and __root__ must be nil when we call super so it knows # to avoid resetting the cache on construction data.nil? ? super() : super(data) - @__path__ = [] + @__path__ = path + @__path__ ||= [] @__root__ = root @__node__ = node @__precedence__ = precedence @@ -76,9 +77,8 @@ class Chef end end - def send_reset_cache(path = nil, key = nil) - next_path = [ path, key ].flatten.compact - __root__.reset_cache(next_path.first) if !__root__.nil? && __root__.respond_to?(:reset_cache) && !next_path.nil? + def send_reset_cache(path) + __root__.reset_cache(*path) if !__root__.nil? && __root__.respond_to?(:reset_cache) && !path.nil? end def copy_state_to(ret, next_path) diff --git a/lib/chef/node_map.rb b/lib/chef/node_map.rb index 25b1f57d44..dde93a437d 100644 --- a/lib/chef/node_map.rb +++ b/lib/chef/node_map.rb @@ -16,6 +16,25 @@ # limitations under the License. # +# +# example of a NodeMap entry for the user resource (as typed on the DSL): +# +# :user=> +# [{:klass=>Chef::Resource::User::AixUser, :os=>"aix"}, +# {:klass=>Chef::Resource::User::DsclUser, :os=>"darwin"}, +# {:klass=>Chef::Resource::User::PwUser, :os=>"freebsd"}, +# {:klass=>Chef::Resource::User::LinuxUser, :os=>"linux"}, +# {:klass=>Chef::Resource::User::SolarisUser, +# :os=>["omnios", "solaris2"]}, +# {:klass=>Chef::Resource::User::WindowsUser, :os=>"windows"}], +# +# the entries in the array are pre-sorted into priority order (blocks/platform_version/platform/platform_family/os/none) so that +# the first entry's :klass that matches the filter is returned when doing a get. +# +# note that as this examples show filter values may be a scalar string or an array of scalar strings. +# +# XXX: confusingly, in the *_priority_map the :klass may be an array of Strings of class names +# class Chef class NodeMap @@ -31,13 +50,12 @@ class Chef # # @return [NodeMap] Returns self for possible chaining # - def set(key, value, platform: nil, platform_version: nil, platform_family: nil, os: nil, canonical: nil, override: nil, &block) - filters = {} - filters[:platform] = platform if platform - filters[:platform_version] = platform_version if platform_version - filters[:platform_family] = platform_family if platform_family - filters[:os] = os if os - new_matcher = { value: value, filters: filters } + def set(key, klass, platform: nil, platform_version: nil, platform_family: nil, os: nil, canonical: nil, override: nil, &block) + new_matcher = { klass: klass } + new_matcher[:platform] = platform if platform + new_matcher[:platform_version] = platform_version if platform_version + new_matcher[:platform_family] = platform_family if platform_family + new_matcher[:os] = os if os new_matcher[:block] = block if block new_matcher[:canonical] = canonical if canonical new_matcher[:override] = override if override @@ -48,7 +66,10 @@ class Chef map[key] ||= [] map[key].each_with_index do |matcher, index| cmp = compare_matchers(key, new_matcher, matcher) - insert_at ||= index if cmp && cmp <= 0 + if cmp && cmp <= 0 + insert_at = index + break + end end if insert_at map[key].insert(insert_at, new_matcher) @@ -68,11 +89,14 @@ class Chef # @param canonical [Boolean] `true` or `false` to match canonical or # non-canonical values only. `nil` to ignore canonicality. Default: `nil` # - # @return [Object] Value + # @return [Object] Class # def get(node, key, canonical: nil) - raise ArgumentError, "first argument must be a Chef::Node" unless node.is_a?(Chef::Node) || node.nil? - list(node, key, canonical: canonical).first + return nil unless map.has_key?(key) + map[key].map do |matcher| + return matcher[:klass] if node_matches?(node, matcher) && canonical_matches?(canonical, matcher) + end + nil end # @@ -85,23 +109,22 @@ class Chef # @param canonical [Boolean] `true` or `false` to match canonical or # non-canonical values only. `nil` to ignore canonicality. Default: `nil` # - # @return [Object] Value + # @return [Object] Class # def list(node, key, canonical: nil) - raise ArgumentError, "first argument must be a Chef::Node" unless node.is_a?(Chef::Node) || node.nil? return [] unless map.has_key?(key) map[key].select do |matcher| node_matches?(node, matcher) && canonical_matches?(canonical, matcher) - end.map { |matcher| matcher[:value] } + end.map { |matcher| matcher[:klass] } end # Seriously, don't use this, it's nearly certain to change on you # @return remaining # @api private - def delete_canonical(key, value) + def delete_canonical(key, klass) remaining = map[key] if remaining - remaining.delete_if { |matcher| matcher[:canonical] && Array(matcher[:value]) == Array(value) } + remaining.delete_if { |matcher| matcher[:canonical] && Array(matcher[:klass]) == Array(klass) } if remaining.empty? map.delete(key) remaining = nil @@ -161,7 +184,7 @@ class Chef def node_matches?(node, matcher) return true if !node - filters_match?(node, matcher[:filters]) && block_matches?(node, matcher[:block]) + filters_match?(node, matcher) && block_matches?(node, matcher[:block]) end def canonical_matches?(canonical, matcher) @@ -171,17 +194,17 @@ class Chef # @api private def dispatch_compare_matchers(key, new_matcher, matcher) - cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:block] } + cmp = compare_matcher_properties(new_matcher[:block], matcher[:block]) return cmp if cmp != 0 - cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:platform_version] } + cmp = compare_matcher_properties(new_matcher[:platform_version], matcher[:platform_version]) return cmp if cmp != 0 - cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:platform] } + cmp = compare_matcher_properties(new_matcher[:platform], matcher[:platform]) return cmp if cmp != 0 - cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:platform_family] } + cmp = compare_matcher_properties(new_matcher[:platform_family], matcher[:platform_family]) return cmp if cmp != 0 - cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:os] } + cmp = compare_matcher_properties(new_matcher[:os], matcher[:os]) return cmp if cmp != 0 - cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:override] } + cmp = compare_matcher_properties(new_matcher[:override], matcher[:override]) return cmp if cmp != 0 # If all things are identical, return 0 0 @@ -195,37 +218,32 @@ class Chef if cmp == 0 # Sort by class name (ascending) as well, if all other properties # are exactly equal - if new_matcher[:value].is_a?(Class) && !new_matcher[:override] - cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:value].name } + # XXX: remove this in Chef-14 and use last-writer-wins (prepend if they match) + if !new_matcher[:override] + # we only sort classes, which only sorts the handler array, this magically does not sort + # the priority array via the invisible else here. + if new_matcher[:klass].is_a?(Class) + cmp = compare_matcher_properties(new_matcher[:klass].name, matcher[:klass].name) + end end end cmp end - def compare_matcher_properties(new_matcher, matcher) - a = yield(new_matcher) - b = yield(matcher) + def compare_matcher_properties(a, b) + # falsity comparisons here handle both "nil" and "false" + return 1 if !a && b + return -1 if !b && a + return 0 if !a && !b - # Check for blcacklists ('!windows'). Those always come *after* positive + # Check for blacklists ('!windows'). Those always come *after* positive # whitelists. a_negated = Array(a).any? { |f| f.is_a?(String) && f.start_with?("!") } b_negated = Array(b).any? { |f| f.is_a?(String) && f.start_with?("!") } - if a_negated != b_negated - return 1 if a_negated - return -1 if b_negated - end + return 1 if a_negated && !b_negated + return -1 if b_negated && !a_negated - # We treat false / true and nil / not-nil with the same comparison - a = nil if a == false - b = nil if b == false - cmp = a <=> b - # This is the case where one is non-nil, and one is nil. The one that is - # nil is "greater" (i.e. it should come last). - if cmp.nil? - return 1 if a.nil? - return -1 if b.nil? - end - cmp + a <=> b end def map diff --git a/lib/chef/property.rb b/lib/chef/property.rb index a72e41a61e..9d0957dcdf 100644 --- a/lib/chef/property.rb +++ b/lib/chef/property.rb @@ -99,7 +99,7 @@ class Chef if options.has_key?(:name_attribute) # If we have both name_attribute and name_property and they differ, raise an error if options.has_key?(:name_property) - raise ArgumentError, "Cannot specify both name_property and name_attribute together on property #{self}." + raise ArgumentError, "name_attribute and name_property are functionally identical and both cannot be specified on a property at once. Use just one on property #{self}" end # replace name_property with name_attribute in place options = Hash[options.map { |k, v| k == :name_attribute ? [ :name_property, v ] : [ k, v ] }] @@ -107,7 +107,7 @@ class Chef end if options.has_key?(:default) && options.has_key?(:name_property) - raise ArgumentError, "Cannot specify both default and name_property/name_attribute together on property #{self}" + raise ArgumentError, "A property cannot be both a name_property/name_attribute and have a default value. Use one or the other on property #{self}" end # Recursively freeze the default if it isn't a lazy value. @@ -361,7 +361,7 @@ class Chef end if value.nil? && required? - raise Chef::Exceptions::ValidationFailed, "#{name} is required" + raise Chef::Exceptions::ValidationFailed, "#{name} is a required property" else value end @@ -386,7 +386,7 @@ class Chef value = set_value(resource, input_to_stored_value(resource, value)) if value.nil? && required? - raise Chef::Exceptions::ValidationFailed, "#{name} is required" + raise Chef::Exceptions::ValidationFailed, "#{name} is a required property" else value end @@ -457,7 +457,7 @@ class Chef # options. # # @param resource [Chef::Resource] The resource we're validating against - # (to provide context for the validate). + # (to provide context for the validation). # @param value The value to validate. # # @raise Chef::Exceptions::ValidationFailed If the value is invalid for @@ -514,18 +514,18 @@ class Chef # very confusing results. if property_redefines_method? resource_name = declared_in.respond_to?(:resource_name) ? declared_in.resource_name : declared_in - raise ArgumentError, "Property `#{name}` of resource `#{resource_name}` overwrites an existing method." + raise ArgumentError, "Property `#{name}` of resource `#{resource_name}` overwrites an existing method. A different name should be used for this property." end # We prefer this form because the property name won't show up in the # stack trace if you use `define_method`. declared_in.class_eval <<-EOM, __FILE__, __LINE__ + 1 def #{name}(value=NOT_PASSED) - raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given? + raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given? self.class.properties[#{name.inspect}].call(self, value) end def #{name}=(value) - raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given? + raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given? self.class.properties[#{name.inspect}].set(self, value) end EOM diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb index 1ebdfa6feb..327bf52a13 100644 --- a/lib/chef/provider.rb +++ b/lib/chef/provider.rb @@ -1,7 +1,7 @@ # # Author:: Adam Jacob (<adam@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) -# Copyright:: Copyright 2008-2016, 2009-2017, Chef Software Inc. +# Copyright:: Copyright 2008-2016, 2009-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,7 +38,6 @@ class Chef attr_accessor :run_context attr_reader :recipe_name - attr_reader :cookbook_name include Chef::Mixin::WhyRun extend Chef::Mixin::Provides @@ -250,7 +249,13 @@ class Chef properties_str = if new_resource.sensitive specified_properties.join(", ") else - specified_properties.map { |p| "#{p}=#{new_resource.send(p).inspect}" }.join(", ") + specified_properties.map do |property| + "#{property}=" << if new_resource.class.properties[property].sensitive? + "(suppressed sensitive property)" + else + new_resource.send(property).inspect + end + end.join(", ") end Chef::Log.debug("Skipping update of #{new_resource}: has not changed any of the specified properties #{properties_str}.") return false @@ -259,7 +264,7 @@ class Chef # Print the pretty green text and run the block property_size = modified.map { |p| p.size }.max modified.map! do |p| - properties_str = if new_resource.sensitive + properties_str = if new_resource.sensitive || new_resource.class.properties[p].sensitive? "(suppressed sensitive property)" else "#{new_resource.send(p).inspect} (was #{current_resource.send(p).inspect})" @@ -274,7 +279,7 @@ class Chef property_size = properties.map { |p| p.size }.max created = properties.map do |property| default = " (default value)" unless new_resource.property_is_set?(property) - properties_str = if new_resource.sensitive + properties_str = if new_resource.sensitive || new_resource.class.properties[property].sensitive? "(suppressed sensitive property)" else new_resource.send(property).inspect @@ -325,7 +330,7 @@ class Chef define_singleton_method(:inspect) { to_s } # Add a delegator for each explicit property that will get the *current* value # of the property by default instead of the *actual* value. - resource.class.properties.each do |name, property| + resource.class.properties.each_key do |name| class_eval(<<-EOM, __FILE__, __LINE__) def #{name}(*args, &block) # If no arguments were passed, we process "get" by defaulting diff --git a/lib/chef/provider/apt_preference.rb b/lib/chef/provider/apt_preference.rb index ff4ea02ff0..59c6fc7f6d 100644 --- a/lib/chef/provider/apt_preference.rb +++ b/lib/chef/provider/apt_preference.rb @@ -24,7 +24,7 @@ require "chef/log" class Chef class Provider class AptPreference < Chef::Provider - provides :apt_preference, os: "linux", platform_family: "debian" + provides :apt_preference, platform_family: "debian" APT_PREFERENCE_DIR = "/etc/apt/preferences.d".freeze diff --git a/lib/chef/provider/apt_repository.rb b/lib/chef/provider/apt_repository.rb index 2d86a6fce4..c16f1e5767 100644 --- a/lib/chef/provider/apt_repository.rb +++ b/lib/chef/provider/apt_repository.rb @@ -27,7 +27,7 @@ class Chef class AptRepository < Chef::Provider include Chef::Mixin::ShellOut - provides :apt_repository, os: "linux", platform_family: "debian" + provides :apt_repository, platform_family: "debian" LIST_APT_KEYS = "apt-key list".freeze LIST_APT_KEY_FINGERPRINTS = "apt-key adv --list-public-keys --with-fingerprint --with-colons".freeze diff --git a/lib/chef/provider/apt_update.rb b/lib/chef/provider/apt_update.rb index bfd9603e4e..9d794abcf0 100644 --- a/lib/chef/provider/apt_update.rb +++ b/lib/chef/provider/apt_update.rb @@ -23,7 +23,7 @@ require "chef/dsl/declare_resource" class Chef class Provider class AptUpdate < Chef::Provider - provides :apt_update, os: "linux", platform_family: "debian" + provides :apt_update, platform_family: "debian" APT_CONF_DIR = "/etc/apt/apt.conf.d" STAMP_DIR = "/var/lib/apt/periodic" diff --git a/lib/chef/provider/deploy.rb b/lib/chef/provider/deploy.rb deleted file mode 100644 index c4229d2441..0000000000 --- a/lib/chef/provider/deploy.rb +++ /dev/null @@ -1,470 +0,0 @@ -# -# Author:: Daniel DeLeo (<dan@kallistec.com>) -# Copyright:: Copyright 2008-2017, 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/mixin/from_file" -require "chef/provider/git" -require "chef/provider/subversion" -require "chef/dsl/recipe" -require "chef/util/path_helper" - -class Chef - class Provider - class Deploy < Chef::Provider - - include Chef::DSL::Recipe - include Chef::Mixin::FromFile - - attr_reader :scm_provider, :release_path, :shared_path, :previous_release_path - - def initialize(new_resource, run_context) - super(new_resource, run_context) - - # will resolve to either git or svn based on resource attributes, - # and will create a resource corresponding to that provider - @scm_provider = new_resource.scm_provider.new(new_resource, run_context) - - # @configuration is not used by Deploy, it is only for backwards compat with - # chef-deploy or capistrano hooks that might use it to get environment information - @configuration = new_resource.to_hash - @configuration[:environment] = @configuration[:environment] && @configuration[:environment]["RAILS_ENV"] - end - - def load_current_resource - @scm_provider.load_current_resource - @release_path = new_resource.deploy_to + "/releases/#{release_slug}" - @shared_path = new_resource.shared_path - end - - def sudo(command, &block) - execute(command, &block) - end - - def run(command, &block) - exec = execute(command, &block) - exec.user(new_resource.user) if new_resource.user - exec.group(new_resource.group) if new_resource.group - exec.cwd(release_path) unless exec.cwd - exec.environment(new_resource.environment) unless exec.environment - converge_by("execute #{command}") do - exec - end - end - - def define_resource_requirements - requirements.assert(:rollback) do |a| - a.assertion { all_releases[-2] } - a.failure_message(RuntimeError, "There is no release to rollback to!") - #There is no reason to assume 2 deployments in a single chef run, hence fails in whyrun. - end - - [ new_resource.before_migrate, new_resource.before_symlink, - new_resource.before_restart, new_resource.after_restart ].each do |script| - requirements.assert(:deploy, :force_deploy) do |a| - callback_file = "#{release_path}/#{script}" - a.assertion do - if script && script.class == String - ::File.exist?(callback_file) - else - true - end - end - a.failure_message(RuntimeError, "Can't find your callback file #{callback_file}") - a.whyrun("Would assume callback file #{callback_file} included in release") - end - end - end - - def action_deploy - save_release_state - if deployed?(release_path ) - if current_release?(release_path ) - Chef::Log.debug("#{new_resource} is the latest version") - else - rollback_to release_path - end - else - - with_rollback_on_error do - deploy - end - end - end - - def action_force_deploy - if deployed?(release_path) - converge_by("delete deployed app at #{release_path} prior to force-deploy") do - Chef::Log.info("Already deployed app at #{release_path}, forcing.") - FileUtils.rm_rf(release_path) - Chef::Log.info("#{new_resource} forcing deploy of already deployed app at #{release_path}") - end - end - - # Alternatives: - # * Move release_path directory before deploy and move it back when error occurs - # * Rollback to previous commit - # * Do nothing - because deploy is force, it will be retried in short time - # Because last is simplest, keep it - deploy - end - - def action_rollback - rollback_to all_releases[-2] - end - - def rollback_to(target_release_path) - @release_path = target_release_path - - rp_index = all_releases.index(release_path) - releases_to_nuke = all_releases[(rp_index + 1)..-1] - - rollback - - releases_to_nuke.each do |i| - converge_by("roll back by removing release #{i}") do - Chef::Log.info "#{new_resource} removing release: #{i}" - FileUtils.rm_rf i - end - release_deleted(i) - end - end - - def deploy - verify_directories_exist - update_cached_repo # no converge-by - scm provider will dothis - enforce_ownership - copy_cached_repo - install_gems - enforce_ownership - callback(:before_migrate, new_resource.before_migrate) - migrate - callback(:before_symlink, new_resource.before_symlink) - symlink - callback(:before_restart, new_resource.before_restart) - restart - callback(:after_restart, new_resource.after_restart) - cleanup! - Chef::Log.info "#{new_resource} deployed to #{new_resource.deploy_to}" - end - - def rollback - Chef::Log.info "#{new_resource} rolling back to previous release #{release_path}" - symlink - Chef::Log.info "#{new_resource} restarting with previous release" - restart - end - - def callback(what, callback_code = nil) - @collection = Chef::ResourceCollection.new - case callback_code - when Proc - Chef::Log.info "#{new_resource} running callback #{what}" - recipe_eval(&callback_code) - when String - run_callback_from_file("#{release_path}/#{callback_code}") - when nil - run_callback_from_file("#{release_path}/deploy/#{what}.rb") - end - end - - def migrate - run_symlinks_before_migrate - - if new_resource.migrate - enforce_ownership - - environment = new_resource.environment - env_info = environment && environment.map do |key_and_val| - "#{key_and_val.first}='#{key_and_val.last}'" - end.join(" ") - - converge_by("execute migration command #{new_resource.migration_command}") do - Chef::Log.info "#{new_resource} migrating #{new_resource.user} with environment #{env_info}" - shell_out!(new_resource.migration_command, run_options(:cwd => release_path, :log_level => :info)) - end - end - end - - def symlink - purge_tempfiles_from_current_release - link_tempfiles_to_current_release - link_current_release_to_production - Chef::Log.info "#{new_resource} updated symlinks" - end - - def restart - if restart_cmd = new_resource.restart_command - if restart_cmd.kind_of?(Proc) - Chef::Log.info("#{new_resource} restarting app with embedded recipe") - recipe_eval(&restart_cmd) - else - converge_by("restart app using command #{new_resource.restart_command}") do - Chef::Log.info("#{new_resource} restarting app") - shell_out!(new_resource.restart_command, run_options(:cwd => new_resource.current_path)) - end - end - end - end - - def cleanup! - converge_by("update release history data") do - release_created(release_path) - end - - chop = -1 - new_resource.keep_releases - all_releases[0..chop].each do |old_release| - converge_by("remove old release #{old_release}") do - Chef::Log.info "#{new_resource} removing old release #{old_release}" - FileUtils.rm_rf(old_release) - end - release_deleted(old_release) - end - end - - def all_releases - Dir.glob(Chef::Util::PathHelper.escape_glob_dir(new_resource.deploy_to) + "/releases/*").sort - end - - def update_cached_repo - if new_resource.svn_force_export - # TODO assertion, non-recoverable - @scm_provider must be svn if force_export? - svn_force_export - else - run_scm_sync - end - end - - def run_scm_sync - @scm_provider.run_action(:sync) - end - - def svn_force_export - Chef::Log.info "#{new_resource} exporting source repository" - @scm_provider.run_action(:force_export) - end - - def copy_cached_repo - target_dir_path = new_resource.deploy_to + "/releases" - converge_by("deploy from repo to #{target_dir_path} ") do - FileUtils.rm_rf(release_path) if ::File.exist?(release_path) - FileUtils.mkdir_p(target_dir_path) - FileUtils.cp_r(::File.join(new_resource.destination, "."), release_path, :preserve => true) - Chef::Log.info "#{new_resource} copied the cached checkout to #{release_path}" - end - end - - def enforce_ownership - converge_by("force ownership of #{new_resource.deploy_to} to #{new_resource.group}:#{new_resource.user}") do - FileUtils.chown_R(new_resource.user, new_resource.group, new_resource.deploy_to, :force => true) - Chef::Log.info("#{new_resource} set user to #{new_resource.user}") if new_resource.user - Chef::Log.info("#{new_resource} set group to #{new_resource.group}") if new_resource.group - end - end - - def verify_directories_exist - create_dir_unless_exists(new_resource.deploy_to) - create_dir_unless_exists(new_resource.shared_path) - end - - def link_current_release_to_production - converge_by(["remove existing link at #{new_resource.current_path}", - "link release #{release_path} into production at #{new_resource.current_path}"]) do - FileUtils.rm_f(new_resource.current_path) - begin - FileUtils.ln_sf(release_path, new_resource.current_path) - rescue => e - raise Chef::Exceptions::FileNotFound.new("Cannot symlink current release to production: #{e.message}") - end - Chef::Log.info "#{new_resource} linked release #{release_path} into production at #{new_resource.current_path}" - end - enforce_ownership - end - - def run_symlinks_before_migrate - links_info = new_resource.symlink_before_migrate.map { |src, dst| "#{src} => #{dst}" }.join(", ") - converge_by("make pre-migration symlinks: #{links_info}") do - new_resource.symlink_before_migrate.each do |src, dest| - begin - FileUtils.ln_sf(new_resource.shared_path + "/#{src}", release_path + "/#{dest}") - rescue => e - raise Chef::Exceptions::FileNotFound.new("Cannot symlink #{new_resource.shared_path}/#{src} to #{release_path}/#{dest} before migrate: #{e.message}") - end - end - Chef::Log.info "#{new_resource} made pre-migration symlinks" - end - end - - def link_tempfiles_to_current_release - dirs_info = new_resource.create_dirs_before_symlink.join(",") - new_resource.create_dirs_before_symlink.each do |dir| - create_dir_unless_exists(release_path + "/#{dir}") - end - Chef::Log.info("#{new_resource} created directories before symlinking: #{dirs_info}") - - links_info = new_resource.symlinks.map { |src, dst| "#{src} => #{dst}" }.join(", ") - converge_by("link shared paths into current release: #{links_info}") do - new_resource.symlinks.each do |src, dest| - begin - FileUtils.ln_sf(::File.join(new_resource.shared_path, src), ::File.join(release_path, dest)) - rescue => e - raise Chef::Exceptions::FileNotFound.new("Cannot symlink shared data #{::File.join(new_resource.shared_path, src)} to #{::File.join(release_path, dest)}: #{e.message}") - end - end - Chef::Log.info("#{new_resource} linked shared paths into current release: #{links_info}") - end - run_symlinks_before_migrate - enforce_ownership - end - - def create_dirs_before_symlink - end - - def purge_tempfiles_from_current_release - log_info = new_resource.purge_before_symlink.join(", ") - converge_by("purge directories in checkout #{log_info}") do - new_resource.purge_before_symlink.each { |dir| FileUtils.rm_rf(release_path + "/#{dir}") } - Chef::Log.info("#{new_resource} purged directories in checkout #{log_info}") - end - end - - protected - - # Internal callback, called after copy_cached_repo. - # Override if you need to keep state externally. - # Note that YOU are responsible for implementing whyrun-friendly behavior - # in any actions you take in this callback. - def release_created(release_path) - end - - # Note that YOU are responsible for using appropriate whyrun nomenclature - # Override if you need to keep state externally. - # Note that YOU are responsible for implementing whyrun-friendly behavior - # in any actions you take in this callback. - def release_deleted(release_path) - end - - def release_slug - raise Chef::Exceptions::Override, "You must override release_slug in #{self}" - end - - def install_gems - gem_resource_collection_runner.converge - end - - def gem_resource_collection_runner - child_context = run_context.create_child - gem_packages.each { |rbgem| child_context.resource_collection.insert(rbgem) } - Chef::Runner.new(child_context) - end - - def gem_packages - return [] unless ::File.exist?("#{release_path}/gems.yml") - gems = YAML.load(IO.read("#{release_path}/gems.yml")) - - gems.map do |g| - r = Chef::Resource::GemPackage.new(g[:name], run_context) - r.version g[:version] - r.action :install - r.source "http://gems.github.com" - r - end - end - - def run_options(run_opts = {}) - run_opts[:user] = new_resource.user if new_resource.user - run_opts[:group] = new_resource.group if new_resource.group - run_opts[:environment] = new_resource.environment if new_resource.environment - run_opts[:log_tag] = new_resource.to_s - run_opts[:log_level] ||= :debug - if run_opts[:log_level] == :info - if STDOUT.tty? && !Chef::Config[:daemon] && Chef::Log.info? - run_opts[:live_stream] = STDOUT - end - end - run_opts - end - - def run_callback_from_file(callback_file) - Chef::Log.info "#{new_resource} queueing checkdeploy hook #{callback_file}" - recipe_eval do - Dir.chdir(release_path) do - from_file(callback_file) if ::File.exist?(callback_file) - end - end - end - - def create_dir_unless_exists(dir) - if ::File.directory?(dir) - Chef::Log.debug "#{new_resource} not creating #{dir} because it already exists" - return false - end - converge_by("create new directory #{dir}") do - begin - FileUtils.mkdir_p(dir) - Chef::Log.debug "#{new_resource} created directory #{dir}" - if new_resource.user - FileUtils.chown(new_resource.user, nil, dir) - Chef::Log.debug("#{new_resource} set user to #{new_resource.user} for #{dir}") - end - if new_resource.group - FileUtils.chown(nil, new_resource.group, dir) - Chef::Log.debug("#{new_resource} set group to #{new_resource.group} for #{dir}") - end - rescue => e - raise Chef::Exceptions::FileNotFound.new("Cannot create directory #{dir}: #{e.message}") - end - end - end - - def with_rollback_on_error - yield - rescue ::Exception => e - if new_resource.rollback_on_error - Chef::Log.warn "Error on deploying #{release_path}: #{e.message}" - failed_release = release_path - - if previous_release_path - @release_path = previous_release_path - rollback - end - converge_by("remove failed deploy #{failed_release}") do - Chef::Log.info "Removing failed deploy #{failed_release}" - FileUtils.rm_rf failed_release - end - release_deleted(failed_release) - end - - raise - end - - def save_release_state - if ::File.exists?(new_resource.current_path) - release = ::File.readlink(new_resource.current_path) - @previous_release_path = release if ::File.exists?(release) - end - end - - def deployed?(release) - all_releases.include?(release) - end - - def current_release?(release) - @previous_release_path == release - end - end - end -end diff --git a/lib/chef/provider/deploy/revision.rb b/lib/chef/provider/deploy/revision.rb deleted file mode 100644 index 06138e4f05..0000000000 --- a/lib/chef/provider/deploy/revision.rb +++ /dev/null @@ -1,107 +0,0 @@ -# -# Author:: Daniel DeLeo (<dan@kallistec.com>) -# Author:: Tim Hinderliter (<tim@chef.io>) -# Author:: Seth Falcon (<seth@chef.io>) -# Copyright:: Copyright 2009-2016, Daniel DeLeo -# Copyright:: Copyright 2010-2016, Chef Software Inc. -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require "chef/provider" -require "chef/provider/deploy" -require "chef/json_compat" - -class Chef - class Provider - class Deploy - class Revision < Chef::Provider::Deploy - provides :deploy_revision - provides :deploy_branch - - def all_releases - sorted_releases - end - - def action_deploy - validate_release_history! - super - end - - def cleanup! - super - - known_releases = sorted_releases - - Dir["#{Chef::Util::PathHelper.escape_glob_dir(new_resource.deploy_to)}/releases/*"].each do |release_dir| - unless known_releases.include?(release_dir) - converge_by("Remove unknown release in #{release_dir}") do - FileUtils.rm_rf(release_dir) - end - end - end - end - - protected - - def release_created(release) - sorted_releases { |r| r.delete(release); r << release } - end - - def release_deleted(release) - sorted_releases { |r| r.delete(release) } - end - - def release_slug - scm_provider.revision_slug - end - - private - - def sorted_releases - cache = load_cache - if block_given? - yield cache - save_cache(cache) - end - cache - end - - def validate_release_history! - sorted_releases do |release_list| - release_list.each do |path| - release_list.delete(path) unless ::File.exist?(path) - end - end - end - - def sorted_releases_from_filesystem - Dir.glob(Chef::Util::PathHelper.escape_glob_dir(new_resource.deploy_to) + "/releases/*").sort_by { |d| ::File.ctime(d) } - end - - def load_cache - Chef::JSONCompat.parse(Chef::FileCache.load("revision-deploys/#{new_resource.name}")) - rescue Chef::Exceptions::FileNotFound - sorted_releases_from_filesystem - end - - def save_cache(cache) - Chef::FileCache.store("revision-deploys/#{new_resource.name}", Chef::JSONCompat.to_json(cache)) - cache - end - - end - end - end -end diff --git a/lib/chef/provider/deploy/timestamped.rb b/lib/chef/provider/deploy/timestamped.rb deleted file mode 100644 index 5486b092d3..0000000000 --- a/lib/chef/provider/deploy/timestamped.rb +++ /dev/null @@ -1,34 +0,0 @@ -# -# Author:: Daniel DeLeo (<dan@kallistec.com>) -# Copyright:: Copyright 2009-2016, Daniel DeLeo -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -class Chef - class Provider - class Deploy - class Timestamped < Chef::Provider::Deploy - provides :timestamped_deploy - provides :deploy - - protected - - def release_slug - Time.now.utc.strftime("%Y%m%d%H%M%S") - end - end - end - end -end diff --git a/lib/chef/provider/erl_call.rb b/lib/chef/provider/erl_call.rb deleted file mode 100644 index b73341bb16..0000000000 --- a/lib/chef/provider/erl_call.rb +++ /dev/null @@ -1,76 +0,0 @@ -# -# Author:: Joe Williams (<joe@joetify.com>) -# Copyright:: Copyright 2009-2016, Joe Williams -# 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/log" -require "chef/provider" - -class Chef - class Provider - class ErlCall < Chef::Provider - - provides :erl_call - - def initialize(node, new_resource) - super(node, new_resource) - end - - def load_current_resource - true - end - - def action_run - case new_resource.name_type - when "sname" - node = "-sname #{new_resource.node_name}" - when "name" - node = "-name #{new_resource.node_name}" - end - - if new_resource.cookie - cookie = "-c #{new_resource.cookie}" - else - cookie = "" - end - - if new_resource.distributed - distributed = "-s" - else - distributed = "" - end - - command = "erl_call -e #{distributed} #{node} #{cookie}" - - converge_by("run erlang block") do - so = shell_out!(command, input: new_resource.code) - - # fail if stderr contains anything - if so.stderr.length > 0 - raise Chef::Exceptions::ErlCall, so.stderr - end - - # fail if the first 4 characters aren't "{ok," - unless so.stdout[0..3].include?("{ok,") - raise Chef::Exceptions::ErlCall, so.stdout - end - - end - end - - end - end -end diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb index fea77dd7ea..86e7e5a5c4 100644 --- a/lib/chef/provider/file.rb +++ b/lib/chef/provider/file.rb @@ -339,7 +339,7 @@ class Chef if tempfile new_resource.verify.each do |v| if ! v.verify(tempfile.path) - raise Chef::Exceptions::ValidationFailed.new "Proposed content for #{new_resource.path} failed verification #{v}" + raise Chef::Exceptions::ValidationFailed.new "Proposed content for #{new_resource.path} failed verification #{new_resource.sensitive ? '[sensitive]' : v}" end end end diff --git a/lib/chef/provider/group/dscl.rb b/lib/chef/provider/group/dscl.rb index 71e42b36ba..fe152eda33 100644 --- a/lib/chef/provider/group/dscl.rb +++ b/lib/chef/provider/group/dscl.rb @@ -88,8 +88,12 @@ class Chef def gid_used?(gid) return false unless gid - groups_gids = safe_dscl("list", "/Groups", "gid") - !!( groups_gids =~ Regexp.new("#{Regexp.escape(gid.to_s)}\n") ) + search_gids = safe_dscl("search", "/Groups", "PrimaryGroupID", gid.to_s) + + # dscl -search should not return anything if the gid doesn't exist, + # but on the off-chance that it does, check whether the given gid is + # in the output. + !!(search_gids =~ /\b#{gid}\b/) end def set_gid diff --git a/lib/chef/provider/ifconfig.rb b/lib/chef/provider/ifconfig.rb index 5008d7877a..c8da5e255f 100644 --- a/lib/chef/provider/ifconfig.rb +++ b/lib/chef/provider/ifconfig.rb @@ -23,20 +23,14 @@ require "chef/resource/file" require "chef/exceptions" require "erb" -# Recipe example: -# -# int = {Hash with your network settings...} -# -# ifconfig int['ip'] do -# ignore_failure true -# device int['dev'] -# mask int['mask'] -# gateway int['gateway'] -# mtu int['mtu'] -# end - class Chef class Provider + # use the ifconfig resource to manage interfaces on *nix systems + # + # @example set a static ip on eth1 + # ifconfig '33.33.33.80' do + # device 'eth1' + # end class Ifconfig < Chef::Provider provides :ifconfig diff --git a/lib/chef/provider/launchd.rb b/lib/chef/provider/launchd.rb index 8281410d42..8d868784dd 100644 --- a/lib/chef/provider/launchd.rb +++ b/lib/chef/provider/launchd.rb @@ -17,7 +17,6 @@ # require "chef/provider" -require "chef/resource/launchd" require "chef/resource/file" require "chef/resource/cookbook_file" require "chef/resource/macosx_service" diff --git a/lib/chef/provider/log.rb b/lib/chef/provider/log.rb index fbbc053b5b..214f284fbb 100644 --- a/lib/chef/provider/log.rb +++ b/lib/chef/provider/log.rb @@ -17,37 +17,27 @@ # class Chef - class Provider - class Log - - # Chef log provider, allows logging to chef's logs from recipes + # Chef log provider, allows logging to chef's logs class ChefLog < Chef::Provider - provides :log # No concept of a 'current' resource for logs, this is a no-op # - # === Return - # true:: Always return true + # @return [true] Always returns true def load_current_resource true end # Write the log to Chef's log # - # === Return - # true:: Always return true + # @return [true] Always returns true def action_write Chef::Log.send(new_resource.level, new_resource.message) new_resource.updated_by_last_action(true) if Chef::Config[:count_log_resource_updates] end - end - end - end - end diff --git a/lib/chef/provider/package/dnf.rb b/lib/chef/provider/package/dnf.rb index 7843bc74fc..90a5596727 100644 --- a/lib/chef/provider/package/dnf.rb +++ b/lib/chef/provider/package/dnf.rb @@ -148,7 +148,7 @@ class Chef @available_version[index] end - # @returns Array<Version> + # @return [Array<Version>] def installed_version(index) @installed_version ||= [] @installed_version[index] ||= if new_resource.source diff --git a/lib/chef/provider/package/smartos.rb b/lib/chef/provider/package/smartos.rb index 8e4368f7c1..66d23554df 100644 --- a/lib/chef/provider/package/smartos.rb +++ b/lib/chef/provider/package/smartos.rb @@ -3,7 +3,7 @@ # Bryan McLellan (btm@loftninjas.org) # Matthew Landauer (matthew@openaustralia.org) # Ben Rockwood (benr@joyent.com) -# Copyright:: Copyright 2009-2016, Bryan McLellan, Matthew Landauer +# Copyright:: Copyright 2009-2018, Bryan McLellan, Matthew Landauer # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,7 +30,7 @@ class Chef attr_accessor :is_virtual_package provides :package, platform: "smartos" - provides :smartos_package, os: "solaris2", platform_family: "smartos" + provides :smartos_package, platform_family: "smartos" def load_current_resource Chef::Log.debug("#{new_resource} loading current resource") diff --git a/lib/chef/provider/reboot.rb b/lib/chef/provider/reboot.rb index 32dc38f788..c09fbaa2c0 100644 --- a/lib/chef/provider/reboot.rb +++ b/lib/chef/provider/reboot.rb @@ -21,9 +21,19 @@ require "chef/provider" class Chef class Provider + # Use the reboot resource to reboot a node, a necessary step with some + # installations on certain platforms. This resource is supported for use on + # the Microsoft Windows, macOS, and Linux platforms. + # + # In using this resource via notifications, it's important to *only* use + # immediate notifications. Delayed notifications produce unintuitive and + # probably undesired results. + # + # @since 12.0.0 class Reboot < Chef::Provider provides :reboot + # @return [void] def load_current_resource @current_resource ||= Chef::Resource::Reboot.new(new_resource.name) current_resource.reason(new_resource.reason) @@ -31,6 +41,8 @@ class Chef current_resource end + # add a reboot to the node run_context + # @return [void] def request_reboot node.run_context.request_reboot( :delay_mins => new_resource.delay_mins, diff --git a/lib/chef/provider/remote_directory.rb b/lib/chef/provider/remote_directory.rb index 6f4956de96..94de68c557 100644 --- a/lib/chef/provider/remote_directory.rb +++ b/lib/chef/provider/remote_directory.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# 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"); @@ -47,8 +47,6 @@ class Chef !!@overwrite end - attr_accessor :managed_files - # Hash containing keys of the paths for all the files that we sync, plus all their # parent directories. # @@ -153,7 +151,7 @@ class Chef # # FIXME: it should do breadth-first, see CHEF-5080 (please use a performant sort) # - # @return Array<String> The list of files to transfer + # @return [Array<String>] The list of files to transfer # @api private # def files_to_transfer diff --git a/lib/chef/provider/remote_file/http.rb b/lib/chef/provider/remote_file/http.rb index ad044f9e3c..4732253e5b 100644 --- a/lib/chef/provider/remote_file/http.rb +++ b/lib/chef/provider/remote_file/http.rb @@ -61,12 +61,13 @@ class Chef def fetch http = Chef::HTTP::Simple.new(uri, http_client_opts) + tempfile = Chef::FileContentManagement::Tempfile.new(@new_resource).tempfile if want_progress? - tempfile = http.streaming_request_with_progress(uri, headers) do |size, total| + tempfile = http.streaming_request_with_progress(uri, headers, tempfile) do |size, total| events.resource_update_progress(new_resource, size, total, progress_interval) end else - tempfile = http.streaming_request(uri, headers) + tempfile = http.streaming_request(uri, headers, tempfile) end if tempfile update_cache_control_data(tempfile, http.last_response) diff --git a/lib/chef/provider/route.rb b/lib/chef/provider/route.rb index be695dd83a..2784ae43bc 100644 --- a/lib/chef/provider/route.rb +++ b/lib/chef/provider/route.rb @@ -181,7 +181,7 @@ class Chef conf[dev] << config_file_contents(:delete) end end - conf.each do |k, v| + conf.each_key do |k| if new_resource.target == "default" network_file_name = "/etc/sysconfig/network" converge_by("write route default route to #{network_file_name}") do diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb index 58a43d27f8..fcfa34ddf9 100644 --- a/lib/chef/provider/service/debian.rb +++ b/lib/chef/provider/service/debian.rb @@ -53,7 +53,7 @@ class Chef requirements.assert(:all_actions) do |a| a.assertion { @so_priority.exitstatus == 0 } - a.failure_message Chef::Exceptions::Service, "/usr/sbin/update-rc.d -n -f #{current_resource.service_name} failed - #{@so_priority.inspect}" + a.failure_message Chef::Exceptions::Service, "/usr/sbin/update-rc.d -f #{current_resource.service_name} failed - #{@so_priority.inspect}" # This can happen if the service is not yet installed,so we'll fake it. a.whyrun ["Unable to determine priority of service, assuming service would have been correctly installed earlier in the run.", "Assigning temporary priorities to continue.", @@ -73,7 +73,7 @@ class Chef def get_priority priority = {} - @so_priority = shell_out!("/usr/sbin/update-rc.d -n -f #{current_resource.service_name} remove") + @so_priority = shell_out!("/usr/sbin/update-rc.d -f #{current_resource.service_name} remove") [@so_priority.stdout, @so_priority.stderr].each do |iop| iop.each_line do |line| diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb index 70b40f11ca..f2b1ec4262 100644 --- a/lib/chef/provider/service/solaris.rb +++ b/lib/chef/provider/service/solaris.rb @@ -54,6 +54,8 @@ class Chef end def enable_service + # Running service status to update maintenance status to invoke svcadm clear + service_status shell_out!(default_init_command, "clear", @new_resource.service_name) if @maintenance enable_flags = [ "-s", @new_resource.options ].flatten.compact shell_out!(default_init_command, "enable", *enable_flags, @new_resource.service_name) @@ -93,6 +95,9 @@ class Chef # dependency require_all/error svc:/milestone/multi-user:default (online) # $ + # Set the default value for maintenance + @maintenance = false + # load output into hash status = {} cmd.stdout.each_line do |line| diff --git a/lib/chef/provider/service/windows.rb b/lib/chef/provider/service/windows.rb index 931e320695..8503bd684d 100644 --- a/lib/chef/provider/service/windows.rb +++ b/lib/chef/provider/service/windows.rb @@ -19,6 +19,7 @@ # require "chef/provider/service/simple" +require "chef/win32_service_constants" if RUBY_PLATFORM =~ /mswin|mingw32|windows/ require "chef/win32/error" require "win32/service" @@ -30,6 +31,7 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service include Chef::Mixin::ShellOut include Chef::ReservedNames::Win32::API::Error rescue LoadError + include Chef::Win32ServiceConstants #Win32::Service.get_start_type AUTO_START = "auto start" @@ -50,18 +52,36 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service SERVICE_RIGHT = "SeServiceLogonRight" def load_current_resource - @current_resource = Chef::Resource::WindowsService.new(@new_resource.name) - @current_resource.service_name(@new_resource.service_name) - @current_resource.running(current_state == RUNNING) - Chef::Log.debug "#{@new_resource} running: #{@current_resource.running}" - case current_start_type - when AUTO_START - @current_resource.enabled(true) - when DISABLED - @current_resource.enabled(false) + @current_resource = Chef::Resource::WindowsService.new(new_resource.name) + current_resource.service_name(new_resource.service_name) + + if Win32::Service.exists?(current_resource.service_name) + current_resource.running(current_state == RUNNING) + Chef::Log.debug "#{new_resource} running: #{current_resource.running}" + case current_start_type + when AUTO_START + current_resource.enabled(true) + when DISABLED + current_resource.enabled(false) + end + Chef::Log.debug "#{new_resource} enabled: #{current_resource.enabled}" + + config_info = Win32::Service.config_info(current_resource.service_name) + current_resource.service_type(get_service_type(config_info[:service_type])) if config_info[:service_type] + current_resource.startup_type(get_start_type(config_info[:start_type])) if config_info[:start_type] + current_resource.error_control(get_error_control(config_info[:error_control])) if config_info[:error_control] + current_resource.binary_path_name(config_info[:binary_path_name]) if config_info[:binary_path_name] + current_resource.load_order_group(config_info[:load_order_group]) if config_info[:load_order_group] + current_resource.dependencies(config_info[:dependencies]) if config_info[:dependencies] + current_resource.run_as_user(config_info[:service_start_name]) if config_info[:service_start_name] + current_resource.display_name(config_info[:display_name]) if config_info[:display_name] + + if delayed_start = current_delayed_start + current_resource.delayed_start(delayed_start) + end end - Chef::Log.debug "#{@new_resource} enabled: #{@current_resource.enabled}" - @current_resource + + current_resource end def start_service @@ -175,6 +195,44 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service end end + action :create do + return if Win32::Service.exists?(new_resource.service_name) + + converge_by("create service #{new_resource.service_name}") do + Win32::Service.new(windows_service_config) + end + + converge_delayed_start + end + + action :delete do + return unless Win32::Service.exists?(new_resource.service_name) + + converge_by("delete service #{new_resource.service_name}") do + Win32::Service.delete(new_resource.service_name) + end + end + + action :configure do + unless Win32::Service.exists?(new_resource.service_name) + Chef::Log.debug "#{new_resource} does not exist - nothing to do" + return + end + + # Until #6300 is solved this is required + if new_resource.run_as_user == new_resource.class.properties[:run_as_user].default + new_resource.run_as_user = new_resource.class.properties[:run_as_user].default + end + + converge_if_changed :service_type, :startup_type, :error_control, + :binary_path_name, :load_order_group, :dependencies, + :run_as_user, :display_name do + Win32::Service.configure(windows_service_config(:configure)) + end + + converge_delayed_start + end + def action_enable if current_start_type != AUTO_START converge_by("enable service #{@new_resource}") do @@ -264,6 +322,14 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service Win32::Service.config_info(@new_resource.service_name).start_type end + def current_delayed_start + if service = Win32::Service.services.find { |x| x.service_name == @new_resource.service_name } + service.delayed_start + else + nil + end + end + # Helper method that waits for a status to change its state since state # changes aren't usually instantaneous. def wait_for_state(desired_state) @@ -306,4 +372,102 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service ) @new_resource.updated_by_last_action(true) end + + def windows_service_config(action = :create) + config = {} + + config[:service_name] = new_resource.service_name + config[:display_name] = new_resource.display_name if new_resource.display_name + config[:service_type] = new_resource.service_type if new_resource.service_type + config[:start_type] = new_resource.startup_type if new_resource.startup_type + config[:error_control] = new_resource.error_control if new_resource.error_control + config[:binary_path_name] = new_resource.binary_path_name if new_resource.binary_path_name + config[:load_order_group] = new_resource.load_order_group if new_resource.load_order_group + config[:dependencies] = new_resource.dependencies if new_resource.dependencies + config[:service_start_name] = new_resource.run_as_user unless new_resource.run_as_user.empty? + config[:password] = new_resource.run_as_password unless new_resource.run_as_user.empty? or new_resource.run_as_password.empty? + config[:description] = new_resource.description if new_resource.description + + case action + when :create + config[:desired_access] = new_resource.desired_access if new_resource.desired_access + end + + config + end + + def converge_delayed_start + config = {} + config[:service_name] = new_resource.service_name + config[:delayed_start] = new_resource.delayed_start + + # Until #6300 is solved this is required + if new_resource.delayed_start == new_resource.class.properties[:delayed_start].default + new_resource.delayed_start = new_resource.class.properties[:delayed_start].default + end + + converge_if_changed :delayed_start do + Win32::Service.configure(config) + end + end + + def get_service_type(service_type) + case service_type + when 'file system driver' + SERVICE_FILE_SYSTEM_DRIVER + when 'kernel driver' + SERVICE_KERNEL_DRIVER + when 'own process' + SERVICE_WIN32_OWN_PROCESS + when 'share proces' + SERVICE_WIN32_SHARE_PROCESS + when 'recognizer driver' + SERVICE_RECOGNIZER_DRIVER + when 'driver' + SERVICE_DRIVER + when 'win32' + SERVICE_WIN32 + when 'all' + SERVICE_TYPE_ALL + when 'own process, interactive' + SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS + when 'share process, interactive' + SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_SHARE_PROCESS + else + nil + end + end + + def get_start_type(start_type) + case start_type + when 'auto start' + SERVICE_AUTO_START + when 'boot start' + SERVICE_BOOT_START + when 'demand start' + SERVICE_DEMAND_START + when 'disabled' + SERVICE_DISABLED + when 'system start' + SERVICE_SYSTEM_START + else + nil + end + end + + def get_error_control(error_control) + case error_control + when 'critical' + SERVICE_ERROR_CRITICAL + when 'ignore' + SERVICE_ERROR_IGNORE + when 'normal' + SERVICE_ERROR_NORMAL + when 'severe' + SERVICE_ERROR_SEVERE + else + nil + end + end + end diff --git a/lib/chef/provider/systemd_unit.rb b/lib/chef/provider/systemd_unit.rb index a2ef64044b..e1853bd984 100644 --- a/lib/chef/provider/systemd_unit.rb +++ b/lib/chef/provider/systemd_unit.rb @@ -35,6 +35,7 @@ class Chef def load_current_resource @current_resource = Chef::Resource::SystemdUnit.new(new_resource.name) + current_resource.unit_name(new_resource.unit_name) current_resource.content(::File.read(unit_path)) if ::File.exist?(unit_path) current_resource.user(new_resource.user) current_resource.enabled(enabled?) @@ -57,7 +58,7 @@ class Chef def action_create if current_resource.content != new_resource.to_ini - converge_by("creating unit: #{new_resource.name}") do + converge_by("creating unit: #{new_resource.unit_name}") do manage_unit_file(:create) daemon_reload if new_resource.triggers_reload end @@ -66,7 +67,7 @@ class Chef def action_delete if ::File.exist?(unit_path) - converge_by("deleting unit: #{new_resource.name}") do + converge_by("deleting unit: #{new_resource.unit_name}") do manage_unit_file(:delete) daemon_reload if new_resource.triggers_reload end @@ -75,117 +76,117 @@ class Chef def action_enable if current_resource.static - Chef::Log.debug("#{new_resource.name} is a static unit, enabling is a NOP.") + Chef::Log.debug("#{new_resource.unit_name} is a static unit, enabling is a NOP.") end unless current_resource.enabled || current_resource.static - converge_by("enabling unit: #{new_resource.name}") do - systemctl_execute!(:enable, new_resource.name) + converge_by("enabling unit: #{new_resource.unit_name}") do + systemctl_execute!(:enable, new_resource.unit_name) end end end def action_disable if current_resource.static - Chef::Log.debug("#{new_resource.name} is a static unit, disabling is a NOP.") + Chef::Log.debug("#{new_resource.unit_name} is a static unit, disabling is a NOP.") end if current_resource.enabled && !current_resource.static - converge_by("disabling unit: #{new_resource.name}") do - systemctl_execute!(:disable, new_resource.name) + converge_by("disabling unit: #{new_resource.unit_name}") do + systemctl_execute!(:disable, new_resource.unit_name) end end end def action_mask unless current_resource.masked - converge_by("masking unit: #{new_resource.name}") do - systemctl_execute!(:mask, new_resource.name) + converge_by("masking unit: #{new_resource.unit_name}") do + systemctl_execute!(:mask, new_resource.unit_name) end end end def action_unmask if current_resource.masked - converge_by("unmasking unit: #{new_resource.name}") do - systemctl_execute!(:unmask, new_resource.name) + converge_by("unmasking unit: #{new_resource.unit_name}") do + systemctl_execute!(:unmask, new_resource.unit_name) end end end def action_start unless current_resource.active - converge_by("starting unit: #{new_resource.name}") do - systemctl_execute!(:start, new_resource.name) + converge_by("starting unit: #{new_resource.unit_name}") do + systemctl_execute!(:start, new_resource.unit_name) end end end def action_stop if current_resource.active - converge_by("stopping unit: #{new_resource.name}") do - systemctl_execute!(:stop, new_resource.name) + converge_by("stopping unit: #{new_resource.unit_name}") do + systemctl_execute!(:stop, new_resource.unit_name) end end end def action_restart - converge_by("restarting unit: #{new_resource.name}") do - systemctl_execute!(:restart, new_resource.name) + converge_by("restarting unit: #{new_resource.unit_name}") do + systemctl_execute!(:restart, new_resource.unit_name) end end def action_reload if current_resource.active - converge_by("reloading unit: #{new_resource.name}") do - systemctl_execute!(:reload, new_resource.name) + converge_by("reloading unit: #{new_resource.unit_name}") do + systemctl_execute!(:reload, new_resource.unit_name) end else - Chef::Log.debug("#{new_resource.name} is not active, skipping reload.") + Chef::Log.debug("#{new_resource.unit_name} is not active, skipping reload.") end end def action_try_restart - converge_by("try-restarting unit: #{new_resource.name}") do - systemctl_execute!("try-restart", new_resource.name) + converge_by("try-restarting unit: #{new_resource.unit_name}") do + systemctl_execute!("try-restart", new_resource.unit_name) end end def action_reload_or_restart - converge_by("reload-or-restarting unit: #{new_resource.name}") do - systemctl_execute!("reload-or-restart", new_resource.name) + converge_by("reload-or-restarting unit: #{new_resource.unit_name}") do + systemctl_execute!("reload-or-restart", new_resource.unit_name) end end def action_reload_or_try_restart - converge_by("reload-or-try-restarting unit: #{new_resource.name}") do - systemctl_execute!("reload-or-try-restart", new_resource.name) + converge_by("reload-or-try-restarting unit: #{new_resource.unit_name}") do + systemctl_execute!("reload-or-try-restart", new_resource.unit_name) end end def active? - systemctl_execute("is-active", new_resource.name).exitstatus == 0 + systemctl_execute("is-active", new_resource.unit_name).exitstatus == 0 end def enabled? - systemctl_execute("is-enabled", new_resource.name).exitstatus == 0 + systemctl_execute("is-enabled", new_resource.unit_name).exitstatus == 0 end def masked? - systemctl_execute(:status, new_resource.name).stdout.include?("masked") + systemctl_execute(:status, new_resource.unit_name).stdout.include?("masked") end def static? - systemctl_execute("is-enabled", new_resource.name).stdout.include?("static") + systemctl_execute("is-enabled", new_resource.unit_name).stdout.include?("static") end private def unit_path if new_resource.user - "/etc/systemd/user/#{new_resource.name}" + "/etc/systemd/user/#{new_resource.unit_name}" else - "/etc/systemd/system/#{new_resource.name}" + "/etc/systemd/system/#{new_resource.unit_name}" end end diff --git a/lib/chef/provider/user/dscl.rb b/lib/chef/provider/user/dscl.rb index 60167856d1..bc865b17c5 100644 --- a/lib/chef/provider/user/dscl.rb +++ b/lib/chef/provider/user/dscl.rb @@ -318,7 +318,7 @@ user password using shadow hash.") end def current_home_exists? - ::File.exist?(current_resource.home) + !!current_resource.home && ::File.exist?(current_resource.home) end def new_home_exists? diff --git a/lib/chef/provider/windows_path.rb b/lib/chef/provider/windows_path.rb index b31789b4b9..1c78e20606 100644 --- a/lib/chef/provider/windows_path.rb +++ b/lib/chef/provider/windows_path.rb @@ -23,9 +23,10 @@ require "chef/exceptions" class Chef class Provider class WindowsPath < Chef::Provider - include Chef::Mixin::WindowsEnvHelper if Chef::Platform.windows? + provides :windows_path + def load_current_resource @current_resource = Chef::Resource::WindowsPath.new(new_resource.name) @current_resource.path(new_resource.path) @@ -37,12 +38,10 @@ class Chef # the PATH environment variable. Ruby expects these to be expanded. # path = expand_path(new_resource.path) - converge_by "Adding #{new_resource.path} to path environment variable" do - declare_resource(:env, "path") do - action :modify - delim ::File::PATH_SEPARATOR - value path.tr("/", '\\') - end + declare_resource(:env, "path") do + action :modify + delim ::File::PATH_SEPARATOR + value path.tr("/", '\\') end end diff --git a/lib/chef/provider/windows_task.rb b/lib/chef/provider/windows_task.rb index 2aad02564c..8420210a57 100644 --- a/lib/chef/provider/windows_task.rb +++ b/lib/chef/provider/windows_task.rb @@ -1,6 +1,6 @@ # # Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>) -# 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"); @@ -75,23 +75,22 @@ class Chef def action_create if current_resource.exists + Chef::Log.debug "#{new_resource} task exists." if !(task_need_update? || new_resource.force) - Chef::Log.info "#{new_resource} task already exists - nothing to do" + Chef::Log.info "#{new_resource} task doesn't need updating and force not specified - nothing to do" return end # Setting the attributes of new_resource as current_resource. - # This is required to maintain idempotency when the user is not passing start_day and start_time - # because SCHTASK.exe sets them by default as the current time and day. - # So the current_resource will always have start_time and start_days set for an existing task, - # even though the user didn't pass it. So we set the new_resource attributes as the current_resource attributes + # This is required to handle update scenarios when the user specifies + # only those attributes in the recipe which require update resource_attributes.each do |attribute| new_resource_attribute = new_resource.send(attribute) current_resource_attribute = current_resource.send(attribute) # We accept start_day in mm/dd/yyyy format only. Hence while copying the start_day from system to new_resource.start_day, # we are converting from system date format to mm/dd/yyyy - current_resource_attribute = convert_system_date_to_mm_dd_yyyy(current_resource_attribute) if attribute == "start_day" + current_resource_attribute = convert_system_date_to_mm_dd_yyyy(current_resource_attribute) if attribute == "start_day" && current_resource_attribute != "N/A" # Convert start_time into 24hr time format - current_resource_attribute = DateTime.parse(current_resource_attribute).strftime("%H:%M") if attribute == "start_time" + current_resource_attribute = DateTime.parse(current_resource_attribute).strftime("%H:%M") if attribute == "start_time" && current_resource_attribute != "N/A" new_resource.send("#{attribute}=", current_resource_attribute ) if current_resource_attribute && new_resource_attribute.nil? end end @@ -104,8 +103,8 @@ class Chef options["SD"] = convert_user_date_to_system_date "12/12/2012" else options["SC"] = schedule - options["ST"] = new_resource.start_time unless new_resource.start_time.nil? - options["SD"] = convert_user_date_to_system_date new_resource.start_day unless new_resource.start_day.nil? + options["ST"] = new_resource.start_time unless new_resource.start_time.nil? || new_resource.start_time == "N/A" + options["SD"] = convert_user_date_to_system_date new_resource.start_day unless new_resource.start_day.nil? || new_resource.start_day == "N/A" end options["MO"] = new_resource.frequency_modifier if frequency_modifier_allowed options["I"] = new_resource.idle_time unless new_resource.idle_time.nil? @@ -121,20 +120,21 @@ class Chef xml_options << "cwd" if new_resource.cwd xml_options << "random_delay" if new_resource.random_delay xml_options << "execution_time_limit" if new_resource.execution_time_limit - update_task_xml(xml_options) unless xml_options.empty? - new_resource.updated_by_last_action true - Chef::Log.info "#{new_resource} task created" + converge_by("#{new_resource} task created") do + update_task_xml(xml_options) unless xml_options.empty? + end end def action_run if current_resource.exists + Chef::Log.debug "#{new_resource} task exists." if current_resource.status == :running - Chef::Log.info "#{new_resource} task is currently running, skipping run" + Chef::Log.info "#{new_resource} task is currently running, skipping run." else - run_schtasks "RUN" - new_resource.updated_by_last_action true - Chef::Log.info "#{new_resource} task ran" + converge_by("run scheduled task #{new_resource}") do + run_schtasks "RUN" + end end else Chef::Log.warn "#{new_resource} task doesn't exists - nothing to do" @@ -143,10 +143,11 @@ class Chef def action_delete if current_resource.exists - # always need to force deletion - run_schtasks "DELETE", "F" => "" - new_resource.updated_by_last_action true - Chef::Log.info "#{new_resource} task deleted" + Chef::Log.debug "#{new_resource} task exists." + converge_by("delete scheduled task #{new_resource}") do + # always need to force deletion + run_schtasks "DELETE", "F" => "" + end else Chef::Log.warn "#{new_resource} task doesn't exists - nothing to do" end @@ -154,12 +155,13 @@ class Chef def action_end if current_resource.exists + Chef::Log.debug "#{new_resource} task exists." if current_resource.status != :running Chef::Log.debug "#{new_resource} is not running - nothing to do" else - run_schtasks "END" - new_resource.updated_by_last_action true - Chef::Log.info "#{new_resource} task ended" + converge_by("#{new_resource} task ended") do + run_schtasks "END" + end end else Chef::Log.warn "#{new_resource} task doesn't exist - nothing to do" @@ -168,12 +170,13 @@ class Chef def action_enable if current_resource.exists + Chef::Log.debug "#{new_resource} task exists." if current_resource.enabled Chef::Log.debug "#{new_resource} already enabled - nothing to do" else - run_schtasks "CHANGE", "ENABLE" => "" - new_resource.updated_by_last_action true - Chef::Log.info "#{new_resource} task enabled" + converge_by("#{new_resource} task enabled") do + run_schtasks "CHANGE", "ENABLE" => "" + end end else Chef::Log.fatal "#{new_resource} task doesn't exist - nothing to do" @@ -183,10 +186,11 @@ class Chef def action_disable if current_resource.exists + Chef::Log.info "#{new_resource} task exists." if current_resource.enabled - run_schtasks "CHANGE", "DISABLE" => "" - new_resource.updated_by_last_action true - Chef::Log.info "#{new_resource} task disabled" + converge_by("#{new_resource} task disabled") do + run_schtasks "CHANGE", "DISABLE" => "" + end else Chef::Log.warn "#{new_resource} already disabled - nothing to do" end @@ -200,9 +204,15 @@ class Chef # rubocop:disable Style/StringLiteralsInInterpolation def run_schtasks(task_action, options = {}) cmd = "schtasks /#{task_action} /TN \"#{new_resource.task_name}\" " - options.keys.each do |option| - cmd += "/#{option} " - cmd += "\"#{options[option].to_s.gsub('"', "\\\"")}\" " unless options[option] == "" + options.each_key do |option| + unless option == "TR" + cmd += "/#{option} " + cmd += "\"#{options[option].to_s.gsub('"', "\\\"")}\" " unless options[option] == "" + end + end + # Appending Task Run [TR] option at the end since appending causing sometimes to append other options in option["TR"] value + if options["TR"] + cmd += "/TR \"#{options["TR"]} \" " unless task_action == "DELETE" end Chef::Log.debug("running: ") Chef::Log.debug(" #{cmd}") @@ -219,10 +229,9 @@ class Chef current_resource.frequency_modifier != new_resource.frequency_modifier || current_resource.frequency != new_resource.frequency || current_resource.idle_time != new_resource.idle_time || - current_resource.random_delay != new_resource.random_delay || - !new_resource.execution_time_limit.include?(current_resource.execution_time_limit) || - (new_resource.start_day && start_day_updated?) || - (new_resource.start_time && start_time_updated?) + random_delay_updated? || execution_time_limit_updated? || + (new_resource.start_day && new_resource.start_day != "N/A" && start_day_updated?) || + (new_resource.start_time && new_resource.start_time != "N/A" && start_time_updated?) begin return true if new_resource.day.to_s.casecmp(current_resource.day.to_s) != 0 || new_resource.months.to_s.casecmp(current_resource.months.to_s) != 0 @@ -233,6 +242,37 @@ class Chef false end + # Comparing random_delay values using ISO8601::Duration object Ref: https://github.com/arnau/ISO8601/blob/master/lib/iso8601/duration.rb#L18-L23 + # di = ISO8601::Duration.new(65707200) + # ds = ISO8601::Duration.new('P65707200S') + # dp = ISO8601::Duration.new('P2Y1MT2H') + # di == dp # => true + # di == ds # => true + def random_delay_updated? + if new_resource.random_delay.nil? + false + elsif current_resource.random_delay.nil? && new_resource.random_delay == "PT0S" # when user sets random_dealy to 0 sec + false + elsif current_resource.random_delay.nil? + true + else + ISO8601::Duration.new(current_resource.random_delay) != ISO8601::Duration.new(new_resource.random_delay) + end + end + + # Comparing execution_time_limit values using Ref: https://github.com/arnau/ISO8601/blob/master/lib/iso8601/duration.rb#L18-L23 + def execution_time_limit_updated? + if new_resource.execution_time_limit.nil? + false + elsif current_resource.execution_time_limit.nil? && new_resource.execution_time_limit == "PT0S" # when user sets random_dealy to 0 sec + false + elsif current_resource.execution_time_limit.nil? + true + else + ISO8601::Duration.new(current_resource.execution_time_limit) != ISO8601::Duration.new(new_resource.execution_time_limit) + end + end + def start_day_updated? current_day = DateTime.strptime(current_resource.start_day, convert_system_date_format_to_ruby_date_format) new_day = parse_day(new_resource.start_day) @@ -328,12 +368,12 @@ class Chef end options.each do |option| - Chef::Log.debug 'Removing former #{option} if any' + Chef::Log.debug "Removing former #{option} if any" doc.root.elements.delete(xml_element_mapping[option]) option_value = new_resource.send("#{option}") if option_value - Chef::Log.debug "Setting #option as #option_value" + Chef::Log.debug "Setting #{option} as #{option_value}" split_xml_path = xml_element_mapping[option].split("/") # eg. if xml_element_mapping[option] = "Actions/Exec/WorkingDirectory" element_name = split_xml_path.last # element_name = "WorkingDirectory" cwd_element = REXML::Element.new(element_name) @@ -355,7 +395,6 @@ class Chef options["RP"] = new_resource.password if new_resource.password options["IT"] = "" if new_resource.interactive_enabled options["XML"] = temp_task_file - run_schtasks("DELETE", "F" => "") run_schtasks("CREATE", options) ensure diff --git a/lib/chef/provider/yum_repository.rb b/lib/chef/provider/yum_repository.rb index 957ee9f0f3..20a7a8e3d2 100644 --- a/lib/chef/provider/yum_repository.rb +++ b/lib/chef/provider/yum_repository.rb @@ -47,7 +47,7 @@ class Chef if new_resource.make_cache notifies :run, "execute[yum clean metadata #{new_resource.repositoryid}]", :immediately if new_resource.clean_metadata || new_resource.clean_headers notifies :run, "execute[yum-makecache-#{new_resource.repositoryid}]", :immediately - notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately + notifies :create, "ruby_block[package-cache-reload-#{new_resource.repositoryid}]", :immediately end end @@ -63,9 +63,14 @@ class Chef only_if { new_resource.enabled } end - # reload internal Chef yum cache - declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do - block { Chef::Provider::Package::Yum::YumCache.instance.reload } + # reload internal Chef yum/dnf cache + declare_resource(:ruby_block, "package-cache-reload-#{new_resource.repositoryid}") do + if ( platform?("fedora") && node["platform_version"].to_i >= 22 ) || + ( platform_family?("rhel") && node["platform_version"].to_i >= 8 ) + block { Chef::Provider::Package::Dnf::PythonHelper.instance.restart } + else + block { Chef::Provider::Package::Yum::YumCache.instance.reload } + end action :nothing end end @@ -79,11 +84,16 @@ class Chef declare_resource(:file, "/etc/yum.repos.d/#{new_resource.repositoryid}.repo") do action :delete - notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately + notifies :create, "ruby_block[package-cache-reload-#{new_resource.repositoryid}]", :immediately end - declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do - block { Chef::Provider::Package::Yum::YumCache.instance.reload } + declare_resource(:ruby_block, "package-cache-reload-#{new_resource.repositoryid}") do + if ( platform?("fedora") && node["platform_version"].to_i >= 22 ) || + ( platform_family?("rhel") && node["platform_version"].to_i >= 8 ) + block { Chef::Provider::Package::Dnf::PythonHelper.instance.restart } + else + block { Chef::Provider::Package::Yum::YumCache.instance.reload } + end action :nothing end end @@ -95,8 +105,13 @@ class Chef only_if { new_resource.enabled } end - declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do - block { Chef::Provider::Package::Yum::YumCache.instance.reload } + declare_resource(:ruby_block, "package-cache-reload-#{new_resource.repositoryid}") do + if ( platform?("fedora") && node["platform_version"].to_i >= 22 ) || + ( platform_family?("rhel") && node["platform_version"].to_i >= 8 ) + block { Chef::Provider::Package::Dnf::PythonHelper.instance.restart } + else + block { Chef::Provider::Package::Yum::YumCache.instance.reload } + end action :run end end diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb index a3332477e7..507203fd28 100644 --- a/lib/chef/providers.rb +++ b/lib/chef/providers.rb @@ -24,12 +24,10 @@ require "chef/provider/cookbook_file" require "chef/provider/cron" require "chef/provider/cron/solaris" require "chef/provider/cron/aix" -require "chef/provider/deploy" require "chef/provider/directory" require "chef/provider/dsc_script" require "chef/provider/dsc_resource" require "chef/provider/env" -require "chef/provider/erl_call" require "chef/provider/execute" require "chef/provider/file" require "chef/provider/git" @@ -131,9 +129,6 @@ require "chef/provider/mount/aix" require "chef/provider/mount/solaris" require "chef/provider/mount/windows" -require "chef/provider/deploy/revision" -require "chef/provider/deploy/timestamped" - require "chef/provider/remote_file/ftp" require "chef/provider/remote_file/sftp" require "chef/provider/remote_file/http" diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index 5436e3ceb3..5ee4be6e25 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -861,7 +861,7 @@ class Chef # @return [Array<Symbol>] The list of actions this Resource is allowed to # have. # - attr_accessor :allowed_actions + attr_writer :allowed_actions def allowed_actions(value = NOT_PASSED) if value != NOT_PASSED self.allowed_actions = value diff --git a/lib/chef/resource/action_class.rb b/lib/chef/resource/action_class.rb index dce3be3244..1bb3decb75 100644 --- a/lib/chef/resource/action_class.rb +++ b/lib/chef/resource/action_class.rb @@ -1,6 +1,6 @@ # # Author:: John Keiser (<jkeiser@chef.io) -# Copyright:: Copyright 2015-2017, 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"); @@ -40,7 +40,7 @@ class Chef # We clear desired state in the copy, because it is supposed to be actual state. # We keep identity properties and non-desired-state, which are assumed to be # "control" values like `recurse: true` - current_resource.class.properties.each do |name, property| + current_resource.class.properties.each_value do |property| if property.desired_state? && !property.identity? && !property.name_property? property.reset(current_resource) end diff --git a/lib/chef/resource/apt_package.rb b/lib/chef/resource/apt_package.rb index 8397f84c71..c077922a20 100644 --- a/lib/chef/resource/apt_package.rb +++ b/lib/chef/resource/apt_package.rb @@ -21,6 +21,7 @@ require "chef/provider/package/apt" class Chef class Resource + # Use the apt_package resource to manage packages on Debian and Ubuntu platforms. class AptPackage < Chef::Resource::Package resource_name :apt_package provides :package, os: "linux", platform_family: "debian" diff --git a/lib/chef/resource/apt_preference.rb b/lib/chef/resource/apt_preference.rb index 603766d76b..87c5a5a016 100644 --- a/lib/chef/resource/apt_preference.rb +++ b/lib/chef/resource/apt_preference.rb @@ -20,6 +20,10 @@ require "chef/resource" class Chef class Resource + # The apt_preference resource allows for the creation of APT preference files. Preference files are used to control + # which package versions and sources are prioritized during installation. + # + # @since 13.3 class AptPreference < Chef::Resource resource_name :apt_preference provides :apt_preference diff --git a/lib/chef/resource/apt_repository.rb b/lib/chef/resource/apt_repository.rb index 8b69435246..5da0b4e37b 100644 --- a/lib/chef/resource/apt_repository.rb +++ b/lib/chef/resource/apt_repository.rb @@ -20,6 +20,10 @@ require "chef/resource" class Chef class Resource + # Use the apt_repository resource to specify additional APT repositories. Adding a new repository will update + # APT package cache immediately. + # + # @since 12.9 class AptRepository < Chef::Resource resource_name :apt_repository provides :apt_repository diff --git a/lib/chef/resource/apt_update.rb b/lib/chef/resource/apt_update.rb index 67ca7fbfea..0349614ad2 100644 --- a/lib/chef/resource/apt_update.rb +++ b/lib/chef/resource/apt_update.rb @@ -20,6 +20,9 @@ require "chef/resource" class Chef class Resource + # Use the apt_update resource to manage APT repository updates on Debian and Ubuntu platforms. + # + # @since 12.7 class AptUpdate < Chef::Resource resource_name :apt_update provides :apt_update diff --git a/lib/chef/resource/bash.rb b/lib/chef/resource/bash.rb index 1238eedc42..ebc4a7790b 100644 --- a/lib/chef/resource/bash.rb +++ b/lib/chef/resource/bash.rb @@ -21,6 +21,10 @@ require "chef/provider/script" class Chef class Resource + # Use the bash resource to execute scripts using the Bash interpreter. This resource may also use any of the actions + # and properties that are available to the execute resource. Commands that are executed with this resource are (by + # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if + # and only_if to guard this resource for idempotence. class Bash < Chef::Resource::Script def initialize(name, run_context = nil) diff --git a/lib/chef/resource/batch.rb b/lib/chef/resource/batch.rb index 10e96839fb..b3c7b17cef 100644 --- a/lib/chef/resource/batch.rb +++ b/lib/chef/resource/batch.rb @@ -20,6 +20,11 @@ require "chef/resource/windows_script" class Chef class Resource + # Use the batch resource to execute a batch script using the cmd.exe interpreter on Windows. The batch resource + # creates and executes a temporary file (similar to how the script resource behaves), rather than running the + # command inline. Commands that are executed with this resource are (by their nature) not idempotent, as they are + # typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for + # idempotence. class Batch < Chef::Resource::WindowsScript provides :batch, os: "windows" diff --git a/lib/chef/resource/bff_package.rb b/lib/chef/resource/bff_package.rb index b14591876a..d91777cb74 100644 --- a/lib/chef/resource/bff_package.rb +++ b/lib/chef/resource/bff_package.rb @@ -21,6 +21,10 @@ require "chef/provider/package/aix" class Chef class Resource + # Use the bff_package resource to manage packages for the AIX platform using the installp utility. When a package is + # installed from a local file, it must be added to the node using the remote_file or cookbook_file resources. + # + # @since 12.0 class BffPackage < Chef::Resource::Package end end diff --git a/lib/chef/resource/breakpoint.rb b/lib/chef/resource/breakpoint.rb index 81cfd89e5e..5d2c5555be 100644 --- a/lib/chef/resource/breakpoint.rb +++ b/lib/chef/resource/breakpoint.rb @@ -20,6 +20,12 @@ require "chef/resource" class Chef class Resource + # Use the breakpoint resource to add breakpoints to recipes. Run the chef-shell in chef-client mode, and then use + # those breakpoints to debug recipes. Breakpoints are ignored by the chef-client during an actual chef-client run. + # That said, breakpoints are typically used to debug recipes only when running them in a non-production environment, + # after which they are removed from those recipes before the parent cookbook is uploaded to the Chef server. + # + # @since 12.0 class Breakpoint < Chef::Resource provides :breakpoint resource_name :breakpoint diff --git a/lib/chef/resource/cab_package.rb b/lib/chef/resource/cab_package.rb index b7acfb0ec9..8f3b3038c4 100644 --- a/lib/chef/resource/cab_package.rb +++ b/lib/chef/resource/cab_package.rb @@ -21,24 +21,24 @@ require "chef/mixin/uris" class Chef class Resource + # Use the cab_package resource to install or remove Microsoft Windows cabinet (.cab) packages. + # + # @since 12.15 class CabPackage < Chef::Resource::Package include Chef::Mixin::Uris + resource_name :cab_package provides :cab_package, os: "windows" allowed_actions :install, :remove - def initialize(name, run_context = nil) - super - @resource_name = :cab_package - end - property :source, String, coerce: (proc do |s| unless s.nil? uri_scheme?(s) ? s : Chef::Util::PathHelper.canonical_path(s, false) end - end) + end), + default: lazy { |r| r.package_name } end end end diff --git a/lib/chef/resource/chef_gem.rb b/lib/chef/resource/chef_gem.rb index 7025d74e58..b6bbd0e209 100644 --- a/lib/chef/resource/chef_gem.rb +++ b/lib/chef/resource/chef_gem.rb @@ -21,6 +21,18 @@ require "chef/resource/gem_package" class Chef class Resource + # Use the chef_gem resource to install a gem only for the instance of Ruby that is dedicated to the chef-client. + # When a gem is installed from a local file, it must be added to the node using the remote_file or cookbook_file + # resources. + # + # The chef_gem resource works with all of the same properties and options as the gem_package resource, but does not + # accept the gem_binary property because it always uses the CurrentGemEnvironment under which the chef-client is + # running. In addition to performing actions similar to the gem_package resource, the chef_gem resource does the + # following: + # - Runs its actions immediately, before convergence, allowing a gem to be used in a recipe immediately after it is + # installed + # - Runs Gem.clear_paths after the action, ensuring that gem is aware of changes so that it can be required + # immediately after it is installed class ChefGem < Chef::Resource::Package::GemPackage resource_name :chef_gem @@ -30,6 +42,7 @@ class Chef } property :compile_time, [ true, false ], default: false, desired_state: false + # force the resource to compile time if the compile time property has been set def after_created if compile_time Array(action).each do |action| diff --git a/lib/chef/resource/chocolatey_package.rb b/lib/chef/resource/chocolatey_package.rb index a443b9a1d7..58bcab8b39 100644 --- a/lib/chef/resource/chocolatey_package.rb +++ b/lib/chef/resource/chocolatey_package.rb @@ -20,22 +20,20 @@ require "chef/resource/package" class Chef class Resource + # Use the chocolatey_package resource to manage packages using Chocolatey on the Microsoft Windows platform. + # + # @since 12.7 class ChocolateyPackage < Chef::Resource::Package + resource_name :chocolatey_package provides :chocolatey_package, os: "windows" allowed_actions :install, :upgrade, :remove, :uninstall, :purge, :reconfig - def initialize(name, run_context = nil) - super - @resource_name = :chocolatey_package - end - # windows can't take Array options yet property :options, String property :package_name, [String, Array], coerce: proc { |x| [x].flatten } - property :version, [String, Array], coerce: proc { |x| [x].flatten } property :returns, [Integer, Array], default: [ 0 ], desired_state: false end diff --git a/lib/chef/resource/cookbook_file.rb b/lib/chef/resource/cookbook_file.rb index 785cf693be..8c3de119e9 100644 --- a/lib/chef/resource/cookbook_file.rb +++ b/lib/chef/resource/cookbook_file.rb @@ -24,26 +24,24 @@ require "chef/mixin/securable" class Chef class Resource + # Use the cookbook_file resource to transfer files from a sub-directory of COOKBOOK_NAME/files/ to a specified path + # located on a host that is running the chef-client. The file is selected according to file specificity, which allows + # different source files to be used based on the hostname, host platform (operating system, distro, or as appropriate), + # or platform version. Files that are located in the COOKBOOK_NAME/files/default sub-directory may be used on any + # platform. + # + # During a chef-client run, the checksum for each local file is calculated and then compared against the checksum for + # the same file as it currently exists in the cookbook on the Chef server. A file is not transferred when the checksums + # match. Only files that require an update are transferred from the Chef server to a node. class CookbookFile < Chef::Resource::File include Chef::Mixin::Securable - default_action :create - - def initialize(name, run_context = nil) - super - @provider = Chef::Provider::CookbookFile - @source = ::File.basename(name) - @cookbook = nil - end + resource_name :cookbook_file - def source(source_filename = nil) - set_or_return(:source, source_filename, :kind_of => [ String, Array ]) - end - - def cookbook(cookbook_name = nil) - set_or_return(:cookbook, cookbook_name, :kind_of => String) - end + property :source, [ String, Array ], default: lazy { ::File.basename(name) } + property :cookbook, String + default_action :create end end end diff --git a/lib/chef/resource/cron.rb b/lib/chef/resource/cron.rb index a76d454bf0..2b70be7bb8 100644 --- a/lib/chef/resource/cron.rb +++ b/lib/chef/resource/cron.rb @@ -21,6 +21,8 @@ require "chef/resource" class Chef class Resource + # Use the cron resource to manage cron entries for time-based job scheduling. Properties for a schedule will default + # to * if not provided. The cron resource requires access to a crontab program, typically cron. class Cron < Chef::Resource identity_attr :command diff --git a/lib/chef/resource/csh.rb b/lib/chef/resource/csh.rb index 4e7c22b660..ef302af6c0 100644 --- a/lib/chef/resource/csh.rb +++ b/lib/chef/resource/csh.rb @@ -21,6 +21,10 @@ require "chef/provider/script" class Chef class Resource + # Use the csh resource to execute scripts using the csh interpreter. This resource may also use any of the actions + # and properties that are available to the execute resource. Commands that are executed with this resource are (by + # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if + # and only_if to guard this resource for idempotence. class Csh < Chef::Resource::Script def initialize(name, run_context = nil) diff --git a/lib/chef/resource/deploy.rb b/lib/chef/resource/deploy.rb deleted file mode 100644 index f74fe86c12..0000000000 --- a/lib/chef/resource/deploy.rb +++ /dev/null @@ -1,449 +0,0 @@ -# -# Author:: Daniel DeLeo (<dan@kallistec.com>) -# Author:: Tyler Cloke (<tyler@chef.io>) -# Copyright:: Copyright 2008-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. -# - -# EX: -# deploy "/my/deploy/dir" do -# repo "git@github.com/whoami/project" -# revision "abc123" # or "HEAD" or "TAG_for_1.0" or (subversion) "1234" -# user "deploy_ninja" -# enable_submodules true -# migrate true -# migration_command "rake db:migrate" -# environment "RAILS_ENV" => "production", "OTHER_ENV" => "foo" -# shallow_clone true -# depth 1 -# action :deploy # or :rollback -# restart_command "touch tmp/restart.txt" -# git_ssh_wrapper "wrap-ssh4git.sh" -# scm_provider Chef::Provider::Git # is the default, for svn: Chef::Provider::Subversion -# svn_username "whoami" -# svn_password "supersecret" -# end - -require "chef/resource/scm" - -class Chef - class Resource - - # Deploy: Deploy apps from a source control repository. - # - # Callbacks: - # Callbacks can be a block or a string. If given a block, the code - # is evaluated as an embedded recipe, and run at the specified - # point in the deploy process. If given a string, the string is taken as - # a path to a callback file/recipe. Paths are evaluated relative to the - # release directory. Callback files can contain chef code (resources, etc.) - # - class Deploy < Chef::Resource - - identity_attr :repository - - state_attrs :deploy_to, :revision - - default_action :deploy - allowed_actions :force_deploy, :deploy, :rollback - - def initialize(name, run_context = nil) - super - @deploy_to = name - @environment = nil - @repository_cache = "cached-copy" - @copy_exclude = [] - @purge_before_symlink = %w{log tmp/pids public/system} - @create_dirs_before_symlink = %w{tmp public config} - @symlink_before_migrate = { "config/database.yml" => "config/database.yml" } - @symlinks = { "system" => "public/system", "pids" => "tmp/pids", "log" => "log" } - @revision = "HEAD" - @migrate = false - @rollback_on_error = false - @remote = "origin" - @enable_submodules = false - @shallow_clone = false - @depth = nil - @scm_provider = Chef::Provider::Git - @svn_force_export = false - @additional_remotes = Hash[] - @keep_releases = 5 - @enable_checkout = true - @checkout_branch = "deploy" - end - - # This resource is deprecated. - def after_created - Chef.deprecated(:deploy_resource, "The #{resource_name} resource (#{source_line}) is deprecated and will be removed from Chef core in 14.0 (April 2018). " \ - "A migration cookbook will be available in the future, see the deprecation documentation for more information.") - end - - # where the checked out/cloned code goes - def destination - @destination ||= shared_path + "/#{@repository_cache}" - end - - # where shared stuff goes, i.e., logs, tmp, etc. goes here - def shared_path - @shared_path ||= @deploy_to + "/shared" - end - - # where the deployed version of your code goes - def current_path - @current_path ||= @deploy_to + "/current" - end - - def depth(arg = @shallow_clone ? 5 : nil) - set_or_return( - :depth, - arg, - :kind_of => [ Integer ] - ) - end - - # note: deploy_to is your application "meta-root." - def deploy_to(arg = nil) - set_or_return( - :deploy_to, - arg, - :kind_of => [ String ] - ) - end - - def repo(arg = nil) - set_or_return( - :repo, - arg, - :kind_of => [ String ] - ) - end - alias :repository :repo - - def remote(arg = nil) - set_or_return( - :remote, - arg, - :kind_of => [ String ] - ) - end - - def role(arg = nil) - set_or_return( - :role, - arg, - :kind_of => [ String ] - ) - end - - def restart_command(arg = nil, &block) - arg ||= block - set_or_return( - :restart_command, - arg, - :kind_of => [ String, Proc ] - ) - end - alias :restart :restart_command - - def migrate(arg = nil) - set_or_return( - :migrate, - arg, - :kind_of => [ TrueClass, FalseClass ] - ) - end - - def migration_command(arg = nil) - set_or_return( - :migration_command, - arg, - :kind_of => [ String ] - ) - end - - def rollback_on_error(arg = nil) - set_or_return( - :rollback_on_error, - arg, - :kind_of => [ TrueClass, FalseClass ] - ) - end - - def user(arg = nil) - set_or_return( - :user, - arg, - :kind_of => [ String ] - ) - end - - def group(arg = nil) - set_or_return( - :group, - arg, - :kind_of => [ String ] - ) - end - - def enable_submodules(arg = nil) - set_or_return( - :enable_submodules, - arg, - :kind_of => [ TrueClass, FalseClass ] - ) - end - - def shallow_clone(arg = nil) - set_or_return( - :shallow_clone, - arg, - :kind_of => [ TrueClass, FalseClass ] - ) - end - - def repository_cache(arg = nil) - set_or_return( - :repository_cache, - arg, - :kind_of => [ String ] - ) - end - - def copy_exclude(arg = nil) - set_or_return( - :copy_exclude, - arg, - :kind_of => [ String ] - ) - end - - def revision(arg = nil) - set_or_return( - :revision, - arg, - :kind_of => [ String ] - ) - end - alias :branch :revision - - def git_ssh_wrapper(arg = nil) - set_or_return( - :git_ssh_wrapper, - arg, - :kind_of => [ String ] - ) - end - alias :ssh_wrapper :git_ssh_wrapper - - def svn_username(arg = nil) - set_or_return( - :svn_username, - arg, - :kind_of => [ String ] - ) - end - - def svn_password(arg = nil) - set_or_return( - :svn_password, - arg, - :kind_of => [ String ] - ) - end - - def svn_arguments(arg = nil) - set_or_return( - :svn_arguments, - arg, - :kind_of => [ String ] - ) - end - - def svn_info_args(arg = nil) - set_or_return( - :svn_arguments, - arg, - :kind_of => [ String ]) - end - - def scm_provider(arg = nil) - klass = if arg.kind_of?(String) || arg.kind_of?(Symbol) - lookup_provider_constant(arg) - else - arg - end - set_or_return( - :scm_provider, - klass, - :kind_of => [ Class ] - ) - end - - # This is to support "provider :revision" without deprecation warnings. - # Do NOT copy this. - def self.provider_base - Chef::Provider::Deploy - end - - def svn_force_export(arg = nil) - set_or_return( - :svn_force_export, - arg, - :kind_of => [ TrueClass, FalseClass ] - ) - end - - def environment(arg = nil) - if arg.is_a?(String) - Chef::Log.debug "Setting RAILS_ENV, RACK_ENV, and MERB_ENV to `#{arg}'" - Chef::Log.warn "[DEPRECATED] please modify your deploy recipe or attributes to set the environment using a hash" - arg = { "RAILS_ENV" => arg, "MERB_ENV" => arg, "RACK_ENV" => arg } - end - set_or_return( - :environment, - arg, - :kind_of => [ Hash ] - ) - end - - # The number of old release directories to keep around after cleanup - def keep_releases(arg = nil) - [set_or_return( - :keep_releases, - arg, - :kind_of => [ Integer ]), 1].max - end - - # An array of paths, relative to your app's root, to be purged from a - # SCM clone/checkout before symlinking. Use this to get rid of files and - # directories you want to be shared between releases. - # Default: ["log", "tmp/pids", "public/system"] - def purge_before_symlink(arg = nil) - set_or_return( - :purge_before_symlink, - arg, - :kind_of => Array - ) - end - - # An array of paths, relative to your app's root, where you expect dirs to - # exist before symlinking. This runs after #purge_before_symlink, so you - # can use this to recreate dirs that you had previously purged. - # For example, if you plan to use a shared directory for pids, and you - # want it to be located in $APP_ROOT/tmp/pids, you could purge tmp, - # then specify tmp here so that the tmp directory will exist when you - # symlink the pids directory in to the current release. - # Default: ["tmp", "public", "config"] - def create_dirs_before_symlink(arg = nil) - set_or_return( - :create_dirs_before_symlink, - arg, - :kind_of => Array - ) - end - - # A Hash of shared/dir/path => release/dir/path. This attribute determines - # which files and dirs in the shared directory get symlinked to the current - # release directory, and where they go. If you have a directory - # $shared/pids that you would like to symlink as $current_release/tmp/pids - # you specify it as "pids" => "tmp/pids" - # Default {"system" => "public/system", "pids" => "tmp/pids", "log" => "log"} - def symlinks(arg = nil) - set_or_return( - :symlinks, - arg, - :kind_of => Hash - ) - end - - # A Hash of shared/dir/path => release/dir/path. This attribute determines - # which files in the shared directory get symlinked to the current release - # directory and where they go. Unlike map_shared_files, these are symlinked - # *before* any migration is run. - # For a rails/merb app, this is used to link in a known good database.yml - # (with the production db password) before running migrate. - # Default {"config/database.yml" => "config/database.yml"} - def symlink_before_migrate(arg = nil) - set_or_return( - :symlink_before_migrate, - arg, - :kind_of => Hash - ) - end - - # Callback fires before migration is run. - def before_migrate(arg = nil, &block) - arg ||= block - set_or_return(:before_migrate, arg, :kind_of => [Proc, String]) - end - - # Callback fires before symlinking - def before_symlink(arg = nil, &block) - arg ||= block - set_or_return(:before_symlink, arg, :kind_of => [Proc, String]) - end - - # Callback fires before restart - def before_restart(arg = nil, &block) - arg ||= block - set_or_return(:before_restart, arg, :kind_of => [Proc, String]) - end - - # Callback fires after restart - def after_restart(arg = nil, &block) - arg ||= block - set_or_return(:after_restart, arg, :kind_of => [Proc, String]) - end - - def additional_remotes(arg = nil) - set_or_return( - :additional_remotes, - arg, - :kind_of => Hash - ) - end - - def enable_checkout(arg = nil) - set_or_return( - :enable_checkout, - arg, - :kind_of => [TrueClass, FalseClass] - ) - end - - def checkout_branch(arg = nil) - set_or_return( - :checkout_branch, - arg, - :kind_of => String - ) - end - - # FIXME The Deploy resource may be passed to an SCM provider as its - # resource. The SCM provider knows that SCM resources can specify a - # timeout for SCM operations. The deploy resource must therefore support - # a timeout method, but the timeout it describes is for SCM operations, - # not the overall deployment. This is potentially confusing. - def timeout(arg = nil) - set_or_return( - :timeout, - arg, - :kind_of => Integer - ) - end - - end - end -end diff --git a/lib/chef/resource/deploy_revision.rb b/lib/chef/resource/deploy_revision.rb deleted file mode 100644 index 41046ec288..0000000000 --- a/lib/chef/resource/deploy_revision.rb +++ /dev/null @@ -1,31 +0,0 @@ -# -# Author:: Daniel DeLeo (<dan@kallistec.com>) -# Copyright:: Copyright 2009-2016, Daniel DeLeo -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -class Chef - class Resource - - # Convenience class for using the deploy resource with the revision - # deployment strategy (provider) - class DeployRevision < Chef::Resource::Deploy - end - - class DeployBranch < Chef::Resource::DeployRevision - end - - end -end diff --git a/lib/chef/resource/directory.rb b/lib/chef/resource/directory.rb index faad659668..b989b3ecde 100644 --- a/lib/chef/resource/directory.rb +++ b/lib/chef/resource/directory.rb @@ -2,7 +2,7 @@ # Author:: Adam Jacob (<adam@chef.io>) # Author:: Seth Chisamore (<schisamo@chef.io>) # Author:: Tyler Cloke (<tyler@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2017, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,14 +19,16 @@ # require "chef/resource" -require "chef/provider/directory" require "chef/mixin/securable" class Chef class Resource + # Use the directory resource to manage a directory, which is a hierarchy of folders that comprises all of the + # information stored on a computer. The root directory is the top-level, under which the rest of the directory + # is organized. The directory resource uses the name property to specify the path to a location in a directory. + # Typically, permission to access that location in the directory is required. class Directory < Chef::Resource - - identity_attr :path + resource_name :directory state_attrs :group, :mode, :owner @@ -35,28 +37,8 @@ class Chef default_action :create allowed_actions :create, :delete - def initialize(name, run_context = nil) - super - @path = name - @recursive = false - end - - def recursive(arg = nil) - set_or_return( - :recursive, - arg, - :kind_of => [ TrueClass, FalseClass ] - ) - end - - def path(arg = nil) - set_or_return( - :path, - arg, - :kind_of => String - ) - end - + property :path, String, name_property: true, identity: true + property :recursive, [ TrueClass, FalseClass ], default: false end end end diff --git a/lib/chef/resource/dnf_package.rb b/lib/chef/resource/dnf_package.rb index 05ed895e70..0e09d90d43 100644 --- a/lib/chef/resource/dnf_package.rb +++ b/lib/chef/resource/dnf_package.rb @@ -21,6 +21,11 @@ require "chef/mixin/shell_out" class Chef class Resource + # Use the dnf_package resource to install, upgrade, and remove packages with DNF for Fedora platforms. The dnf_package + # resource is able to resolve provides data for packages much like DNF can do when it is run from the command line. + # This allows a variety of options for installing packages, like minimum versions, virtual provides, and library names. + # + # @since 12.18 class DnfPackage < Chef::Resource::Package extend Chef::Mixin::Which extend Chef::Mixin::ShellOut diff --git a/lib/chef/resource/dpkg_package.rb b/lib/chef/resource/dpkg_package.rb index 9ff3239884..c73fc506ad 100644 --- a/lib/chef/resource/dpkg_package.rb +++ b/lib/chef/resource/dpkg_package.rb @@ -20,6 +20,8 @@ require "chef/resource/package" class Chef class Resource + # Use the dpkg_package resource to manage packages for the dpkg platform. When a package is installed from a local + # file, it must be added to the node using the remote_file or cookbook_file resources. class DpkgPackage < Chef::Resource::Package resource_name :dpkg_package provides :dpkg_package, os: "linux" diff --git a/lib/chef/resource/dsc_resource.rb b/lib/chef/resource/dsc_resource.rb index d3b579e428..0840b9bca1 100644 --- a/lib/chef/resource/dsc_resource.rb +++ b/lib/chef/resource/dsc_resource.rb @@ -19,6 +19,11 @@ require "chef/dsl/powershell" class Chef class Resource + # The dsc_resource resource allows any DSC resource to be used in a Chef recipe, as well as any custom resources + # that have been added to your Windows PowerShell environment. Microsoft frequently adds new resources to the DSC + # resource collection. + # + # @since 12.2 class DscResource < Chef::Resource provides :dsc_resource, os: "windows" diff --git a/lib/chef/resource/dsc_script.rb b/lib/chef/resource/dsc_script.rb index 7da29a651a..cea52e422b 100644 --- a/lib/chef/resource/dsc_script.rb +++ b/lib/chef/resource/dsc_script.rb @@ -21,9 +21,15 @@ require "chef/dsl/powershell" class Chef class Resource + # Many DSC resources are comparable to built-in Chef resources. For example, both DSC and Chef have file, package, + # and service resources. The dsc_script resource is most useful for those DSC resources that do not have a direct + # comparison to a resource in Chef, such as the Archive resource, a custom DSC resource, an existing DSC script + # that performs an important task, and so on. Use the dsc_script resource to embed the code that defines a DSC + # configuration directly within a Chef recipe. class DscScript < Chef::Resource include Chef::DSL::Powershell + resource_name :dsc_script provides :dsc_script, os: "windows" default_action :run diff --git a/lib/chef/resource/env.rb b/lib/chef/resource/env.rb index 746369f02d..12133f4368 100644 --- a/lib/chef/resource/env.rb +++ b/lib/chef/resource/env.rb @@ -19,7 +19,10 @@ class Chef class Resource + # Use the env resource to manage environment keys in Microsoft Windows. After an environment key is set, Microsoft + # Windows must be restarted before the environment key will be available to the Task Scheduler. class Env < Chef::Resource + resource_name :env provides :env, os: "windows" default_action :create diff --git a/lib/chef/resource/erl_call.rb b/lib/chef/resource/erl_call.rb deleted file mode 100644 index 3e317676a5..0000000000 --- a/lib/chef/resource/erl_call.rb +++ /dev/null @@ -1,85 +0,0 @@ -# -# Author:: Joe Williams (<joe@joetify.com>) -# Author:: Tyler Cloke (<tyler@chef.io>) -# Copyright:: Copyright 2009-2016, Joe Williams -# 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/resource" -require "chef/provider/erl_call" - -class Chef - class Resource - class ErlCall < Chef::Resource - - # erl_call : http://erlang.org/doc/man/erl_call.html - - identity_attr :code - - default_action :run - - def initialize(name, run_context = nil) - super - - @code = "q()." # your erlang code goes here - @cookie = nil # cookie of the erlang node - @distributed = false # if you want to have a distributed erlang node - @name_type = "sname" # type of erlang hostname name or sname - @node_name = "chef@localhost" # the erlang node hostname - end - - def code(arg = nil) - set_or_return( - :code, - arg, - :kind_of => [ String ] - ) - end - - def cookie(arg = nil) - set_or_return( - :cookie, - arg, - :kind_of => [ String ] - ) - end - - def distributed(arg = nil) - set_or_return( - :distributed, - arg, - :kind_of => [ TrueClass, FalseClass ] - ) - end - - def name_type(arg = nil) - set_or_return( - :name_type, - arg, - :kind_of => [ String ] - ) - end - - def node_name(arg = nil) - set_or_return( - :node_name, - arg, - :kind_of => [ String ] - ) - end - - end - end -end diff --git a/lib/chef/resource/execute.rb b/lib/chef/resource/execute.rb index ba1b8ae6e3..616195deee 100644 --- a/lib/chef/resource/execute.rb +++ b/lib/chef/resource/execute.rb @@ -22,6 +22,9 @@ require "chef/provider/execute" class Chef class Resource + # Use the execute resource to execute a single command. Commands that are executed with this resource are (by their + # nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if + # to guard this resource for idempotence. class Execute < Chef::Resource identity_attr :command @@ -130,7 +133,8 @@ class Chef property :password, String, sensitive: true - property :sensitive, [ TrueClass, FalseClass ], default: false, coerce: proc { |x| password ? true : x } + # lazy used to set default value of sensitive to true if password is set + property :sensitive, [ TrueClass, FalseClass ], default: lazy { |r| r.password ? true : false } property :elevated, [ TrueClass, FalseClass ], default: false diff --git a/lib/chef/resource/file.rb b/lib/chef/resource/file.rb index 5c275a574f..43d9c57150 100644 --- a/lib/chef/resource/file.rb +++ b/lib/chef/resource/file.rb @@ -25,6 +25,7 @@ require "pathname" class Chef class Resource + # Use the file resource to manage files directly on a node. class File < Chef::Resource include Chef::Mixin::Securable @@ -43,7 +44,7 @@ class Chef # mutate the new_resource.checksum which would change the # user intent in the new_resource if the resource is reused. # - # @returns [String] Checksum of the file we actually rendered + # @return [String] Checksum of the file we actually rendered attr_accessor :final_checksum default_action :create diff --git a/lib/chef/resource/file/verification.rb b/lib/chef/resource/file/verification.rb index 079e6dc201..ed6fce2e5c 100644 --- a/lib/chef/resource/file/verification.rb +++ b/lib/chef/resource/file/verification.rb @@ -119,6 +119,16 @@ class Chef v = verification_class.new(@parent_resource, @command, @command_opts, &@block) v.verify(path, opts) end + + def to_s + if @block + "<Proc>" + elsif @command.is_a?(Symbol) + "#{@command.inspect} (#{Chef::Resource::File::Verification.lookup(@command).name})" + elsif @command.is_a?(String) + @command + end + end end end end diff --git a/lib/chef/resource/freebsd_package.rb b/lib/chef/resource/freebsd_package.rb index ecaff95244..caaba29129 100644 --- a/lib/chef/resource/freebsd_package.rb +++ b/lib/chef/resource/freebsd_package.rb @@ -26,25 +26,33 @@ require "chef/mixin/shell_out" class Chef class Resource + # Use the freebsd_package resource to manage packages for the FreeBSD platform. class FreebsdPackage < Chef::Resource::Package include Chef::Mixin::ShellOut resource_name :freebsd_package provides :package, platform: "freebsd" + # make sure we assign the appropriate underlying providers based on what + # package managers exist on this FreeBSD system or the source of the package + # + # @return [void] def after_created assign_provider end + # Is the system at least version 1000017 or is the make variable WITH_PKGNG set + # + # @return [Boolean] do we support pkgng def supports_pkgng? ships_with_pkgng? || !!shell_out_compact!("make", "-V", "WITH_PKGNG", :env => nil).stdout.match(/yes/i) end private + # It was not until __FreeBSD_version 1000017 that pkgng became + # the default binary package manager. See '/usr/ports/Mk/bsd.port.mk'. def ships_with_pkgng? - # It was not until __FreeBSD_version 1000017 that pkgng became - # the default binary package manager. See '/usr/ports/Mk/bsd.port.mk'. node[:os_version].to_i >= 1000017 end diff --git a/lib/chef/resource/gem_package.rb b/lib/chef/resource/gem_package.rb index fc162a6033..8e3a426035 100644 --- a/lib/chef/resource/gem_package.rb +++ b/lib/chef/resource/gem_package.rb @@ -20,6 +20,8 @@ require "chef/resource/package" class Chef class Resource + # Use the gem_package resource to manage gem packages that are only included in recipes. When a package is installed + # from a local file, it must be added to the node using the remote_file or cookbook_file resources. class GemPackage < Chef::Resource::Package resource_name :gem_package diff --git a/lib/chef/resource/git.rb b/lib/chef/resource/git.rb index 4799b54d3d..ac4f027552 100644 --- a/lib/chef/resource/git.rb +++ b/lib/chef/resource/git.rb @@ -20,6 +20,8 @@ require "chef/resource/scm" class Chef class Resource + # Use the git resource to manage source control resources that exist in a git repository. git version 1.6.5 (or higher) + # is required to use all of the functionality in the git resource. class Git < Chef::Resource::Scm def initialize(name, run_context = nil) diff --git a/lib/chef/resource/group.rb b/lib/chef/resource/group.rb index d3a4a1ce89..69a3827a5c 100644 --- a/lib/chef/resource/group.rb +++ b/lib/chef/resource/group.rb @@ -19,6 +19,7 @@ class Chef class Resource + # Use the group resource to manage a local group. class Group < Chef::Resource identity_attr :group_name diff --git a/lib/chef/resource/homebrew_package.rb b/lib/chef/resource/homebrew_package.rb index c2d0a65c5b..6174a31079 100644 --- a/lib/chef/resource/homebrew_package.rb +++ b/lib/chef/resource/homebrew_package.rb @@ -23,6 +23,9 @@ require "chef/resource/package" class Chef class Resource + # Use the homebrew_package resource to manage packages for the macOS platform. + # + # @since 12.0 class HomebrewPackage < Chef::Resource::Package resource_name :homebrew_package provides :package, os: "darwin" diff --git a/lib/chef/resource/http_request.rb b/lib/chef/resource/http_request.rb index 9fac3562f3..9d8fce9b22 100644 --- a/lib/chef/resource/http_request.rb +++ b/lib/chef/resource/http_request.rb @@ -22,6 +22,8 @@ require "chef/provider/http_request" class Chef class Resource + # Use the http_request resource to send an HTTP request (GET, PUT, POST, DELETE, HEAD, or OPTIONS) with an arbitrary + # message. This resource is often useful when custom callbacks are necessary. class HttpRequest < Chef::Resource identity_attr :url diff --git a/lib/chef/resource/ifconfig.rb b/lib/chef/resource/ifconfig.rb index 3673311348..e9ef47d95b 100644 --- a/lib/chef/resource/ifconfig.rb +++ b/lib/chef/resource/ifconfig.rb @@ -21,163 +21,36 @@ require "chef/resource" class Chef class Resource + # use the ifconfig resource to manage interfaces on *nix systems + # + # @example set a static ip on eth1 + # ifconfig '33.33.33.80' do + # device 'eth1' + # end class Ifconfig < Chef::Resource - - identity_attr :device + resource_name :ifconfig state_attrs :inet_addr, :mask default_action :add allowed_actions :add, :delete, :enable, :disable - def initialize(name, run_context = nil) - super - @target = name - @hwaddr = nil - @mask = nil - @inet_addr = nil - @bcast = nil - @mtu = nil - @metric = nil - @device = nil - @onboot = nil - @network = nil - @bootproto = nil - @onparent = nil - @ethtool_opts = nil - @bonding_opts = nil - @master = nil - @slave = nil - end - - def target(arg = nil) - set_or_return( - :target, - arg, - :kind_of => String - ) - end - - def device(arg = nil) - set_or_return( - :device, - arg, - :kind_of => String - ) - end - - def hwaddr(arg = nil) - set_or_return( - :hwaddr, - arg, - :kind_of => String - ) - end - - def inet_addr(arg = nil) - set_or_return( - :inet_addr, - arg, - :kind_of => String - ) - end - - def bcast(arg = nil) - set_or_return( - :bcast, - arg, - :kind_of => String - ) - end - - def mask(arg = nil) - set_or_return( - :mask, - arg, - :kind_of => String - ) - end - - def mtu(arg = nil) - set_or_return( - :mtu, - arg, - :kind_of => String - ) - end - - def metric(arg = nil) - set_or_return( - :metric, - arg, - :kind_of => String - ) - end - - def onboot(arg = nil) - set_or_return( - :onboot, - arg, - :kind_of => String - ) - end - - def network(arg = nil) - set_or_return( - :network, - arg, - :kind_of => String - ) - end - - def bootproto(arg = nil) - set_or_return( - :bootproto, - arg, - :kind_of => String - ) - end - - def onparent(arg = nil) - set_or_return( - :onparent, - arg, - :kind_of => String - ) - end - - def ethtool_opts(arg = nil) - set_or_return( - :ethtool_opts, - arg, - :kind_of => String - ) - end - - def bonding_opts(arg = nil) - set_or_return( - :bonding_opts, - arg, - :kind_of => String - ) - end - - def master(arg = nil) - set_or_return( - :master, - arg, - :kind_of => String - ) - end - - def slave(arg = nil) - set_or_return( - :slave, - arg, - :kind_of => String - ) - end + property :target, String, name_property: true + property :hwaddr, String + property :mask, String + property :inet_addr, String + property :bcast, String + property :mtu, String + property :metric, String + property :device, String, identity: true + property :onboot, String + property :network, String + property :bootproto, String + property :onparent, String + property :ethtool_opts, String + property :bonding_opts, String + property :master, String + property :slave, String end - end end diff --git a/lib/chef/resource/ips_package.rb b/lib/chef/resource/ips_package.rb index 4d2c957e17..296919dc1c 100644 --- a/lib/chef/resource/ips_package.rb +++ b/lib/chef/resource/ips_package.rb @@ -21,6 +21,7 @@ require "chef/provider/package/ips" class Chef class Resource + # Use the ips_package resource to manage packages (using Image Packaging System (IPS)) on the Solaris 11 platform. class IpsPackage < ::Chef::Resource::Package resource_name :ips_package provides :package, os: "solaris2" diff --git a/lib/chef/resource/ksh.rb b/lib/chef/resource/ksh.rb index 3097156329..8024f0d6bd 100644 --- a/lib/chef/resource/ksh.rb +++ b/lib/chef/resource/ksh.rb @@ -20,6 +20,12 @@ require "chef/resource/script" class Chef class Resource + # Use the ksh resource to execute scripts using the Korn shell (ksh) interpreter. This resource may also use any + # f the actions and properties that are available to the execute resource. Commands that are executed with this + # resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are + # run. Use not_if and only_if to guard this resource for idempotence. + # + # @since 12.6 class Ksh < Chef::Resource::Script def initialize(name, run_context = nil) diff --git a/lib/chef/resource/launchd.rb b/lib/chef/resource/launchd.rb index 3fba76e220..121af1555c 100644 --- a/lib/chef/resource/launchd.rb +++ b/lib/chef/resource/launchd.rb @@ -17,19 +17,20 @@ # require "chef/resource" -require "chef/provider/launchd" class Chef class Resource + # Use the launchd resource to manage system-wide services (daemons) and per-user services (agents) on the macOS platform. + # + # @since 12.8 class Launchd < Chef::Resource + resource_name :launchd provides :launchd, os: "darwin" - identity_attr :label - default_action :create allowed_actions :create, :create_if_missing, :delete, :enable, :disable, :restart - property :label, String, default: lazy { name }, identity: true + property :label, String, identity: true, name_property: true property :backup, [Integer, FalseClass] property :cookbook, String property :group, [String, Integer] diff --git a/lib/chef/resource/link.rb b/lib/chef/resource/link.rb index 5717ec7bad..7a106b1703 100644 --- a/lib/chef/resource/link.rb +++ b/lib/chef/resource/link.rb @@ -22,6 +22,16 @@ require "chef/mixin/securable" class Chef class Resource + # Use the link resource to create symbolic or hard links. + # + # A symbolic link—sometimes referred to as a soft link—is a directory entry that associates a file name with a string + # that contains an absolute or relative path to a file on any file system. In other words, “a file that contains a path + # that points to another file.” A symbolic link creates a new file with a new inode that points to the inode location + # of the original file. + # + # A hard link is a directory entry that associates a file with another file in the same file system. In other words, + # “multiple directory entries to the same file.” A hard link creates a new file that points to the same inode as the + # original file. class Link < Chef::Resource include Chef::Mixin::Securable diff --git a/lib/chef/resource/log.rb b/lib/chef/resource/log.rb index 8f7879872f..b6da123526 100644 --- a/lib/chef/resource/log.rb +++ b/lib/chef/resource/log.rb @@ -18,59 +18,32 @@ # require "chef/resource" -require "chef/provider/log" class Chef class Resource + # Use the log resource to create log entries. The log resource behaves like any other resource: built into the resource + # collection during the compile phase, and then run during the execution phase. (To create a log entry that is not built + # into the resource collection, use Chef::Log instead of the log resource.) + # + # Allows logging a :debug, :info, :warn, and :error levels + # Defaults to :info level + # + # @example logging at default info level + # log "your string to log" + # + # @example logging at specified debug level + # log "a debug string" do + # level :debug + # end + # class Log < Chef::Resource + resource_name :log - identity_attr :message + property :message, String, name_property: true + property :level, Symbol, equal_to: [ :debug, :info, :warn, :error, :fatal ], default: :info + allowed_actions :write default_action :write - - # Sends a string from a recipe to a log provider - # - # log "some string to log" do - # level :info # (default) also supports :warn, :debug, and :error - # end - # - # === Example - # log "your string to log" - # - # or - # - # log "a debug string" { level :debug } - # - - # Initialize log resource with a name as the string to log - # - # === Parameters - # name<String>:: Message to log - # collection<Array>:: Collection of included recipes - # node<Chef::Node>:: Node where resource will be used - def initialize(name, run_context = nil) - super - @level = :info - @message = name - end - - def message(arg = nil) - set_or_return( - :message, - arg, - :kind_of => String - ) - end - - # <Symbol> Log level, one of :debug, :info, :warn, :error or :fatal - def level(arg = nil) - set_or_return( - :level, - arg, - :equal_to => [ :debug, :info, :warn, :error, :fatal ] - ) - end - end end end diff --git a/lib/chef/resource/lwrp_base.rb b/lib/chef/resource/lwrp_base.rb index b12ac98673..0e4c3f826c 100644 --- a/lib/chef/resource/lwrp_base.rb +++ b/lib/chef/resource/lwrp_base.rb @@ -2,7 +2,7 @@ # Author:: Adam Jacob (<adam@chef.io>) # Author:: Christopher Walters (<cw@chef.io>) # Author:: Daniel DeLeo (<dan@chef.io>) -# 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"); @@ -41,8 +41,6 @@ class Chef include Chef::Mixin::ConvertToClassName include Chef::Mixin::FromFile - attr_accessor :loaded_lwrps - def build_from_file(cookbook_name, filename, run_context) if LWRPBase.loaded_lwrps[filename] Chef::Log.debug("Custom resource #{filename} from cookbook #{cookbook_name} has already been loaded! Skipping the reload.") @@ -102,6 +100,7 @@ class Chef protected + attr_writer :loaded_lwrps def loaded_lwrps @loaded_lwrps ||= {} end diff --git a/lib/chef/resource/macports_package.rb b/lib/chef/resource/macports_package.rb index 3685334c17..e787529f48 100644 --- a/lib/chef/resource/macports_package.rb +++ b/lib/chef/resource/macports_package.rb @@ -20,6 +20,7 @@ require "chef/resource/package" class Chef class Resource + # Use the macports_package resource to manage packages for the macOS platform. class MacportsPackage < Chef::Resource::Package resource_name :macports_package end diff --git a/lib/chef/resource/mdadm.rb b/lib/chef/resource/mdadm.rb index df6e705f15..354582d1cf 100644 --- a/lib/chef/resource/mdadm.rb +++ b/lib/chef/resource/mdadm.rb @@ -21,6 +21,10 @@ require "chef/resource" class Chef class Resource + # Use the mdadm resource to manage RAID devices in a Linux environment using the mdadm utility. The mdadm resource + # will create and assemble an array, but it will not create the config file that is used to persist the array upon + # reboot. If the config file is required, it must be done by specifying a template with the correct array layout, + # and then by using the mount provider to create a file systems table (fstab) entry. class Mdadm < Chef::Resource identity_attr :raid_device diff --git a/lib/chef/resource/mount.rb b/lib/chef/resource/mount.rb index 9df2bbcdbc..1a1f8c0565 100644 --- a/lib/chef/resource/mount.rb +++ b/lib/chef/resource/mount.rb @@ -21,6 +21,7 @@ require "chef/resource" class Chef class Resource + # Use the mount resource to manage a mounted file system. class Mount < Chef::Resource identity_attr :device diff --git a/lib/chef/resource/msu_package.rb b/lib/chef/resource/msu_package.rb index 753992c185..77eeed898f 100644 --- a/lib/chef/resource/msu_package.rb +++ b/lib/chef/resource/msu_package.rb @@ -21,26 +21,25 @@ require "chef/mixin/uris" class Chef class Resource + # Use the msu_package resource to install Microsoft Update(MSU) packages on Microsoft Windows machines. + # + # @since 12.17 class MsuPackage < Chef::Resource::Package include Chef::Mixin::Uris + resource_name :msu_package provides :msu_package, os: "windows" allowed_actions :install, :remove - - def initialize(name, run_context = nil) - super - @resource_name = :msu_package - @source = name - @action = :install - end + default_action :install property :source, String, coerce: (proc do |s| unless s.nil? uri_scheme?(s) ? s : Chef::Util::PathHelper.canonical_path(s, false) end - end) + end), + default: lazy { |r| r.package_name } property :checksum, String, desired_state: false end end diff --git a/lib/chef/resource/ohai.rb b/lib/chef/resource/ohai.rb index 6fffecf16e..f2534413ea 100644 --- a/lib/chef/resource/ohai.rb +++ b/lib/chef/resource/ohai.rb @@ -19,6 +19,8 @@ class Chef class Resource + # Use the ohai resource to reload the Ohai configuration on a node. This allows recipes that change system attributes + # (like a recipe that adds a user) to refer to those attributes later on during the chef-client run. class Ohai < Chef::Resource resource_name :ohai provides :ohai diff --git a/lib/chef/resource/openbsd_package.rb b/lib/chef/resource/openbsd_package.rb index d0f9fe877f..e5cdefe684 100644 --- a/lib/chef/resource/openbsd_package.rb +++ b/lib/chef/resource/openbsd_package.rb @@ -25,6 +25,9 @@ require "chef/mixin/shell_out" class Chef class Resource + # Use the openbsd_package resource to manage packages for the OpenBSD platform. + # + # @since 12.1 class OpenbsdPackage < Chef::Resource::Package include Chef::Mixin::ShellOut diff --git a/lib/chef/resource/openssl_dhparam.rb b/lib/chef/resource/openssl_dhparam.rb new file mode 100644 index 0000000000..cec27d21bd --- /dev/null +++ b/lib/chef/resource/openssl_dhparam.rb @@ -0,0 +1,59 @@ +# +# Copyright:: Copyright 2009-2018, 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/resource" + +class Chef + class Resource + # a resource for generating dhparam.pem files. + # If a valid dhparam.pem file is found at the specified location, no new + # file will be created. If a file is found at the specified location but it + # is not a valid dhparam file, it will be overwritten. + # + # @since 14.0 + class OpensslDhparam < Chef::Resource + require "chef/mixin/openssl" + include Chef::Mixin::OpenSSL + + resource_name :openssl_dhparam + + property :path, String, name_property: true + property :key_length, equal_to: [1024, 2048, 4096, 8192], default: 2048 + property :generator, equal_to: [2, 5], default: 2 + property :owner, [String, nil] + property :group, [String, nil] + property :mode, [Integer, String], default: "0640" + + action :create do + unless dhparam_pem_valid?(new_resource.path) + converge_by("Create a dhparam file #{new_resource.path}") do + dhparam_content = gen_dhparam(new_resource.key_length, new_resource.generator).to_pem + + declare_resource(:file, new_resource.path) do + action :create + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + mode new_resource.mode + sensitive true + content dhparam_content + end + end + end + end + end + end +end diff --git a/lib/chef/resource/openssl_rsa_private_key.rb b/lib/chef/resource/openssl_rsa_private_key.rb new file mode 100644 index 0000000000..32c394846b --- /dev/null +++ b/lib/chef/resource/openssl_rsa_private_key.rb @@ -0,0 +1,69 @@ +# +# Copyright:: Copyright 2009-2018, 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/resource" + +class Chef + class Resource + # A resource for generating rsa private key files. + # If a valid rsa key file can be opened at the specified location, no new file + # will be created. If the RSA key file cannot be opened, either because it + # does not exist or because the password to the RSA key file does not match + # the password in the recipe, it will be overwritten. + # + # @since 14.0 + class OpensslRsaPrivateKey < Chef::Resource + require "chef/mixin/openssl" + include Chef::Mixin::OpenSSL + + resource_name :openssl_rsa_private_key + provides :openssl_rsa_private_key + provides :openssl_rsa_key # legacy cookbook resource name + + property :path, String, name_property: true + property :key_length, equal_to: [1024, 2048, 4096, 8192], default: 2048 + property :key_pass, String + property :key_cipher, String, default: "des3", equal_to: OpenSSL::Cipher.ciphers + property :owner, [String, nil] + property :group, [String, nil] + property :mode, [Integer, String], default: "0600" + property :force, [true, false], default: false + + action :create do + return if new_resource.force || priv_key_file_valid?(new_resource.path, new_resource.key_pass) + + converge_by("create #{new_resource.key_length} bit RSA key #{new_resource.path}") do + if new_resource.key_pass + unencrypted_rsa_key = gen_rsa_priv_key(new_resource.key_length) + rsa_key_content = encrypt_rsa_key(unencrypted_rsa_key, new_resource.key_pass, new_resource.key_cipher) + else + rsa_key_content = gen_rsa_priv_key(new_resource.key_length).to_pem + end + + declare_resource(:file, new_resource.path) do + action :create + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + mode new_resource.mode + sensitive true + content rsa_key_content + end + end + end + end + end +end diff --git a/lib/chef/resource/openssl_rsa_public_key.rb b/lib/chef/resource/openssl_rsa_public_key.rb new file mode 100644 index 0000000000..602b48065e --- /dev/null +++ b/lib/chef/resource/openssl_rsa_public_key.rb @@ -0,0 +1,56 @@ +# +# Copyright:: Copyright 2009-2018, 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/resource" + +class Chef + class Resource + # A resource for generating rsa public key files given a rsa private key. + # + # @since 14.0 + class OpensslRsaPublicKey < Chef::Resource + require "chef/mixin/openssl" + include Chef::Mixin::OpenSSL + + resource_name :openssl_rsa_public_key + + property :path, String, name_property: true + property :private_key_path, String + property :private_key_content, String + property :private_key_pass, String + property :owner, [String, nil] + property :group, [String, nil] + property :mode, [Integer, String], default: "0640" + + action :create do + raise ArgumentError, "You cannot specify both 'private_key_path' and 'private_key_content' properties at the same time." if new_resource.private_key_path && new_resource.private_key_content + raise ArgumentError, "You must specify the private key with either 'private_key_path' or 'private_key_content' properties." unless new_resource.private_key_path || new_resource.private_key_content + raise "#{new_resource.private_key_path} not a valid private RSA key or password is invalid" unless priv_key_file_valid?((new_resource.private_key_path || new_resource.private_key_content), new_resource.private_key_pass) + + rsa_key_content = gen_rsa_pub_key((new_resource.private_key_path || new_resource.private_key_content), new_resource.private_key_pass) + + declare_resource(:file, new_resource.path) do + action :create + owner new_resource.owner unless new_resource.owner.nil? + group new_resource.group unless new_resource.group.nil? + mode new_resource.mode + content rsa_key_content + end + end + end + end +end diff --git a/lib/chef/resource/osx_profile.rb b/lib/chef/resource/osx_profile.rb index 8142e1fd96..1d13a8851e 100644 --- a/lib/chef/resource/osx_profile.rb +++ b/lib/chef/resource/osx_profile.rb @@ -20,6 +20,12 @@ require "chef/resource" class Chef class Resource + # Use the osx_profile resource to manage configuration profiles (.mobileconfig files) + # on the macOS platform. The osx_profile resource installs profiles by using + # the uuidgen library to generate a unique ProfileUUID, and then using the + # profiles command to install the profile on the system. + # + # @since 12.7 class OsxProfile < Chef::Resource provides :osx_profile, os: "darwin" provides :osx_config_profile, os: "darwin" @@ -29,46 +35,10 @@ class Chef default_action :install allowed_actions :install, :remove - def initialize(name, run_context = nil) - super - @profile_name = name - @profile = nil - @identifier = nil - @path = nil - end - - def profile_name(arg = nil) - set_or_return( - :profile_name, - arg, - :kind_of => [ String ] - ) - end - - def profile(arg = nil) - set_or_return( - :profile, - arg, - :kind_of => [ String, Hash ] - ) - end - - def identifier(arg = nil) - set_or_return( - :identifier, - arg, - :kind_of => [ String ] - ) - end - - def path(arg = nil) - set_or_return( - :path, - arg, - :kind_of => [ String ] - ) - end - + property :profile_name, String, name_property: true + property :profile, [ String, Hash ] + property :identifier, String + property :path, String end end end diff --git a/lib/chef/resource/package.rb b/lib/chef/resource/package.rb index 5647f203d2..60810fd5ad 100644 --- a/lib/chef/resource/package.rb +++ b/lib/chef/resource/package.rb @@ -21,6 +21,12 @@ require "chef/resource" class Chef class Resource + # Use the package resource to manage packages. When the package is installed from a local file (such as with RubyGems, + # dpkg, or RPM Package Manager), the file must be added to the node using the remote_file or cookbook_file resources. + # + # This resource is the base resource for several other resources used for package management on specific platforms. + # While it is possible to use each of these specific resources, it is recommended to use the package resource as often + # as possible. class Package < Chef::Resource resource_name :package diff --git a/lib/chef/resource/pacman_package.rb b/lib/chef/resource/pacman_package.rb index 66b39d164d..73d8afb0de 100644 --- a/lib/chef/resource/pacman_package.rb +++ b/lib/chef/resource/pacman_package.rb @@ -20,6 +20,7 @@ require "chef/resource/package" class Chef class Resource + # Use the pacman_package resource to manage packages (using pacman) on the Arch Linux platform. class PacmanPackage < Chef::Resource::Package resource_name :pacman_package provides :pacman_package, os: "linux" diff --git a/lib/chef/resource/paludis_package.rb b/lib/chef/resource/paludis_package.rb index 31c0f31b8c..6bc598e4ee 100644 --- a/lib/chef/resource/paludis_package.rb +++ b/lib/chef/resource/paludis_package.rb @@ -21,6 +21,9 @@ require "chef/provider/package/paludis" class Chef class Resource + # Use the paludis_package resource to manage packages for the Paludis platform. + # + # @since 12.1 class PaludisPackage < Chef::Resource::Package resource_name :paludis_package provides :paludis_package, os: "linux" diff --git a/lib/chef/resource/perl.rb b/lib/chef/resource/perl.rb index 60af0e92da..c00246ac6b 100644 --- a/lib/chef/resource/perl.rb +++ b/lib/chef/resource/perl.rb @@ -21,6 +21,10 @@ require "chef/provider/script" class Chef class Resource + # Use the perl resource to execute scripts using the Perl interpreter. This resource may also use any of the actions + # and properties that are available to the execute resource. Commands that are executed with this resource are (by + # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and + # only_if to guard this resource for idempotence. class Perl < Chef::Resource::Script def initialize(name, run_context = nil) super diff --git a/lib/chef/resource/portage_package.rb b/lib/chef/resource/portage_package.rb index ad66c7b42b..a2bc516711 100644 --- a/lib/chef/resource/portage_package.rb +++ b/lib/chef/resource/portage_package.rb @@ -20,6 +20,7 @@ require "chef/resource/package" class Chef class Resource + # Use the portage_package resource to manage packages for the Gentoo platform. class PortagePackage < Chef::Resource::Package resource_name :portage_package def initialize(name, run_context = nil) diff --git a/lib/chef/resource/powershell_package.rb b/lib/chef/resource/powershell_package.rb index 4d658d3cc5..05c59acf73 100644 --- a/lib/chef/resource/powershell_package.rb +++ b/lib/chef/resource/powershell_package.rb @@ -20,6 +20,11 @@ require "chef/mixin/uris" class Chef class Resource + # Use the powershell_package resource to install and manage packages via the Powershell Package Manager for the + # Microsoft Windows platform. The powershell_package resource requires administrative access, and a source must be + # configured in the Powershell Package Manager via the Register-PackageSource command + # + # @since 12.16 class PowershellPackage < Chef::Resource::Package include Chef::Mixin::Uris diff --git a/lib/chef/resource/powershell_script.rb b/lib/chef/resource/powershell_script.rb index b2bd6e718e..8ff58cfeab 100644 --- a/lib/chef/resource/powershell_script.rb +++ b/lib/chef/resource/powershell_script.rb @@ -19,6 +19,14 @@ require "chef/resource/windows_script" class Chef class Resource + # Use the powershell_script resource to execute a script using the Windows PowerShell interpreter, much like how the + # script and script-based resources—bash, csh, perl, python, and ruby—are used. The powershell_script is specific to + # the Microsoft Windows platform and the Windows PowerShell interpreter. + # + # The powershell_script resource creates and executes a temporary file (similar to how the script resource behaves), + # rather than running the command inline. Commands that are executed with this resource are (by their nature) not + # idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard + # this resource for idempotence. class PowershellScript < Chef::Resource::WindowsScript provides :powershell_script, os: "windows" diff --git a/lib/chef/resource/python.rb b/lib/chef/resource/python.rb index bcad3d090b..8c9e74217a 100644 --- a/lib/chef/resource/python.rb +++ b/lib/chef/resource/python.rb @@ -20,6 +20,10 @@ require "chef/provider/script" class Chef class Resource + # Use the python resource to execute scripts using the Python interpreter. This resource may also use any of the actions + # and properties that are available to the execute resource. Commands that are executed with this resource are (by + # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and + # only_if to guard this resource for idempotence. class Python < Chef::Resource::Script def initialize(name, run_context = nil) super diff --git a/lib/chef/resource/reboot.rb b/lib/chef/resource/reboot.rb index 519defa602..e93c7f53c5 100644 --- a/lib/chef/resource/reboot.rb +++ b/lib/chef/resource/reboot.rb @@ -18,31 +18,25 @@ require "chef/resource" -# In using this resource via notifications, it's important to *only* use -# immediate notifications. Delayed notifications produce unintuitive and -# probably undesired results. class Chef class Resource + # Use the reboot resource to reboot a node, a necessary step with some + # installations on certain platforms. This resource is supported for use on + # the Microsoft Windows, macOS, and Linux platforms. + # + # In using this resource via notifications, it's important to *only* use + # immediate notifications. Delayed notifications produce unintuitive and + # probably undesired results. + # + # @since 12.0 class Reboot < Chef::Resource - allowed_actions :request_reboot, :reboot_now, :cancel - - def initialize(name, run_context = nil) - super - @provider = Chef::Provider::Reboot - - @reason = "Reboot by Chef" - @delay_mins = 0 + resource_name :reboot - # no default action. - end - - def reason(arg = nil) - set_or_return(:reason, arg, :kind_of => String) - end + allowed_actions :request_reboot, :reboot_now, :cancel + default_action :nothing # make sure people are quite clear what they want - def delay_mins(arg = nil) - set_or_return(:delay_mins, arg, :kind_of => Integer) - end + property :reason, String, default: "Reboot by Chef" + property :delay_mins, Integer, default: 0 end end end diff --git a/lib/chef/resource/registry_key.rb b/lib/chef/resource/registry_key.rb index 549897bb1d..565ff278ea 100644 --- a/lib/chef/resource/registry_key.rb +++ b/lib/chef/resource/registry_key.rb @@ -21,6 +21,7 @@ require "chef/digester" class Chef class Resource + # Use the registry_key resource to create and delete registry keys in Microsoft Windows. class RegistryKey < Chef::Resource identity_attr :key state_attrs :values diff --git a/lib/chef/resource/remote_directory.rb b/lib/chef/resource/remote_directory.rb index 6e2928f3eb..b165606c79 100644 --- a/lib/chef/resource/remote_directory.rb +++ b/lib/chef/resource/remote_directory.rb @@ -23,6 +23,9 @@ require "chef/mixin/securable" class Chef class Resource + # Use the remote_directory resource to incrementally transfer a directory from a cookbook to a node. The director + # that is copied from the cookbook should be located under COOKBOOK_NAME/files/default/REMOTE_DIRECTORY. The + # remote_directory resource will obey file specificity. class RemoteDirectory < Chef::Resource::Directory include Chef::Mixin::Securable diff --git a/lib/chef/resource/remote_file.rb b/lib/chef/resource/remote_file.rb index 25586af702..4db055a20d 100644 --- a/lib/chef/resource/remote_file.rb +++ b/lib/chef/resource/remote_file.rb @@ -25,6 +25,8 @@ require "chef/mixin/uris" class Chef class Resource + # Use the remote_file resource to transfer a file from a remote location using file specificity. This resource is + # similar to the file resource. class RemoteFile < Chef::Resource::File include Chef::Mixin::Securable diff --git a/lib/chef/resource/resource_notification.rb b/lib/chef/resource/resource_notification.rb index 20e3c75b67..6ede2fc346 100644 --- a/lib/chef/resource/resource_notification.rb +++ b/lib/chef/resource/resource_notification.rb @@ -20,6 +20,10 @@ require "chef/resource" class Chef class Resource + # @author Tyler Ball + # @attr [Resource] resource the Chef resource object to notify to + # @attr [Action] action the action to notify + # @attr [Resource] notifying_resource the Chef resource performing the notification class Notification attr_accessor :resource, :action, :notifying_resource @@ -30,6 +34,10 @@ class Chef @notifying_resource = notifying_resource end + # Is the current notification a duplicate of another notification + # + # @param [Notification] another notification object to compare to + # @return [Boolean] does the resource match def duplicates?(other_notification) unless other_notification.respond_to?(:resource) && other_notification.respond_to?(:action) msg = "only duck-types of Chef::Resource::Notification can be checked for duplication "\ @@ -41,6 +49,9 @@ class Chef # If resource and/or notifying_resource is not a resource object, this will look them up in the resource collection # and fix the references from strings to actual Resource objects. + # @param [ResourceCollection] resource_collection + # + # @return [void] def resolve_resource_reference(resource_collection) return resource if resource.kind_of?(Chef::Resource) && notifying_resource.kind_of?(Chef::Resource) @@ -55,6 +66,9 @@ class Chef # This will look up the resource if it is not a Resource Object. It will complain if it finds multiple # resources, can't find a resource, or gets invalid syntax. + # @param [ResourceCollection] resource_collection + # + # @return [void] def fix_resource_reference(resource_collection) matching_resource = resource_collection.find(resource) if Array(matching_resource).size > 1 @@ -84,6 +98,9 @@ is defined near #{notifying_resource.source_line} # This will look up the notifying_resource if it is not a Resource Object. It will complain if it finds multiple # resources, can't find a resource, or gets invalid syntax. + # @param [ResourceCollection] resource_collection + # + # @return [void] def fix_notifier_reference(resource_collection) matching_notifier = resource_collection.find(notifying_resource) if Array(matching_notifier).size > 1 diff --git a/lib/chef/resource/route.rb b/lib/chef/resource/route.rb index 9412d28dce..922535f885 100644 --- a/lib/chef/resource/route.rb +++ b/lib/chef/resource/route.rb @@ -21,6 +21,7 @@ require "chef/resource" class Chef class Resource + # Use the route resource to manage the system routing table in a Linux environment. class Route < Chef::Resource default_action :add allowed_actions :add, :delete diff --git a/lib/chef/resource/rpm_package.rb b/lib/chef/resource/rpm_package.rb index c93dfecaf5..3760412a77 100644 --- a/lib/chef/resource/rpm_package.rb +++ b/lib/chef/resource/rpm_package.rb @@ -21,6 +21,7 @@ require "chef/provider/package/rpm" class Chef class Resource + # Use the rpm_package resource to manage packages for the RPM Package Manager platform. class RpmPackage < Chef::Resource::Package resource_name :rpm_package provides :rpm_package, os: %w{linux aix} diff --git a/lib/chef/resource/ruby.rb b/lib/chef/resource/ruby.rb index 91805a1db6..300405f89e 100644 --- a/lib/chef/resource/ruby.rb +++ b/lib/chef/resource/ruby.rb @@ -21,6 +21,10 @@ require "chef/provider/script" class Chef class Resource + # Use the ruby resource to execute scripts using the Ruby interpreter. This resource may also use any of the actions + # and properties that are available to the execute resource. Commands that are executed with this resource are (by + # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and + # only_if to guard this resource for idempotence. class Ruby < Chef::Resource::Script def initialize(name, run_context = nil) super diff --git a/lib/chef/resource/ruby_block.rb b/lib/chef/resource/ruby_block.rb index 87a4cfb7c5..89b90ae70b 100644 --- a/lib/chef/resource/ruby_block.rb +++ b/lib/chef/resource/ruby_block.rb @@ -22,6 +22,9 @@ require "chef/provider/ruby_block" class Chef class Resource + # Use the ruby_block resource to execute Ruby code during a chef-client run. Ruby code in the ruby_block resource is + # evaluated with other resources during convergence, whereas Ruby code outside of a ruby_block resource is evaluated + # before other resources, as the recipe is compiled. class RubyBlock < Chef::Resource default_action :run allowed_actions :create, :run diff --git a/lib/chef/resource/script.rb b/lib/chef/resource/script.rb index 5039e2d8fe..a7191360ca 100644 --- a/lib/chef/resource/script.rb +++ b/lib/chef/resource/script.rb @@ -22,6 +22,10 @@ require "chef/provider/script" class Chef class Resource + # Use the script resource to execute scripts using a specified interpreter, such as Bash, csh, Perl, Python, or Ruby. + # This resource may also use any of the actions and properties that are available to the execute resource. Commands + # that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the + # environment in which they are run. Use not_if and only_if to guard this resource for idempotence. class Script < Chef::Resource::Execute identity_attr :name diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb index 83e44c9d30..dc23155b59 100644 --- a/lib/chef/resource/service.rb +++ b/lib/chef/resource/service.rb @@ -22,6 +22,7 @@ require "shellwords" class Chef class Resource + # Use the service resource to manage a service. class Service < Chef::Resource identity_attr :service_name diff --git a/lib/chef/resource/smartos_package.rb b/lib/chef/resource/smartos_package.rb index 87173ccfa9..9e79cace3f 100644 --- a/lib/chef/resource/smartos_package.rb +++ b/lib/chef/resource/smartos_package.rb @@ -21,6 +21,7 @@ require "chef/provider/package/smartos" class Chef class Resource + # Use the smartos_package resource to manage packages for the SmartOS platform. class SmartosPackage < Chef::Resource::Package resource_name :smartos_package provides :package, os: "solaris2", platform_family: "smartos" diff --git a/lib/chef/resource/solaris_package.rb b/lib/chef/resource/solaris_package.rb index d0f8c144af..24215bb456 100644 --- a/lib/chef/resource/solaris_package.rb +++ b/lib/chef/resource/solaris_package.rb @@ -22,6 +22,7 @@ require "chef/provider/package/solaris" class Chef class Resource + # The solaris_package resource is used to manage packages for the Solaris platform. class SolarisPackage < Chef::Resource::Package resource_name :solaris_package provides :package, os: "solaris2", platform_family: "nexentacore" diff --git a/lib/chef/resource/subversion.rb b/lib/chef/resource/subversion.rb index 9966614eeb..473a48cefd 100644 --- a/lib/chef/resource/subversion.rb +++ b/lib/chef/resource/subversion.rb @@ -21,6 +21,7 @@ require "chef/resource/scm" class Chef class Resource + # Use the subversion resource to manage source control resources that exist in a Subversion repository. class Subversion < Chef::Resource::Scm allowed_actions :force_export diff --git a/lib/chef/resource/systemd_unit.rb b/lib/chef/resource/systemd_unit.rb index 1a19a7d682..b08b26efa7 100644 --- a/lib/chef/resource/systemd_unit.rb +++ b/lib/chef/resource/systemd_unit.rb @@ -21,6 +21,9 @@ require "iniparse" class Chef class Resource + # Use the systemd_unit resource to create, manage, and run systemd units. + # + # @since 12.11 class SystemdUnit < Chef::Resource resource_name :systemd_unit @@ -46,6 +49,9 @@ class Chef default: true, desired_state: false property :verify, [TrueClass, FalseClass], default: true, desired_state: false + property :unit_name, String, desired_state: false, + identity: true, + name_property: true def to_ini case content diff --git a/lib/chef/resource/template.rb b/lib/chef/resource/template.rb index 896aa71340..4b5b82effb 100644 --- a/lib/chef/resource/template.rb +++ b/lib/chef/resource/template.rb @@ -24,6 +24,15 @@ require "chef/mixin/securable" class Chef class Resource + # A cookbook template is an Embedded Ruby (ERB) template that is used to dynamically generate static text files. + # Templates may contain Ruby expressions and statements, and are a great way to manage configuration files. Use the + # template resource to add cookbook templates to recipes; place the corresponding Embedded Ruby (ERB) template file + # in a cookbook’s /templates directory. + # + # Use the template resource to manage the contents of a file using an Embedded Ruby (ERB) template by transferring + # files from a sub-directory of COOKBOOK_NAME/templates/ to a specified path located on a host that is running the + # chef-client. This resource includes actions and properties from the file resource. Template files managed by the + # template resource follow the same file specificity rules as the remote_file and file resources. class Template < Chef::Resource::File include Chef::Mixin::Securable diff --git a/lib/chef/resource/timestamped_deploy.rb b/lib/chef/resource/timestamped_deploy.rb deleted file mode 100644 index 1d6b07a719..0000000000 --- a/lib/chef/resource/timestamped_deploy.rb +++ /dev/null @@ -1,26 +0,0 @@ -# -# Author:: Daniel DeLeo (<dan@kallistec.com>) -# Copyright:: Copyright 2009-2016, Daniel DeLeo -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -class Chef - class Resource - # Convenience class for using the deploy resource with the timestamped - # deployment strategy (provider) - class TimestampedDeploy < Chef::Resource::Deploy - end - end -end diff --git a/lib/chef/resource/user.rb b/lib/chef/resource/user.rb index 380671113a..39d8159d4f 100644 --- a/lib/chef/resource/user.rb +++ b/lib/chef/resource/user.rb @@ -20,6 +20,7 @@ require "chef/resource" class Chef class Resource + # Use the user resource to add users, update existing users, remove users, and to lock/unlock user passwords. class User < Chef::Resource resource_name :user_resource_abstract_base_class # this prevents magickal class name DSL wiring identity_attr :username diff --git a/lib/chef/resource/windows_package.rb b/lib/chef/resource/windows_package.rb index e37bad4b0a..d373e1f19c 100644 --- a/lib/chef/resource/windows_package.rb +++ b/lib/chef/resource/windows_package.rb @@ -23,6 +23,8 @@ require "chef/win32/error" if RUBY_PLATFORM =~ /mswin|mingw|windows/ class Chef class Resource + # Use the windows_package resource to manage Microsoft Installer Package (MSI) packages for the Microsoft Windows + # platform. class WindowsPackage < Chef::Resource::Package include Chef::Mixin::Uris diff --git a/lib/chef/resource/windows_path.rb b/lib/chef/resource/windows_path.rb index 5472a7e4fd..7da24a3c06 100644 --- a/lib/chef/resource/windows_path.rb +++ b/lib/chef/resource/windows_path.rb @@ -20,21 +20,16 @@ require "chef/resource" class Chef class Resource + # Use the windows_path resource to manage the path environment variable on Microsoft Windows. + # + # @since 13.4 class WindowsPath < Chef::Resource - - provides :windows_path, os: "windows" + resource_name :windows_path + provides :windows_path allowed_actions :add, :remove default_action :add - def initialize(name, run_context = nil) - super - @resource_name = :windows_path - @path = name - @provider = Chef::Provider::WindowsPath - @action = :add - end - property :path, String, name_property: true end end diff --git a/lib/chef/resource/windows_service.rb b/lib/chef/resource/windows_service.rb index 405f7f6dbe..bcd0272b06 100644 --- a/lib/chef/resource/windows_service.rb +++ b/lib/chef/resource/windows_service.rb @@ -17,10 +17,21 @@ # require "chef/resource/service" +require "chef/win32_service_constants" class Chef class Resource + # Use the windows_service resource to manage a service on the Microsoft Windows platform. + # + # @since 12.0 class WindowsService < Chef::Resource::Service + include Chef::Win32ServiceConstants + + ALLOWED_START_TYPES = { + :automatic => SERVICE_AUTO_START, + :manual => SERVICE_DEMAND_START, + :disabled => SERVICE_DISABLED, + } # Until #1773 is resolved, you need to manually specify the windows_service resource # to use action :configure_startup and attribute startup_type @@ -28,44 +39,75 @@ class Chef provides :windows_service, os: "windows" provides :service, os: "windows" - allowed_actions :configure_startup + allowed_actions :configure_startup, :create, :delete, :configure identity_attr :service_name state_attrs :enabled, :running - def initialize(name, run_context = nil) - super - @startup_type = :automatic - @run_as_user = "" - @run_as_password = "" - end - - def startup_type(arg = nil) - # Set-Service arguments are automatic and manual - # Win32::Service returns 'auto start' or 'demand start' respectively, which the provider currently uses - set_or_return( - :startup_type, - arg, - :equal_to => [ :automatic, :manual, :disabled ] - ) - end - - def run_as_user(arg = nil) - set_or_return( - :run_as_user, - arg, - :kind_of => [ String ] - ) - end - - def run_as_password(arg = nil) - set_or_return( - :run_as_password, - arg, - :kind_of => [ String ] - ) - end + property :service_name, name_property: true + + # The display name to be used by user interface programs to identify the + # service. This string has a maximum length of 256 characters. + property :display_name, String, regex: /^.{1,256}$/ + + # https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L19-L29 + property :desired_access, Integer, default: SERVICE_ALL_ACCESS + + # https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L31-L41 + property :service_type, Integer, default: SERVICE_WIN32_OWN_PROCESS + + # Valid options: + # - :automatic + # - :manual + # - :disabled + # Reference: https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L49-L54 + property :startup_type, Integer, default: SERVICE_AUTO_START, coerce: proc { |x| + if x.is_a?(Integer) + x + elsif x.is_a?(String) or x.is_a?(Symbol) + x = x.to_sym + ALLOWED_START_TYPES.fetch(x) do + Chef::Log.warn("Unsupported startup_type #{x}, falling back to :automatic") + SERVICE_AUTO_START + end + end + } + + # This only applies if startup_type is :automatic + property :delayed_start, [Integer], default: false, coerce: proc { |x| + if x.is_a?(TrueClass) + 1 + elsif x.is_a?(FalseClass) + 0 + elsif x.is_a?(Integer) + x.zero? ? 0 : 1 + end + } + + # https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L43-L47 + property :error_control, Integer, default: SERVICE_ERROR_NORMAL + + # The fully qualified path to the service binary file. The path can also + # include arguments for an auto-start service. + property :binary_path_name, String, required: true + + # The names of the load ordering group of which this service is a member. + # Specify nil or an empty string if the service does not belong to a group. + property :load_order_group, String + + # A pointer to a double null-terminated array of null-separated names of + # services or load ordering groups that the system must start before this + # service. Specify nil or an empty string if the service has no + # dependencies. Dependency on a group means that this service can run if + # at least one member of the group is running after an attempt to start + # all members of the group. + property :dependencies, [String, Array] + + property :description, String + + property :run_as_user, String, default: 'LocalSystem' + property :run_as_password, String, default: '' end end end diff --git a/lib/chef/resource/windows_task.rb b/lib/chef/resource/windows_task.rb index 235bbdfd67..10e8400c34 100644 --- a/lib/chef/resource/windows_task.rb +++ b/lib/chef/resource/windows_task.rb @@ -20,21 +20,18 @@ require "chef/resource" class Chef class Resource + # Use the windows_task resource to create, delete or run a Windows scheduled task. Requires Windows Server 2008 + # or later due to API usage. + # @since 13.0 class WindowsTask < Chef::Resource + resource_name :windows_task provides :windows_task, os: "windows" allowed_actions :create, :delete, :run, :end, :enable, :disable default_action :create - def initialize(name, run_context = nil) - super - @resource_name = :windows_task - @task_name = name - @action = :create - end - - property :task_name, String, regex: [/\A[^\/\:\*\?\<\>\|]+\z/] + property :task_name, String, regex: [/\A[^\/\:\*\?\<\>\|]+\z/], name_property: true property :command, String property :cwd, String property :user, String, default: "SYSTEM" @@ -44,22 +41,22 @@ class Chef property :interactive_enabled, [TrueClass, FalseClass], default: false property :frequency_modifier, [Integer, String], default: 1 property :frequency, equal_to: [:minute, - :hourly, - :daily, - :weekly, - :monthly, - :once, - :on_logon, - :onstart, - :on_idle, - :none], default: :hourly + :hourly, + :daily, + :weekly, + :monthly, + :once, + :on_logon, + :onstart, + :on_idle, + :none], default: :hourly property :start_day, String property :start_time, String property :day, [String, Integer] property :months, String property :idle_time, Integer - property :random_delay, String - property :execution_time_limit, String + property :random_delay, [String, Integer] + property :execution_time_limit, [String, Integer], default: "PT72H" # 72 hours in ISO8601 duration format attr_accessor :exists, :status, :enabled @@ -71,15 +68,11 @@ class Chef end if execution_time_limit - raise ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as a String e.g. '60'." if execution_time_limit.to_i == 0 - duration = sec_to_dur(execution_time_limit) - execution_time_limit(duration) - else - # schtask sets execution_time_limit as PT72H by default - # We are setting the default value here so that we can do idempotency check later - # Note: We can't use `default` in the property - # because it will raise error for Invalid values passed as "PT72H" is not in seconds - execution_time_limit("PT72H") + unless execution_time_limit == "PT72H" # don't double convert an ISO8601 format duration + raise ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(execution_time_limit) + duration = sec_to_dur(execution_time_limit) + execution_time_limit(duration) + end end validate_start_time(start_time, frequency) @@ -89,45 +82,57 @@ class Chef validate_create_frequency_modifier(frequency, frequency_modifier) validate_create_day(day, frequency) if day validate_create_months(months, frequency) if months - validate_idle_time(idle_time, frequency) if idle_time + validate_idle_time(idle_time, frequency) if ( !idle_time.nil? && ([:minute, :hourly, :daily, :weekly, :monthly].include? frequency)) || (idle_time.nil? || !(idle_time > 0 && idle_time <= 999)) && !([:minute, :hourly, :daily, :weekly, :monthly].include? frequency) end private + # Validate the passed value is numeric values only if it is a string + def numeric_value_in_string?(val) + return true if Integer(val) + rescue ArgumentError + false + end + def validate_random_delay(random_delay, frequency) if [:once, :on_logon, :onstart, :on_idle, :none].include? frequency raise ArgumentError, "`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly" end - raise ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as a String e.g. '60'." if random_delay.to_i == 0 + raise ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(random_delay) end + # @todo when we drop ruby 2.3 support this should be converted to .match?() instead of =~f def validate_start_day(start_day, frequency) if [:once, :on_logon, :onstart, :on_idle, :none].include? frequency raise ArgumentError, "`start_day` property is not supported with frequency: #{frequency}" end + + # make sure the start_day is in MM/DD/YYYY format: http://rubular.com/r/cgjHemtWl5 + raise ArgumentError, "`start_day` property must be in the MM/DD/YYYY format." unless /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d$/ =~ start_day end + # @todo when we drop ruby 2.3 support this should be converted to .match?() instead of =~ def validate_start_time(start_time, frequency) - if frequency == :once - raise ArgumentError, "`start_time` needs to be provided with `frequency :once`" unless start_time - elsif frequency == :none - raise ArgumentError, "`start_time` property is not supported with `frequency :none`" if start_time + if start_time + raise ArgumentError, "`start_time` property is not supported with `frequency :none`" if frequency == :none + raise ArgumentError, "`start_time` property must be in the HH:mm format (e.g. 6:20pm -> 18:20)." unless /^[0-2][0-9]:[0-5][0-9]$/ =~ start_time + else + raise ArgumentError, "`start_time` needs to be provided with `frequency :once`" if frequency == :once end end SYSTEM_USERS = ['NT AUTHORITY\SYSTEM', "SYSTEM", 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', "USERS"].freeze def validate_user_and_password(user, password) - if user && use_password?(user) - if password.nil? - raise ArgumentError, "Can't specify a non-system user without a password!" - end + if password_required?(user) && password.nil? + raise ArgumentError, %q{Cannot specify a user other than the system users without specifying a password!. Valid passwordless users: 'NT AUTHORITY\SYSTEM', 'SYSTEM', 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', 'USERS'} end end - def use_password?(user) - @use_password ||= !SYSTEM_USERS.include?(user.upcase) + def password_required?(user) + return false if user.nil? + @password_required ||= !SYSTEM_USERS.include?(user.upcase) end def validate_interactive_setting(interactive_enabled, password) @@ -143,23 +148,23 @@ class Chef case frequency when :minute unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 1439 - raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :minute frequency are 1 - 1439." + raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :minute frequency are 1 - 1439." end when :hourly unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 23 - raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :hourly frequency are 1 - 23." + raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :hourly frequency are 1 - 23." end when :daily unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 365 - raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :daily frequency are 1 - 365." + raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :daily frequency are 1 - 365." end when :weekly unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 52 - raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :weekly frequency are 1 - 52." + raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :weekly frequency are 1 - 52." end when :monthly unless ("1".."12").to_a.push("FIRST", "SECOND", "THIRD", "FOURTH", "LAST", "LASTDAY").include?(frequency_modifier.to_s.upcase) - raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'." + raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'." end end end @@ -167,26 +172,24 @@ class Chef def validate_create_day(day, frequency) unless [:weekly, :monthly].include?(frequency) - raise "day attribute is only valid for tasks that run monthly or weekly" + raise "day property is only valid for tasks that run monthly or weekly" end if day.is_a?(String) && day.to_i.to_s != day days = day.split(",") days.each do |d| unless ["mon", "tue", "wed", "thu", "fri", "sat", "sun", "*"].include?(d.strip.downcase) - raise "day attribute invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma." + raise ArgumentError, "day property invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma." end end end end def validate_create_months(months, frequency) - unless [:monthly].include?(frequency) - raise "months attribute is only valid for tasks that run monthly" - end + raise ArgumentError, "months property is only valid for tasks that run monthly" unless frequency == :monthly if months.is_a? String months.split(",").each do |month| unless ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC", "*"].include?(month.strip.upcase) - raise "months attribute invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma." + raise ArgumentError, "months property invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma." end end end @@ -194,47 +197,23 @@ class Chef def validate_idle_time(idle_time, frequency) unless [:on_idle].include?(frequency) - raise "idle_time attribute is only valid for tasks that run on_idle" + raise ArgumentError, "idle_time property is only valid for tasks that run on_idle" end - - unless idle_time.to_i > 0 && idle_time.to_i <= 999 - raise "idle_time value #{idle_time} is invalid. Valid values for :on_idle frequency are 1 - 999." + if idle_time.nil? + raise ArgumentError, "idle_time value should be set for :on_idle frequency." + end + unless idle_time > 0 && idle_time <= 999 + raise ArgumentError, "idle_time value #{idle_time} is invalid. Valid values for :on_idle frequency are 1 - 999." end end - # Convert the number of seconds to an ISO8601 duration format - # @see http://tools.ietf.org/html/rfc2445#section-4.3.6 - # @param [Integer] seconds The amount of seconds for this duration + # Converts the number of seconds to an ISO8601 duration format and returns it. + # Ref : https://github.com/arnau/ISO8601/blob/master/lib/iso8601/duration.rb#L18-L23 + # e.g. + # ISO8601::Duration.new(65707200) + # returns 'P65707200S' def sec_to_dur(seconds) - seconds = seconds.to_i - return if seconds == 0 - iso_str = "P" - if seconds > 604_800 # more than a week - weeks = seconds / 604_800 - seconds -= (604_800 * weeks) - iso_str << "#{weeks}W" - end - if seconds > 86_400 # more than a day - days = seconds / 86_400 - seconds -= (86_400 * days) - iso_str << "#{days}D" - end - if seconds > 0 - iso_str << "T" - if seconds > 3600 # more than an hour - hours = seconds / 3600 - seconds -= (3600 * hours) - iso_str << "#{hours}H" - end - if seconds > 60 # more than a minute - minutes = seconds / 60 - seconds -= (60 * minutes) - iso_str << "#{minutes}M" - end - iso_str << "#{seconds}S" - end - - iso_str + ISO8601::Duration.new(seconds.to_i).to_s end end diff --git a/lib/chef/resource/yum_repository.rb b/lib/chef/resource/yum_repository.rb index 012a74908a..7c30bc5457 100644 --- a/lib/chef/resource/yum_repository.rb +++ b/lib/chef/resource/yum_repository.rb @@ -1,6 +1,6 @@ # # Author:: Thom May (<thom@chef.io>) -# Copyright:: Copyright (c) 2016 Chef Software, Inc. +# Copyright:: Copyright (c) 2016-2017 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,55 +20,59 @@ require "chef/resource" class Chef class Resource + # Use the yum_repository resource to manage a Yum repository configuration file located at /etc/yum.repos.d/repositoryid.repo + # on the local machine. This configuration file specifies which repositories to reference, how to handle cached data, etc. + # + # @since 12.14 class YumRepository < Chef::Resource resource_name :yum_repository provides :yum_repository # http://linux.die.net/man/5/yum.conf as well as # http://dnf.readthedocs.io/en/latest/conf_ref.html - property :baseurl, [String, Array], regex: /.*/ + property :baseurl, [String, Array] property :clean_headers, [TrueClass, FalseClass], default: false # deprecated property :clean_metadata, [TrueClass, FalseClass], default: true property :cost, String, regex: /^\d+$/ - property :description, String, regex: /.*/, default: "Yum Repository" + property :description, String, default: "Yum Repository" property :enabled, [TrueClass, FalseClass], default: true property :enablegroups, [TrueClass, FalseClass] - property :exclude, String, regex: /.*/ + property :exclude, String property :failovermethod, String, equal_to: %w{priority roundrobin} property :fastestmirror_enabled, [TrueClass, FalseClass] property :gpgcheck, [TrueClass, FalseClass], default: true - property :gpgkey, [String, Array], regex: /.*/ + property :gpgkey, [String, Array] property :http_caching, String, equal_to: %w{packages all none} - property :include_config, String, regex: /.*/ - property :includepkgs, String, regex: /.*/ + property :include_config, String + property :includepkgs, String property :keepalive, [TrueClass, FalseClass] property :make_cache, [TrueClass, FalseClass], default: true property :max_retries, [String, Integer] property :metadata_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/] - property :metalink, String, regex: /.*/ + property :metalink, String property :mirror_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/] - property :mirrorexpire, String, regex: /.*/ + property :mirrorexpire, String property :mirrorlist_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/] - property :mirrorlist, String, regex: /.*/ + property :mirrorlist, String property :mode, default: "0644" property :options, Hash - property :password, String, regex: /.*/ - property :priority, String, regex: /^(\d?[0-9]|[0-9][0-9])$/ - property :proxy_password, String, regex: /.*/ - property :proxy_username, String, regex: /.*/ - property :proxy, String, regex: /.*/ + property :password, String + property :priority, String, regex: /^(\d?[1-9]|[0-9][0-9])$/ + property :proxy_password, String + property :proxy_username, String + property :proxy, String property :repo_gpgcheck, [TrueClass, FalseClass] property :report_instanceid, [TrueClass, FalseClass] - property :repositoryid, String, regex: /.*/, name_property: true + property :repositoryid, String, name_property: true property :skip_if_unavailable, [TrueClass, FalseClass] - property :source, String, regex: /.*/ - property :sslcacert, String, regex: /.*/ - property :sslclientcert, String, regex: /.*/ - property :sslclientkey, String, regex: /.*/ + property :source, String + property :sslcacert, String + property :sslclientcert, String + property :sslclientkey, String property :sslverify, [TrueClass, FalseClass] - property :timeout, String, regex: /^\d+$/ property :throttle, [String, Integer] - property :username, String, regex: /.*/ + property :timeout, String, regex: /^\d+$/ + property :username, String default_action :create allowed_actions :create, :remove, :makecache, :add, :delete diff --git a/lib/chef/resource/zypper_package.rb b/lib/chef/resource/zypper_package.rb index 20b1a9f25f..f412d59988 100644 --- a/lib/chef/resource/zypper_package.rb +++ b/lib/chef/resource/zypper_package.rb @@ -20,6 +20,8 @@ require "chef/resource/package" class Chef class Resource + # Use the zypper_package resource to install, upgrade, and remove packages with Zypper for the SUSE Enterprise and + # OpenSUSE platforms. class ZypperPackage < Chef::Resource::Package resource_name :zypper_package provides :package, platform_family: "suse" diff --git a/lib/chef/resource/zypper_repository.rb b/lib/chef/resource/zypper_repository.rb index 88b6fd9336..72e0074b2a 100644 --- a/lib/chef/resource/zypper_repository.rb +++ b/lib/chef/resource/zypper_repository.rb @@ -20,6 +20,11 @@ require "chef/resource" class Chef class Resource + # The zypper_repository resource allows for the creation of Zypper package repositories on SUSE Enterprise Linux and + # openSUSE systems. This resource maintains full compatibility with the zypper_repository resource in the existing + # zypper cookbook. + # + # @since 13.3 class ZypperRepository < Chef::Resource resource_name :zypper_repository provides :zypper_repo @@ -38,7 +43,7 @@ class Chef property :keeppackages, [true, false], default: false property :mode, default: "0644" property :refresh_cache, [true, false], default: true - property :source, String, regex: /.*/ + property :source, String property :cookbook, String property :gpgautoimportkeys, [true, false], default: true diff --git a/lib/chef/resource_reporter.rb b/lib/chef/resource_reporter.rb index afc8500a2a..53e7ea9e30 100644 --- a/lib/chef/resource_reporter.rb +++ b/lib/chef/resource_reporter.rb @@ -3,7 +3,7 @@ # Author:: Prajakta Purohit (prajakta@chef.io>) # Auther:: Tyler Cloke (<tyler@opscode.com>) # -# 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"); @@ -94,7 +94,6 @@ class Chef attr_reader :updated_resources attr_reader :status attr_reader :exception - attr_reader :run_id attr_reader :error_descriptions PROTOCOL_VERSION = "0.1.0" diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb index 54d21fd53c..9fee978432 100644 --- a/lib/chef/resources.rb +++ b/lib/chef/resources.rb @@ -28,15 +28,12 @@ require "chef/resource/chef_gem" require "chef/resource/chocolatey_package" require "chef/resource/cron" require "chef/resource/csh" -require "chef/resource/deploy" -require "chef/resource/deploy_revision" require "chef/resource/directory" require "chef/resource/dpkg_package" require "chef/resource/dnf_package" require "chef/resource/dsc_script" require "chef/resource/dsc_resource" require "chef/resource/env" -require "chef/resource/erl_call" require "chef/resource/execute" require "chef/resource/file" require "chef/resource/freebsd_package" @@ -56,6 +53,9 @@ require "chef/resource/mdadm" require "chef/resource/mount" require "chef/resource/ohai" require "chef/resource/openbsd_package" +require "chef/resource/openssl_dhparam" +require "chef/resource/openssl_rsa_private_key" +require "chef/resource/openssl_rsa_public_key" require "chef/resource/package" require "chef/resource/pacman_package" require "chef/resource/paludis_package" @@ -81,7 +81,6 @@ require "chef/resource/windows_service" require "chef/resource/subversion" require "chef/resource/smartos_package" require "chef/resource/template" -require "chef/resource/timestamped_deploy" require "chef/resource/user" require "chef/resource/user/aix_user" require "chef/resource/user/dscl_user" diff --git a/lib/chef/role.rb b/lib/chef/role.rb index c22c77b70d..ad01e9fa26 100644 --- a/lib/chef/role.rb +++ b/lib/chef/role.rb @@ -2,7 +2,7 @@ # Author:: Adam Jacob (<adam@chef.io>) # Author:: Nuo Yan (<nuo@chef.io>) # Author:: Christopher Brown (<cb@chef.io>) -# 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"); @@ -33,8 +33,6 @@ class Chef include Chef::Mixin::FromFile include Chef::Mixin::ParamsValidate - attr_accessor :chef_server_rest - # Create a new Chef::Role object. def initialize(chef_server_rest: nil) @name = "" diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb index fc32ab3eeb..b2eee0406e 100644 --- a/lib/chef/run_context.rb +++ b/lib/chef/run_context.rb @@ -29,7 +29,6 @@ require "forwardable" class Chef - # == Chef::RunContext # Value object that loads and tracks the context of a Chef run class RunContext # @@ -312,7 +311,7 @@ class Chef # # @param recipe_names [Array[String]] The recipe name (e.g 'my_cookbook' or # 'my_cookbook::my_resource'). - # @param current_cookbook The cookbook we are currently running in. + # @param current_cookbook [String] The cookbook we are currently running in. # # @return A truthy value if the load occurred; `false` if already loaded. # @@ -556,11 +555,18 @@ ERROR_MESSAGE @reboot_info = reboot_info end + # + # Cancels a pending reboot + # def cancel_reboot Chef::Log.info "Changing reboot status from #{reboot_info.inspect} to {}" @reboot_info = {} end + # + # Checks to see if a reboot has been requested + # @return [Boolean] + # def reboot_requested? reboot_info.size > 0 end diff --git a/lib/chef/search/query.rb b/lib/chef/search/query.rb index a2663d111d..b7b15765bb 100644 --- a/lib/chef/search/query.rb +++ b/lib/chef/search/query.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# 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"); @@ -27,7 +27,6 @@ class Chef class Search class Query - attr_accessor :rest attr_reader :config def initialize(url = nil, config: Chef::Config) diff --git a/lib/chef/server_api.rb b/lib/chef/server_api.rb index 2bdc5d9fe8..c501544954 100644 --- a/lib/chef/server_api.rb +++ b/lib/chef/server_api.rb @@ -31,6 +31,7 @@ class Chef def initialize(url = Chef::Config[:chef_server_url], options = {}) options[:client_name] ||= Chef::Config[:node_name] + options[:raw_key] ||= Chef::Config[:client_key_contents] options[:signing_key_filename] ||= Chef::Config[:client_key] unless options[:raw_key] options[:signing_key_filename] = nil if chef_zero_uri?(url) options[:inflate_json_class] = false diff --git a/lib/chef/shell.rb b/lib/chef/shell.rb index 40bdf01762..88d26e78fc 100644 --- a/lib/chef/shell.rb +++ b/lib/chef/shell.rb @@ -41,7 +41,6 @@ module Shell LEADERS[Chef::Node] = ":attributes" class << self - attr_accessor :client_type attr_accessor :options attr_accessor :env attr_writer :editor diff --git a/lib/chef/shell/model_wrapper.rb b/lib/chef/shell/model_wrapper.rb index 8c3e456a9b..4394caa395 100644 --- a/lib/chef/shell/model_wrapper.rb +++ b/lib/chef/shell/model_wrapper.rb @@ -17,7 +17,7 @@ # require "chef/mixin/convert_to_class_name" -require "chef/mixin/language" +require "chef/dsl/data_query" module Shell class ModelWrapper diff --git a/lib/chef/shell/shell_session.rb b/lib/chef/shell/shell_session.rb index dfed5372c1..ce2e457461 100644 --- a/lib/chef/shell/shell_session.rb +++ b/lib/chef/shell/shell_session.rb @@ -2,7 +2,7 @@ # Author:: Daniel DeLeo (<dan@kallistec.com>) # Author:: Tim Hinderliter (<tim@chef.io>) # Copyright:: Copyright 2009-2016, Daniel DeLeo -# Copyright:: Copyright 2011-2016, 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"); @@ -38,7 +38,7 @@ module Shell @session_type end - attr_accessor :node, :compile, :recipe, :run_context, :json_configuration + attr_accessor :node, :compile, :recipe, :json_configuration attr_reader :node_attributes, :client def initialize @node_built = false @@ -73,6 +73,7 @@ module Shell run_context.resource_collection end + attr_writer :run_context def run_context @run_context ||= rebuild_context end diff --git a/lib/chef/util/windows/volume.rb b/lib/chef/util/windows/volume.rb index dc9c0ca1d0..358a3f4bb8 100644 --- a/lib/chef/util/windows/volume.rb +++ b/lib/chef/util/windows/volume.rb @@ -46,8 +46,4 @@ class Chef::Util::Windows::Volume < Chef::Util::Windows rescue Chef::Exceptions::Win32APIError => e raise ArgumentError, e end - - def mount_point - @mount_point - end end diff --git a/lib/chef/version.rb b/lib/chef/version.rb index 51655c48db..cae58c492a 100644 --- a/lib/chef/version.rb +++ b/lib/chef/version.rb @@ -23,7 +23,7 @@ require "chef/version_string" class Chef CHEF_ROOT = File.expand_path("../..", __FILE__) - VERSION = Chef::VersionString.new("13.6.19") + VERSION = Chef::VersionString.new("14.0.11") end # diff --git a/lib/chef/version/platform.rb b/lib/chef/version/platform.rb index 07b1a17b11..6d8f4192fe 100644 --- a/lib/chef/version/platform.rb +++ b/lib/chef/version/platform.rb @@ -16,6 +16,24 @@ require "chef/version_class" +# NOTE: this is fairly badly broken for its purpose and should not be used +# unless it gets fixed. + +# this strictly wants x, x.y, or x.y.z version constraints in the target and +# will fail hard if it does not match. the semantics that we need here is that +# it must always do the best job that it can do and consume as much of the +# offered version as it can. since we accept arbitrarily parsed strings into +# node[:platform_version] out of dozens or potentially hundreds of operating +# systems this parsing code needs to be fixed to never raise. the Gem::Version +# class is a better model, and in fact it might be a substantially better approach +# to base this class on Gem::Version and then do pre-mangling of things like windows +# version strings via e.g. `.gsub(/R/, '.')`. the raising behavior of this parser +# however, breaks the ProviderResolver in a not just buggy but a "completely unfit +# for purpose" way. +# +# TL;DR: MUST follow the second part of "Be conservative in what you send, +# be liberal in what you accept" +# class Chef class Version class Platform < Chef::Version diff --git a/lib/chef/version_constraint/platform.rb b/lib/chef/version_constraint/platform.rb index 29f4678bb5..e39da194c6 100644 --- a/lib/chef/version_constraint/platform.rb +++ b/lib/chef/version_constraint/platform.rb @@ -16,6 +16,8 @@ require "chef/version_constraint" require "chef/version/platform" +# NOTE: this is fairly badly broken for its purpose and should not be used +# unless it gets fixed. see chef/version/platform. class Chef class VersionConstraint class Platform < Chef::VersionConstraint diff --git a/lib/chef/win32/registry.rb b/lib/chef/win32/registry.rb index 6f1eb9ff12..4a1dbe3eac 100644 --- a/lib/chef/win32/registry.rb +++ b/lib/chef/win32/registry.rb @@ -2,7 +2,7 @@ # Author:: Prajakta Purohit (<prajakta@chef.io>) # Author:: Lamont Granquist (<lamont@chef.io>) # -# Copyright:: Copyright 2012-2016, Chef Software Inc. +# Copyright:: Copyright 2012-2018, 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. @@ -40,7 +40,7 @@ class Chef extend Chef::Mixin::WideString attr_accessor :run_context - attr_accessor :architecture + attr_reader :architecture def initialize(run_context = nil, user_architecture = :machine) @run_context = run_context diff --git a/lib/chef/win32_service_constants.rb b/lib/chef/win32_service_constants.rb new file mode 100644 index 0000000000..4b5eb34327 --- /dev/null +++ b/lib/chef/win32_service_constants.rb @@ -0,0 +1,143 @@ +class Chef + module Win32ServiceConstants + SC_MANAGER_ALL_ACCESS = 0xF003F + SC_MANAGER_CREATE_SERVICE = 0x0002 + SC_MANAGER_CONNECT = 0x0001 + SC_MANAGER_ENUMERATE_SERVICE = 0x0004 + SC_MANAGER_LOCK = 0x0008 + SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020 + SC_MANAGER_QUERY_LOCK_STATUS = 0x0010 + SC_STATUS_PROCESS_INFO = 0 + SC_ENUM_PROCESS_INFO = 0 + + # Service control action types + SC_ACTION_NONE = 0 + SC_ACTION_RESTART = 1 + SC_ACTION_REBOOT = 2 + SC_ACTION_RUN_COMMAND = 3 + + # Service access rights + SERVICE_ALL_ACCESS = 0xF01FF + SERVICE_CHANGE_CONFIG = 0x0002 + SERVICE_ENUMERATE_DEPENDENTS = 0x0008 + SERVICE_INTERROGATE = 0x0080 + SERVICE_PAUSE_CONTINUE = 0x0040 + SERVICE_QUERY_CONFIG = 0x0001 + SERVICE_QUERY_STATUS = 0x0004 + SERVICE_START = 0x0010 + SERVICE_STOP = 0x0020 + SERVICE_USER_DEFINED_CONTROL = 0x0100 + + # Service types + SERVICE_KERNEL_DRIVER = 0x00000001 + SERVICE_FILE_SYSTEM_DRIVER = 0x00000002 + SERVICE_ADAPTER = 0x00000004 + SERVICE_RECOGNIZER_DRIVER = 0x00000008 + SERVICE_WIN32_OWN_PROCESS = 0x00000010 + SERVICE_WIN32_SHARE_PROCESS = 0x00000020 + SERVICE_WIN32 = 0x00000030 + SERVICE_INTERACTIVE_PROCESS = 0x00000100 + SERVICE_DRIVER = 0x0000000B + SERVICE_TYPE_ALL = 0x0000013F + + # Error control + SERVICE_ERROR_IGNORE = 0x00000000 + SERVICE_ERROR_NORMAL = 0x00000001 + SERVICE_ERROR_SEVERE = 0x00000002 + SERVICE_ERROR_CRITICAL = 0x00000003 + + # Start types + SERVICE_BOOT_START = 0x00000000 + SERVICE_SYSTEM_START = 0x00000001 + SERVICE_AUTO_START = 0x00000002 + SERVICE_DEMAND_START = 0x00000003 + SERVICE_DISABLED = 0x00000004 + + # Service control + + SERVICE_CONTROL_STOP = 0x00000001 + SERVICE_CONTROL_PAUSE = 0x00000002 + SERVICE_CONTROL_CONTINUE = 0x00000003 + SERVICE_CONTROL_INTERROGATE = 0x00000004 + SERVICE_CONTROL_SHUTDOWN = 0x00000005 + SERVICE_CONTROL_PARAMCHANGE = 0x00000006 + SERVICE_CONTROL_NETBINDADD = 0x00000007 + SERVICE_CONTROL_NETBINDREMOVE = 0x00000008 + SERVICE_CONTROL_NETBINDENABLE = 0x00000009 + SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A + SERVICE_CONTROL_DEVICEEVENT = 0x0000000B + SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0x0000000C + SERVICE_CONTROL_POWEREVENT = 0x0000000D + SERVICE_CONTROL_SESSIONCHANGE = 0x0000000E + SERVICE_CONTROL_PRESHUTDOWN = 0x0000000F + SERVICE_CONTROL_TIMECHANGE = 0x00000010 + SERVICE_CONTROL_TRIGGEREVENT = 0x00000020 + + # Service controls accepted + + SERVICE_ACCEPT_STOP = 0x00000001 + SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002 + SERVICE_ACCEPT_SHUTDOWN = 0x00000004 + SERVICE_ACCEPT_PARAMCHANGE = 0x00000008 + SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010 + SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020 + SERVICE_ACCEPT_POWEREVENT = 0x00000040 + SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080 + SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100 + SERVICE_ACCEPT_TIMECHANGE = 0x00000200 + SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400 + + # Service states + SERVICE_ACTIVE = 0x00000001 + SERVICE_INACTIVE = 0x00000002 + SERVICE_STATE_ALL = 0x00000003 + + # Service current states + SERVICE_STOPPED = 0x00000001 + SERVICE_START_PENDING = 0x00000002 + SERVICE_STOP_PENDING = 0x00000003 + SERVICE_RUNNING = 0x00000004 + SERVICE_CONTINUE_PENDING = 0x00000005 + SERVICE_PAUSE_PENDING = 0x00000006 + SERVICE_PAUSED = 0x00000007 + + # Info levels + SERVICE_CONFIG_DESCRIPTION = 1 + SERVICE_CONFIG_FAILURE_ACTIONS = 2 + SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3 + SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4 + SERVICE_CONFIG_SERVICE_SID_INFO = 5 + SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 6 + SERVICE_CONFIG_PRESHUTDOWN_INFO = 7 + + # Configuration + SERVICE_NO_CHANGE = 0xffffffff + + # Misc + + WAIT_OBJECT_0 = 0 + WAIT_TIMEOUT = 0x00000102 + INFINITE = 0xFFFFFFFF + + IDLE_CONTROL_CODE = 0 + + DELETE = 0x00010000 + FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000 + FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200 + + NO_ERROR = 0 + + SE_PRIVILEGE_ENABLED = 0x00000002 + TOKEN_ADJUST_PRIVILEGES = 0x0020 + TOKEN_QUERY = 0x0008 + + # Errors + + ERROR_INSUFFICIENT_BUFFER = 122 + ERROR_MORE_DATA = 234 + ERROR_FILE_NOT_FOUND = 2 + ERROR_RESOURCE_TYPE_NOT_FOUND = 1813 + ERROR_RESOURCE_NAME_NOT_FOUND = 1814 + WAIT_FAILED = 0xFFFFFFFF + end +end |