From ed47d1ef46a8ea1537a077f19c15526b1c7e8736 Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Mon, 31 Jul 2023 21:31:11 -0700 Subject: [PATCH 1/8] Lint/ConstantDefinitionInBlock (metaprogramming) When metaprogramming types, parameters and providers, we defined constants within the block, such as Puppet::Type.type(:package).provide(:xxx) do SOMETHING = ... The constant isn't namespaced in the way you'd expect and instead is defined at top-level, potentially clashing with non-Puppet code. In order to define constants on the generated class: Puppet::Type::Package::ProviderXXX use `const_set` instead. But continue providing the "legacy" constant to maintain backwards compatibility and mark it as deprecated. A deprecation warning will only be generated if the legacy constant is accessed when running ruby with -W2: $ bundle exec ruby -W2 -rpuppet -e "Puppet::Type.type(:package).provider(:yum); RPM_VERSION" ... -e:1: warning: constant ::RPM_VERSION is deprecated --- .rubocop_todo.yml | 5 --- lib/puppet/provider/package/aix.rb | 11 ++++-- lib/puppet/provider/package/apt.rb | 29 ++++++++------ lib/puppet/provider/package/gem.rb | 22 +++++++---- lib/puppet/provider/package/pip.rb | 30 +++++++++------ lib/puppet/provider/package/yum.rb | 36 ++++++++++-------- lib/puppet/provider/package/zypper.rb | 2 +- lib/puppet/provider/service/upstart.rb | 40 ++++++++++++-------- lib/puppet/provider/user/directoryservice.rb | 6 +-- lib/puppet/type/file.rb | 20 ++++++---- lib/puppet/type/file/source.rb | 2 +- lib/puppet/type/resources.rb | 10 +++-- lib/puppet/type/schedule.rb | 21 +++++++--- lib/puppet/type/tidy.rb | 10 +++-- 14 files changed, 149 insertions(+), 95 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 370677a7173..75822fcd045 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -580,11 +580,6 @@ Layout/TrailingEmptyLines: Layout/TrailingWhitespace: Enabled: false -# Configuration parameters: AllowedMethods. -# AllowedMethods: enums -Lint/ConstantDefinitionInBlock: - Enabled: false - Lint/MissingSuper: Enabled: false diff --git a/lib/puppet/provider/package/aix.rb b/lib/puppet/provider/package/aix.rb index e29d9bfaa1a..c270982ea7b 100644 --- a/lib/puppet/provider/package/aix.rb +++ b/lib/puppet/provider/package/aix.rb @@ -30,14 +30,17 @@ attr_accessor :latest_info - STATE_CODE = { + const_set(:STATE_CODE, { 'A' => :applied, 'B' => :broken, 'C' => :committed, 'E' => :efix_locked, 'O' => :obsolete, '?' => :inconsistent, - }.freeze + }.freeze) + # deprecate top-level constant + STATE_CODE = const_get(:STATE_CODE) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:STATE_CODE) def self.srclistcmd(source) [ command(:installp), "-L", "-d", source ] @@ -124,8 +127,8 @@ def self.pkglist(hash = {}) begin list = execute(cmd).scan(/^[^#][^:]*:([^:]*):([^:]*):[^:]*:[^:]*:([^:])/).collect { |n,e,s| - e = :absent if [:broken, :inconsistent].include?(STATE_CODE[s]) - { :name => n, :ensure => e, :status => STATE_CODE[s], :provider => self.name } + e = :absent if [:broken, :inconsistent].include?(self::STATE_CODE[s]) + { :name => n, :ensure => e, :status => self::STATE_CODE[s], :provider => self.name } } rescue Puppet::ExecutionFailure => detail if hash[:pkgname] diff --git a/lib/puppet/provider/package/apt.rb b/lib/puppet/provider/package/apt.rb index 9207440d1ca..dcdf871d54e 100644 --- a/lib/puppet/provider/package/apt.rb +++ b/lib/puppet/provider/package/apt.rb @@ -5,8 +5,15 @@ Puppet::Type.type(:package).provide :apt, :parent => :dpkg, :source => :dpkg do # Provide sorting functionality include Puppet::Util::Package - DebianVersion = Puppet::Util::Package::Version::Debian - VersionRange = Puppet::Util::Package::Version::Range + const_set(:DebianVersion, Puppet::Util::Package::Version::Debian) + const_set(:VersionRange, Puppet::Util::Package::Version::Range) + + # deprecate top-level constants + DebianVersion = const_get(:DebianVersion) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:DebianVersion) + VersionRange = const_get(:VersionRange) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:VersionRange) + desc "Package management via `apt-get`. This provider supports the `install_options` attribute, which allows command-line flags to be passed to apt-get. @@ -98,9 +105,9 @@ def best_version(should_range) output.each_line do |line| is = line.split('|')[1].strip begin - is_version = DebianVersion.parse(is) + is_version = self.class::DebianVersion.parse(is) versions << is_version if should_range.include?(is_version) - rescue DebianVersion::ValidationFailure + rescue self.class::DebianVersion::ValidationFailure Puppet.debug("Cannot parse #{is} as a debian version") end end @@ -119,12 +126,12 @@ def install if should.is_a?(String) begin - should_range = VersionRange.parse(should, DebianVersion) + should_range = self.class::VersionRange.parse(should, self.class::DebianVersion) - unless should_range.is_a?(VersionRange::Eq) + unless should_range.is_a?(self.class::VersionRange::Eq) should = best_version(should_range) end - rescue VersionRange::ValidationFailure, DebianVersion::ValidationFailure + rescue self.class::VersionRange::ValidationFailure, self.class::DebianVersion::ValidationFailure Puppet.debug("Cannot parse #{should} as a debian version range, falling through") end end @@ -240,15 +247,15 @@ def insync?(is) return false unless is.is_a?(String) && should.is_a?(String) begin - should_range = VersionRange.parse(should, DebianVersion) - rescue VersionRange::ValidationFailure, DebianVersion::ValidationFailure + should_range = self.class::VersionRange.parse(should, self.class::DebianVersion) + rescue self.class::VersionRange::ValidationFailure, self.class::DebianVersion::ValidationFailure Puppet.debug("Cannot parse #{should} as a debian version range") return false end begin - is_version = DebianVersion.parse(is) - rescue DebianVersion::ValidationFailure + is_version = self.class::DebianVersion.parse(is) + rescue self.class::DebianVersion::ValidationFailure Puppet.debug("Cannot parse #{is} as a debian version") return false end diff --git a/lib/puppet/provider/package/gem.rb b/lib/puppet/provider/package/gem.rb index 9b4d48c64f1..722634de109 100644 --- a/lib/puppet/provider/package/gem.rb +++ b/lib/puppet/provider/package/gem.rb @@ -20,8 +20,14 @@ has_feature :versionable, :install_options, :uninstall_options, :targetable, :version_ranges - GEM_VERSION = Puppet::Util::Package::Version::Gem - GEM_VERSION_RANGE = Puppet::Util::Package::Version::Range + const_set(:GEM_VERSION, Puppet::Util::Package::Version::Gem) + const_set(:GEM_VERSION_RANGE, Puppet::Util::Package::Version::Range) + + # deprecate top-level constants + GEM_VERSION = const_get(:GEM_VERSION) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:GEM_VERSION) + GEM_VERSION_RANGE = const_get(:GEM_VERSION_RANGE) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:GEM_VERSION_RANGE) # Override the specificity method to return 1 if gem is not set as default provider def self.specificity @@ -158,16 +164,16 @@ def insync?(is) unless should =~ Regexp.union(/,/, Gem::Requirement::PATTERN) begin - should_range = GEM_VERSION_RANGE.parse(should, GEM_VERSION) - rescue GEM_VERSION_RANGE::ValidationFailure, GEM_VERSION::ValidationFailure + should_range = self.class::GEM_VERSION_RANGE.parse(should, self.class::GEM_VERSION) + rescue self.class::GEM_VERSION_RANGE::ValidationFailure, self.class::GEM_VERSION::ValidationFailure Puppet.debug("Cannot parse #{should} as a ruby gem version range") return false end return is.any? do |version| begin - should_range.include?(GEM_VERSION.parse(version)) - rescue GEM_VERSION::ValidationFailure + should_range.include?(self.class::GEM_VERSION.parse(version)) + rescue self.class::GEM_VERSION::ValidationFailure Puppet.debug("Cannot parse #{version} as a ruby gem version") false end @@ -199,10 +205,10 @@ def install(useversion = true) unless should =~ Regexp.union(/,/, Gem::Requirement::PATTERN) begin - should_range = GEM_VERSION_RANGE.parse(should, GEM_VERSION) + should_range = self.class::GEM_VERSION_RANGE.parse(should, self.class::GEM_VERSION) should = should_range.to_gem_version useversion = true - rescue GEM_VERSION_RANGE::ValidationFailure, GEM_VERSION::ValidationFailure + rescue self.class::GEM_VERSION_RANGE::ValidationFailure, self.class::GEM_VERSION::ValidationFailure Puppet.debug("Cannot parse #{should} as a ruby gem version range. Falling through.") end end diff --git a/lib/puppet/provider/package/pip.rb b/lib/puppet/provider/package/pip.rb index 9264b8c9375..f7da2fc3483 100644 --- a/lib/puppet/provider/package/pip.rb +++ b/lib/puppet/provider/package/pip.rb @@ -15,8 +15,14 @@ has_feature :installable, :uninstallable, :upgradeable, :versionable, :version_ranges, :install_options, :targetable - PIP_VERSION = Puppet::Util::Package::Version::Pip - PIP_VERSION_RANGE = Puppet::Util::Package::Version::Range + const_set(:PIP_VERSION, Puppet::Util::Package::Version::Pip) + const_set(:PIP_VERSION_RANGE, Puppet::Util::Package::Version::Range) + + # deprecate top-level constants + PIP_VERSION = const_get(:PIP_VERSION) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:PIP_VERSION) + PIP_VERSION_RANGE = const_get(:PIP_VERSION_RANGE) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:PIP_VERSION_RANGE) # Override the specificity method to return 1 if pip is not set as default provider def self.specificity @@ -134,7 +140,7 @@ def latest def self.compare_pip_versions(x, y) begin Puppet::Util::Package::Version::Pip.compare(x, y) - rescue PIP_VERSION::ValidationFailure => ex + rescue self::PIP_VERSION::ValidationFailure => ex Puppet.debug("Cannot compare #{x} and #{y}. #{ex.message} Falling through default comparison mechanism.") Puppet::Util::Package.versioncmp(x, y) end @@ -202,7 +208,7 @@ def available_versions_with_old_pip def best_version(should_range) included_available_versions = [] available_versions.each do |version| - version = PIP_VERSION.parse(version) + version = self.class::PIP_VERSION.parse(version) included_available_versions.push(version) if should_range.include?(version) end @@ -241,15 +247,15 @@ def get_install_command_options() end begin - should_range = PIP_VERSION_RANGE.parse(should, PIP_VERSION) - rescue PIP_VERSION_RANGE::ValidationFailure, PIP_VERSION::ValidationFailure + should_range = self.class::PIP_VERSION_RANGE.parse(should, self.class::PIP_VERSION) + rescue self.class::PIP_VERSION_RANGE::ValidationFailure, self.class::PIP_VERSION::ValidationFailure Puppet.debug("Cannot parse #{should} as a pip version range, falling through.") command_options << "#{@resource[:name]}==#{should}" return command_options end - if should_range.is_a?(PIP_VERSION_RANGE::Eq) + if should_range.is_a?(self.class::PIP_VERSION_RANGE::Eq) command_options << "#{@resource[:name]}==#{should}" return command_options @@ -259,7 +265,7 @@ def get_install_command_options() if should == should_range # when no suitable version for the given range was found, let pip handle - if should.is_a?(PIP_VERSION_RANGE::MinMax) + if should.is_a?(self.class::PIP_VERSION_RANGE::MinMax) command_options << "#{@resource[:name]} #{should.split.join(',')}" else command_options << "#{@resource[:name]} #{should}" @@ -306,15 +312,15 @@ def insync?(is) return false unless is && is != :absent begin should = @resource[:ensure] - should_range = PIP_VERSION_RANGE.parse(should, PIP_VERSION) - rescue PIP_VERSION_RANGE::ValidationFailure, PIP_VERSION::ValidationFailure + should_range = self.class::PIP_VERSION_RANGE.parse(should, self.class::PIP_VERSION) + rescue self.class::PIP_VERSION_RANGE::ValidationFailure, self.class::PIP_VERSION::ValidationFailure Puppet.debug("Cannot parse #{should} as a pip version range") return false end begin - is_version = PIP_VERSION.parse(is) - rescue PIP_VERSION::ValidationFailure + is_version = self.class::PIP_VERSION.parse(is) + rescue self.class::PIP_VERSION::ValidationFailure Puppet.debug("Cannot parse #{is} as a pip version") return false end diff --git a/lib/puppet/provider/package/yum.rb b/lib/puppet/provider/package/yum.rb index 36afec6313e..2a8cdc3eda7 100644 --- a/lib/puppet/provider/package/yum.rb +++ b/lib/puppet/provider/package/yum.rb @@ -18,8 +18,14 @@ has_feature :install_options, :versionable, :virtual_packages, :install_only, :version_ranges - RPM_VERSION = Puppet::Util::Package::Version::Rpm - RPM_VERSION_RANGE = Puppet::Util::Package::Version::Range + const_set(:RPM_VERSION, Puppet::Util::Package::Version::Rpm) + const_set(:RPM_VERSION_RANGE, Puppet::Util::Package::Version::Range) + + # deprecate top-level constants + RPM_VERSION = const_get(:RPM_VERSION) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:RPM_VERSION) + RPM_VERSION_RANGE = const_get(:RPM_VERSION_RANGE) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:RPM_VERSION_RANGE) commands :cmd => "yum", :rpm => "rpm" @@ -43,28 +49,28 @@ def insync?(is) should = @resource[:ensure] if should.is_a?(String) begin - should_version = RPM_VERSION_RANGE.parse(should, RPM_VERSION) + should_version = self.class::RPM_VERSION_RANGE.parse(should, self.class::RPM_VERSION) - if should_version.is_a?(RPM_VERSION_RANGE::Eq) + if should_version.is_a?(self.class::RPM_VERSION_RANGE::Eq) return super end - rescue RPM_VERSION_RANGE::ValidationFailure, RPM_VERSION::ValidationFailure + rescue self.class::RPM_VERSION_RANGE::ValidationFailure, self.class::RPM_VERSION::ValidationFailure Puppet.debug("Cannot parse #{should} as a RPM version range") return super end is.split(self.class::MULTIVERSION_SEPARATOR).any? do |version| begin - is_version = RPM_VERSION.parse(version) + is_version = self.class::RPM_VERSION.parse(version) should_version.include?(is_version) - rescue RPM_VERSION::ValidationFailure + rescue self.class::RPM_VERSION::ValidationFailure Puppet.debug("Cannot parse #{is} as a RPM version") end end end end - VERSION_REGEX = /^(?:(\d+):)?(\S+)-(\S+)$/ + const_set(:VERSION_REGEX, /^(?:(\d+):)?(\S+)-(\S+)$/) def self.prefetch(packages) raise Puppet::Error, _("The yum provider can only be used as root") if Process.euid != 0 @@ -134,7 +140,7 @@ def self.parse_updates(str) body.split(/^\s*\n/).each do |line| line.split.each_slice(3) do |tuple| - next unless tuple[0].include?('.') && tuple[1] =~ VERSION_REGEX + next unless tuple[0].include?('.') && tuple[1] =~ self::VERSION_REGEX hash = update_to_hash(*tuple[0..1]) # Create entries for both the package name without a version and a @@ -159,7 +165,7 @@ def self.update_to_hash(pkgname, pkgversion) raise _("Failed to parse package name and architecture from '%{pkgname}'") % { pkgname: pkgname } end - match = pkgversion.match(VERSION_REGEX) + match = pkgversion.match(self::VERSION_REGEX) epoch = match[1] || '0' version = match[2] release = match[3] @@ -196,20 +202,20 @@ def self.update_command def best_version(should) if should.is_a?(String) begin - should_range = RPM_VERSION_RANGE.parse(should, RPM_VERSION) - if should_range.is_a?(RPM_VERSION_RANGE::Eq) + should_range = self.class::RPM_VERSION_RANGE.parse(should, self.class::RPM_VERSION) + if should_range.is_a?(self.class::RPM_VERSION_RANGE::Eq) return should end - rescue RPM_VERSION_RANGE::ValidationFailure, RPM_VERSION::ValidationFailure + rescue self.class::RPM_VERSION_RANGE::ValidationFailure, self.class::RPM_VERSION::ValidationFailure Puppet.debug("Cannot parse #{should} as a RPM version range") return should end versions = [] available_versions(@resource[:name], disablerepo, enablerepo, disableexcludes).each do |version| begin - rpm_version = RPM_VERSION.parse(version) + rpm_version = self.class::RPM_VERSION.parse(version) versions << rpm_version if should_range.include?(rpm_version) - rescue RPM_VERSION::ValidationFailure + rescue self.class::RPM_VERSION::ValidationFailure Puppet.debug("Cannot parse #{version} as a RPM version") end end diff --git a/lib/puppet/provider/package/zypper.rb b/lib/puppet/provider/package/zypper.rb index bd23120fe5a..1c3925115ba 100644 --- a/lib/puppet/provider/package/zypper.rb +++ b/lib/puppet/provider/package/zypper.rb @@ -188,7 +188,7 @@ def insync?(is) if should.is_a?(String) begin should_version = Puppet::Util::Package::Version::Range.parse(should, Puppet::Util::Package::Version::Rpm) - if should_version.is_a?(RPM_VERSION_RANGE::Eq) + if should_version.is_a?(Puppet::Util::Package::Version::Range::Eq) return super end rescue Puppet::Util::Package::Version::Range::ValidationFailure, Puppet::Util::Package::Version::Rpm::ValidationFailure diff --git a/lib/puppet/provider/service/upstart.rb b/lib/puppet/provider/service/upstart.rb index 42fca395fab..72e47f14499 100644 --- a/lib/puppet/provider/service/upstart.rb +++ b/lib/puppet/provider/service/upstart.rb @@ -1,8 +1,16 @@ # frozen_string_literal: true Puppet::Type.type(:service).provide :upstart, :parent => :debian do - START_ON = /^\s*start\s+on/ - COMMENTED_START_ON = /^\s*#+\s*start\s+on/ - MANUAL = /^\s*manual\s*$/ + const_set(:START_ON, /^\s*start\s+on/) + const_set(:COMMENTED_START_ON, /^\s*#+\s*start\s+on/) + const_set(:MANUAL, /^\s*manual\s*$/) + + # deprecate top-level constants + START_ON = const_get(:START_ON) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:START_ON) + COMMENTED_START_ON = const_get(:COMMENTED_START_ON) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:COMMENTED_START_ON) + MANUAL = const_get(:MANUAL) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:MANUAL) desc "Ubuntu service management with `upstart`. @@ -211,7 +219,7 @@ def version_is_post_0_9_0 def enabled_pre_0_6_7?(script_text) # Upstart version < 0.6.7 means no manual stanza. - if script_text.match(START_ON) + if script_text.match(self.class::START_ON) return :true else return :false @@ -224,9 +232,9 @@ def enabled_pre_0_9_0?(script_text) # The last one in the file wins. enabled = :false script_text.each_line do |line| - if line.match(START_ON) + if line.match(self.class::START_ON) enabled = :true - elsif line.match(MANUAL) + elsif line.match(self.class::MANUAL) enabled = :false end end @@ -240,16 +248,16 @@ def enabled_post_0_9_0?(script_text, over_text) enabled = :false script_text.each_line do |line| - if line.match(START_ON) + if line.match(self.class::START_ON) enabled = :true - elsif line.match(MANUAL) + elsif line.match(self.class::MANUAL) enabled = :false end end over_text.each_line do |line| - if line.match(START_ON) + if line.match(self.class::START_ON) enabled = :true - elsif line.match(MANUAL) + elsif line.match(self.class::MANUAL) enabled = :false end end if over_text @@ -262,7 +270,7 @@ def enable_pre_0_9_0(text) if enabled_pre_0_9_0?(text) == :false enabled_script = - if text.match(COMMENTED_START_ON) + if text.match(self.class::COMMENTED_START_ON) uncomment_start_block_in(text) else add_default_start_to(text) @@ -278,7 +286,7 @@ def enable_post_0_9_0(script_text, over_text) over_text = remove_manual_from(over_text) if enabled_post_0_9_0?(script_text, over_text) == :false - if script_text.match(START_ON) + if script_text.match(self.class::START_ON) over_text << extract_start_on_block_from(script_text) else over_text << "\nstart on runlevel [2,3,4,5]" @@ -326,13 +334,13 @@ def unbalanced_parens_on(line) end def remove_manual_from(text) - text.gsub(MANUAL, "") + text.gsub(self.class::MANUAL, "") end def comment_start_block_in(text) parens = 0 text.lines.map do |line| - if line.match(START_ON) || parens > 0 + if line.match(self.class::START_ON) || parens > 0 # If there are more opening parens than closing parens, we need to comment out a multiline 'start on' stanza parens += unbalanced_parens_on(remove_trailing_comments_from(line)) "#" + line @@ -345,7 +353,7 @@ def comment_start_block_in(text) def uncomment_start_block_in(text) parens = 0 text.lines.map do |line| - if line.match(COMMENTED_START_ON) || parens > 0 + if line.match(self.class::COMMENTED_START_ON) || parens > 0 parens += unbalanced_parens_on(remove_trailing_comments_from_commented_line_of(line)) uncomment(line) else @@ -357,7 +365,7 @@ def uncomment_start_block_in(text) def extract_start_on_block_from(text) parens = 0 text.lines.map do |line| - if line.match(START_ON) || parens > 0 + if line.match(self.class::START_ON) || parens > 0 parens += unbalanced_parens_on(remove_trailing_comments_from(line)) line end diff --git a/lib/puppet/provider/user/directoryservice.rb b/lib/puppet/provider/user/directoryservice.rb index 2cc6e21439d..c0765e67069 100644 --- a/lib/puppet/provider/user/directoryservice.rb +++ b/lib/puppet/provider/user/directoryservice.rb @@ -549,7 +549,7 @@ def write_password_to_users_plist(value) # could be missing entirely and without it the managed user cannot log in if needs_sha512_pbkdf2_authentication_authority_to_be_added?(users_plist) Puppet.debug("Adding 'SALTED-SHA512-PBKDF2' AuthenticationAuthority key for ShadowHash to user '#{@resource.name}'") - merge_attribute_with_dscl('Users', @resource.name, 'AuthenticationAuthority', ERB::Util.html_escape(SHA512_PBKDF2_AUTHENTICATION_AUTHORITY)) + merge_attribute_with_dscl('Users', @resource.name, 'AuthenticationAuthority', ERB::Util.html_escape(self.class::SHA512_PBKDF2_AUTHENTICATION_AUTHORITY)) end set_salted_pbkdf2(users_plist, shadow_hash_data, 'entropy', value) @@ -583,7 +583,7 @@ def get_shadow_hash_data(users_plist) # where users created with `dscl` started to have this field missing def needs_sha512_pbkdf2_authentication_authority_to_be_added?(users_plist) authority = users_plist['authentication_authority'] - return false if Puppet::Util::Package.versioncmp(self.class.get_os_version, '11.0.0') < 0 && authority && authority.include?(SHA512_PBKDF2_AUTHENTICATION_AUTHORITY) + return false if Puppet::Util::Package.versioncmp(self.class.get_os_version, '11.0.0') < 0 && authority && authority.include?(self.class::SHA512_PBKDF2_AUTHENTICATION_AUTHORITY) Puppet.debug("User '#{@resource.name}' is missing the 'SALTED-SHA512-PBKDF2' AuthenticationAuthority key for ShadowHash") true @@ -677,5 +677,5 @@ def set_salted_pbkdf2(users_plist, shadow_hash_data, field, value) private - SHA512_PBKDF2_AUTHENTICATION_AUTHORITY = ';ShadowHash;HASHLIST:' + const_set(:SHA512_PBKDF2_AUTHENTICATION_AUTHORITY, ';ShadowHash;HASHLIST:') end diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb index 2c22f3bfeaa..d2789a20b4d 100644 --- a/lib/puppet/type/file.rb +++ b/lib/puppet/type/file.rb @@ -417,26 +417,32 @@ def self.title_patterns end # mutually exclusive ways to create files - CREATORS = [:content, :source, :target].freeze + const_set(:CREATORS, [:content, :source, :target].freeze) # This is both "checksum types that can't be used with the content property" # and "checksum types that are not digest based" - SOURCE_ONLY_CHECKSUMS = [:none, :ctime, :mtime].freeze + const_set(:SOURCE_ONLY_CHECKSUMS, [:none, :ctime, :mtime].freeze) + + # deprecate top-level constants + CREATORS = const_get(:CREATORS) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:CREATORS) + SOURCE_ONLY_CHECKSUMS = const_get(:SOURCE_ONLY_CHECKSUMS) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:SOURCE_ONLY_CHECKSUMS) validate do creator_count = 0 - CREATORS.each do |param| + self.class::CREATORS.each do |param| creator_count += 1 if self.should(param) end creator_count += 1 if @parameters.include?(:source) - self.fail _("You cannot specify more than one of %{creators}") % { creators: CREATORS.collect { |p| p.to_s}.join(", ") } if creator_count > 1 + self.fail _("You cannot specify more than one of %{creators}") % { creators: self.class::CREATORS.collect { |p| p.to_s}.join(", ") } if creator_count > 1 self.fail _("You cannot specify a remote recursion without a source") if !self[:source] && self[:recurse] == :remote self.fail _("You cannot specify source when using checksum 'none'") if self[:checksum] == :none && !self[:source].nil? - SOURCE_ONLY_CHECKSUMS.each do |checksum_type| + self.class::SOURCE_ONLY_CHECKSUMS.each do |checksum_type| self.fail _("You cannot specify content when using checksum '%{checksum_type}'") % { checksum_type: checksum_type } if self[:checksum] == checksum_type && !self[:content].nil? end @@ -1077,7 +1083,7 @@ def fail_if_checksum_is_wrong(property, path, content_checksum) # Return the desired checksum or nil def desired_checksum(property, path) - return if SOURCE_ONLY_CHECKSUMS.include?(self[:checksum]) + return if self.class::SOURCE_ONLY_CHECKSUMS.include?(self[:checksum]) if self[:checksum] && self[:checksum_value] "{#{self[:checksum]}}#{self[:checksum_value]}" @@ -1086,7 +1092,7 @@ def desired_checksum(property, path) return unless meta # due to HttpMetadata the checksum type may fallback to mtime, so recheck - return if SOURCE_ONLY_CHECKSUMS.include?(meta.checksum_type) + return if self.class::SOURCE_ONLY_CHECKSUMS.include?(meta.checksum_type) meta.checksum elsif property && property.name == :content str = property.actual_content diff --git a/lib/puppet/type/file/source.rb b/lib/puppet/type/file/source.rb index f23e0c62f2f..d568d879259 100644 --- a/lib/puppet/type/file/source.rb +++ b/lib/puppet/type/file/source.rb @@ -101,7 +101,7 @@ module Puppet end end - SEPARATOR_REGEX = [Regexp.escape(File::SEPARATOR.to_s), Regexp.escape(File::ALT_SEPARATOR.to_s)].join + SEPARATOR_REGEX = [Regexp.escape(File::SEPARATOR.to_s), Regexp.escape(File::ALT_SEPARATOR.to_s)].join.freeze # rubocop:disable Lint/ConstantDefinitionInBlock munge do |sources| sources = [sources] unless sources.is_a?(Array) diff --git a/lib/puppet/type/resources.rb b/lib/puppet/type/resources.rb index 27c9d8aec76..5a5621d4788 100644 --- a/lib/puppet/type/resources.rb +++ b/lib/puppet/type/resources.rb @@ -89,11 +89,15 @@ end end - WINDOWS_SYSTEM_SID_REGEXES = + const_set(:WINDOWS_SYSTEM_SID_REGEXES, # Administrator, Guest, Domain Admins, Schema Admins, Enterprise Admins. # https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems [/S-1-5-21.+-500/, /S-1-5-21.+-501/, /S-1-5-21.+-512/, /S-1-5-21.+-518/, - /S-1-5-21.+-519/] + /S-1-5-21.+-519/]) + + # deprecate top-level constant + WINDOWS_SYSTEM_SID_REGEXES = const_get(:WINDOWS_SYSTEM_SID_REGEXES) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:WINDOWS_SYSTEM_SID_REGEXES) def check(resource) @checkmethod ||= "#{self[:name]}_check" @@ -151,7 +155,7 @@ def user_check(resource) return false if unless_uids && unless_uids.include?(current_uid) if current_uid.is_a?(String) # Windows user; is a system user if any regex matches. - WINDOWS_SYSTEM_SID_REGEXES.none? { |regex| current_uid =~ regex } + self.class::WINDOWS_SYSTEM_SID_REGEXES.none? { |regex| current_uid =~ regex } else current_uid > self[:unless_system_user] end diff --git a/lib/puppet/type/schedule.rb b/lib/puppet/type/schedule.rb index 8f13513cdad..011368bf96b 100644 --- a/lib/puppet/type/schedule.rb +++ b/lib/puppet/type/schedule.rb @@ -229,13 +229,13 @@ def match?(previous, now) newvalues(:hourly, :daily, :weekly, :monthly, :never) - ScheduleScales = { + const_set(:ScheduleScales, { :hourly => 3600, :daily => 86400, :weekly => 604800, :monthly => 2592000 - } - ScheduleMethods = { + }.freeze) + const_set(:ScheduleMethods, { :hourly => :hour, :daily => :day, :monthly => :month, @@ -244,7 +244,16 @@ def match?(previous, now) # or if it's been more than a week since we ran prev.wday > now.wday or (now - prev) > (24 * 3600 * 7) end - } + }.freeze) + + # deprecate Puppet constants, these are not top-level because of the way this type + # is defined using: + # module Puppet + # Type.newtype(:schedule) + ScheduleScales = const_get(:ScheduleScales) # rubocop:disable Lint/ConstantDefinitionInBlock + Puppet.deprecate_constant(:ScheduleScales) + ScheduleMethods = const_get(:ScheduleMethods) # rubocop:disable Lint/ConstantDefinitionInBlock + Puppet.deprecate_constant(:ScheduleMethods) def match?(previous, now) return false if value == :never @@ -252,7 +261,7 @@ def match?(previous, now) value = self.value case @resource[:periodmatch] when :number - method = ScheduleMethods[value] + method = self.class::ScheduleMethods[value] if method.is_a?(Proc) return method.call(previous, now) else @@ -260,7 +269,7 @@ def match?(previous, now) return now.send(method) != previous.send(method) end when :distance - scale = ScheduleScales[value] + scale = self.class::ScheduleScales[value] # If the number of seconds between the two times is greater # than the unit of time, we match. We divide the scale diff --git a/lib/puppet/type/tidy.rb b/lib/puppet/type/tidy.rb index 319bdfa742b..a7ddf71ac8e 100644 --- a/lib/puppet/type/tidy.rb +++ b/lib/puppet/type/tidy.rb @@ -126,16 +126,20 @@ def tidy?(path, stat) Specifying 0 will remove all files." - AgeConvertors = { + const_set(:AgeConvertors, { :s => 1, :m => 60, :h => 60 * 60, :d => 60 * 60 * 24, :w => 60 * 60 * 24 * 7, - } + }.freeze) + + # deprecate top-level constant + AgeConvertors = const_get(:AgeConvertors) # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:AgeConvertors) def convert(unit, multi) - num = AgeConvertors[unit] + num = self.class::AgeConvertors[unit] if num return num * multi else From a12bba47d1e8211ec5f98f537a4d05535d47a6f1 Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Mon, 31 Jul 2023 21:31:11 -0700 Subject: [PATCH 2/8] Lint/ConstantDefinitionInBlock (faces) Constants defined in blocks aren't namespaced and instead are created in the top-level namespace, e.g. DEFAULT_SECTION. Define a new module for each face in which to store their respective constants and deprecate the old top-level constants. A deprecation warning will only be generated if the legacy constant is accessed when running ruby with -W2. --- lib/puppet/face/config.rb | 27 +++++++++++++++-------- lib/puppet/face/help.rb | 21 +++++++++++++----- lib/puppet/face/node/clean.rb | 40 ++++++++++++++++++----------------- 3 files changed, 55 insertions(+), 33 deletions(-) diff --git a/lib/puppet/face/config.rb b/lib/puppet/face/config.rb index f500f224a8d..1addf661724 100644 --- a/lib/puppet/face/config.rb +++ b/lib/puppet/face/config.rb @@ -2,6 +2,11 @@ require_relative '../../puppet/face' require_relative '../../puppet/settings/ini_file' +module Puppet::Face::Config + DEFAULT_SECTION_MARKER = Object.new + DEFAULT_SECTION = "main" +end + Puppet::Face.define(:config, '0.0.1') do extend Puppet::Util::Colors copyright "Puppet Inc.", 2011 @@ -13,10 +18,14 @@ 'puppet.conf' configuration file. For documentation about individual settings, see https://puppet.com/docs/puppet/latest/configuration.html." - DEFAULT_SECTION_MARKER = Object.new - DEFAULT_SECTION = "main" + # deprecate top-level constants + DEFAULT_SECTION_MARKER = Puppet::Face::Config::DEFAULT_SECTION_MARKER # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:DEFAULT_SECTION_MARKER) + DEFAULT_SECTION = Puppet::Face::Config::DEFAULT_SECTION # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:DEFAULT_SECTION) + option "--section " + _("SECTION_NAME") do - default_to { DEFAULT_SECTION_MARKER } #Sentinel object for default detection during commands + default_to { Puppet::Face::Config::DEFAULT_SECTION_MARKER } # Sentinel object for default detection during commands summary _("The section of the configuration file to interact with.") description <<-EOT The section of the puppet.conf configuration file to interact with. @@ -62,8 +71,8 @@ options = args.pop @default_section = false - if options[:section] == DEFAULT_SECTION_MARKER - options[:section] = DEFAULT_SECTION + if options[:section] == Puppet::Face::Config::DEFAULT_SECTION_MARKER + options[:section] = Puppet::Face::Config::DEFAULT_SECTION @default_section = true end @@ -138,8 +147,8 @@ def report_section_and_environment(section_name, environment_name) when_invoked do |name, value, options| @default_section = false - if options[:section] == DEFAULT_SECTION_MARKER - options[:section] = DEFAULT_SECTION + if options[:section] == Puppet::Face::Config::DEFAULT_SECTION_MARKER + options[:section] = Puppet::Face::Config::DEFAULT_SECTION @default_section = true end @@ -221,8 +230,8 @@ def report_section_and_environment(section_name, environment_name) when_invoked do |name, options| @default_section = false - if options[:section] == DEFAULT_SECTION_MARKER - options[:section] = DEFAULT_SECTION + if options[:section] == Puppet::Face::Config::DEFAULT_SECTION_MARKER + options[:section] = Puppet::Face::Config::DEFAULT_SECTION @default_section = true end diff --git a/lib/puppet/face/help.rb b/lib/puppet/face/help.rb index 0d5d6ac6563..a64a55c149f 100644 --- a/lib/puppet/face/help.rb +++ b/lib/puppet/face/help.rb @@ -5,6 +5,12 @@ require 'pathname' require 'erb' +module Puppet::Face::Help + COMMON = 'Common:' + SPECIALIZED = 'Specialized:' + BLANK = "\n" +end + Puppet::Face.define(:help, '0.0.1') do copyright "Puppet Inc.", 2011 license _("Apache 2 license; see COPYING") @@ -162,7 +168,7 @@ def all_application_summaries() available_application_names_special_sort().inject([]) do |result, appname| next result if exclude_from_docs?(appname) - if (appname == COMMON || appname == SPECIALIZED || appname == BLANK) + if (appname == Puppet::Face::Help::COMMON || appname == Puppet::Face::Help::SPECIALIZED || appname == Puppet::Face::Help::BLANK) result << appname elsif (is_face_app?(appname)) begin @@ -191,16 +197,21 @@ def all_application_summaries() end end - COMMON = 'Common:' - SPECIALIZED = 'Specialized:' - BLANK = "\n" + # Deprecate top-level constants + COMMON = Puppet::Face::Help::COMMON # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:COMMON) + SPECIALIZED = Puppet::Face::Help::SPECIALIZED # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:SPECIALIZED) + BLANK = Puppet::Face::Help::BLANK # rubocop:disable Lint/ConstantDefinitionInBlock + Object.deprecate_constant(:BLANK) + def available_application_names_special_sort() full_list = Puppet::Application.available_application_names a_list = full_list & %w{apply agent config help lookup module resource} a_list = a_list.sort also_ran = full_list - a_list also_ran = also_ran.sort - [[COMMON], a_list, [BLANK], [SPECIALIZED], also_ran].flatten(1) + [[Puppet::Face::Help::COMMON], a_list, [Puppet::Face::Help::BLANK], [Puppet::Face::Help::SPECIALIZED], also_ran].flatten(1) end def horribly_extract_summary_from(appname) diff --git a/lib/puppet/face/node/clean.rb b/lib/puppet/face/node/clean.rb index eca65250dae..6eba29e5a2a 100644 --- a/lib/puppet/face/node/clean.rb +++ b/lib/puppet/face/node/clean.rb @@ -47,28 +47,10 @@ def cleanup(node) clean_reports(node) end - class LoggerIO - def debug(message) - Puppet.debug(message) - end - - def warn(message) - Puppet.warning(message) unless message =~ /cadir is currently configured to be inside/ - end - - def err(message) - Puppet.err(message) unless message =~ /^\s*Error:\s*/ - end - - def inform(message) - Puppet.notice(message) - end - end - # clean signed cert for +host+ def clean_cert(node) if Puppet.features.puppetserver_ca? - Puppetserver::Ca::Action::Clean.new(LoggerIO.new).run({ 'certnames' => [node] }) + Puppetserver::Ca::Action::Clean.new(Puppet::Face::Node::LoggerIO.new).run({ 'certnames' => [node] }) else Puppet.info _("Not managing %{node} certs as this host is not a CA") % { node: node } end @@ -106,3 +88,23 @@ def type_is_ensurable(resource) return false end end + +module Puppet::Face::Node + class LoggerIO + def debug(message) + Puppet.debug(message) + end + + def warn(message) + Puppet.warning(message) unless message =~ /cadir is currently configured to be inside/ + end + + def err(message) + Puppet.err(message) unless message =~ /^\s*Error:\s*/ + end + + def inform(message) + Puppet.notice(message) + end + end +end From bb21107fab63c6b06bb9cebf29efb8c97d11b18d Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Mon, 4 Dec 2023 16:44:36 -0800 Subject: [PATCH 3/8] Lint/MissingSuper (NEEDS WORK) Explicitly call `super` to avoid bugs that can occur if functionality is added to a superclass' initialize method, but isn't added to all of the subclasses that don't call `super`. There are a few places where it's not clear if calling super is the correct thing, and in those cases the cop has been disabled. In cases where the super and subclass initialize an instance variable, have the subclass call to the superclass' initialize method, such as the EvaluatingEppParser/EvaluatingParser, PSensitiveType/PAnyType, and HTTP client resolvers. Also call super for `inherited` and `method_added` lifecycle methods. --- .rubocop_todo.yml | 3 --- lib/puppet/confine.rb | 1 + lib/puppet/forge.rb | 1 + lib/puppet/http/external_client.rb | 2 +- lib/puppet/http/resolver/server_list.rb | 2 +- lib/puppet/http/resolver/srv.rb | 2 +- lib/puppet/indirector/catalog/compiler.rb | 1 + lib/puppet/indirector/memory.rb | 1 + lib/puppet/indirector/report/processor.rb | 1 + lib/puppet/indirector/terminus.rb | 2 ++ .../module_tool/applications/uninstaller.rb | 2 +- lib/puppet/module_tool/installed_modules.rb | 1 + lib/puppet/module_tool/local_tarball.rb | 1 + lib/puppet/parser/ast/hostclass.rb | 1 + lib/puppet/parser/ast/node.rb | 1 + lib/puppet/parser/ast/pops_bridge.rb | 1 + lib/puppet/pops/adapters.rb | 1 + lib/puppet/pops/evaluator/closure.rb | 3 +++ .../pops/evaluator/relationship_operator.rb | 2 ++ lib/puppet/pops/functions/dispatch.rb | 1 + lib/puppet/pops/loader/static_loader.rb | 1 + lib/puppet/pops/lookup/context.rb | 1 + lib/puppet/pops/lookup/data_adapter.rb | 1 + lib/puppet/pops/lookup/explainer.rb | 4 ++++ lib/puppet/pops/model/factory.rb | 1 + lib/puppet/pops/parser/evaluating_parser.rb | 8 ++++---- lib/puppet/pops/parser/lexer_support.rb | 1 + lib/puppet/pops/parser/locatable.rb | 1 + lib/puppet/pops/parser/locator.rb | 1 + lib/puppet/pops/semantic_error.rb | 1 + lib/puppet/pops/time/timespan.rb | 3 +++ lib/puppet/pops/types/iterable.rb | 2 +- lib/puppet/pops/types/p_object_type.rb | 2 +- .../pops/types/p_object_type_extension.rb | 1 + lib/puppet/pops/types/p_runtime_type.rb | 1 + lib/puppet/pops/types/p_sem_ver_type.rb | 1 + lib/puppet/pops/types/p_sensitive_type.rb | 2 +- lib/puppet/pops/types/p_timespan_type.rb | 1 + lib/puppet/pops/types/p_type_set_type.rb | 1 + lib/puppet/pops/types/p_uri_type.rb | 1 + lib/puppet/pops/types/ruby_method.rb | 1 + lib/puppet/pops/types/types.rb | 17 +++++++++++++++++ lib/puppet/property.rb | 2 ++ lib/puppet/property/ensure.rb | 2 ++ lib/puppet/type.rb | 1 + lib/puppet/util/package/version/debian.rb | 2 +- lib/puppet/util/package/version/rpm.rb | 2 +- .../util/rdoc/generators/puppet_generator.rb | 1 + spec/unit/pops/loaders/loaders_spec.rb | 6 +++--- 49 files changed, 80 insertions(+), 19 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 75822fcd045..08bf5226930 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -580,9 +580,6 @@ Layout/TrailingEmptyLines: Layout/TrailingWhitespace: Enabled: false -Lint/MissingSuper: - Enabled: false - Lint/NestedMethodDefinition: Exclude: - 'lib/puppet/pops/types/p_binary_type.rb' diff --git a/lib/puppet/confine.rb b/lib/puppet/confine.rb index bffb2c573b3..8ee6a3a35f5 100644 --- a/lib/puppet/confine.rb +++ b/lib/puppet/confine.rb @@ -13,6 +13,7 @@ class << self end def self.inherited(klass) + super(klass) name = klass.to_s.split("::").pop.downcase.to_sym raise "Test #{name} is already defined" if @tests.include?(name) diff --git a/lib/puppet/forge.rb b/lib/puppet/forge.rb index fb7436b5a04..529e476f7d2 100644 --- a/lib/puppet/forge.rb +++ b/lib/puppet/forge.rb @@ -24,6 +24,7 @@ class Puppet::Forge < SemanticPuppet::Dependency::Source attr_reader :host, :repository def initialize(host = Puppet[:module_repository]) + super() @host = host @repository = Puppet::Forge::Repository.new(host, USER_AGENT) end diff --git a/lib/puppet/http/external_client.rb b/lib/puppet/http/external_client.rb index eebe666d14e..933993e666d 100644 --- a/lib/puppet/http/external_client.rb +++ b/lib/puppet/http/external_client.rb @@ -11,7 +11,7 @@ class Puppet::HTTP::ExternalClient < Puppet::HTTP::Client # Create an external http client. # # @param [Class] http_client_class The class to create to handle the request - def initialize(http_client_class) + def initialize(http_client_class) #rubocop:disable Lint/MissingSuper @http_client_class = http_client_class end diff --git a/lib/puppet/http/resolver/server_list.rb b/lib/puppet/http/resolver/server_list.rb index 68ca2c38b5f..a1ade814092 100644 --- a/lib/puppet/http/resolver/server_list.rb +++ b/lib/puppet/http/resolver/server_list.rb @@ -17,7 +17,7 @@ class Puppet::HTTP::Resolver::ServerList < Puppet::HTTP::Resolver # will return nil. # def initialize(client, server_list_setting:, default_port:, services: ) - @client = client + super(client) @server_list_setting = server_list_setting @default_port = default_port @services = services diff --git a/lib/puppet/http/resolver/srv.rb b/lib/puppet/http/resolver/srv.rb index e92cb84828c..1381e8e9f5f 100644 --- a/lib/puppet/http/resolver/srv.rb +++ b/lib/puppet/http/resolver/srv.rb @@ -11,7 +11,7 @@ class Puppet::HTTP::Resolver::SRV < Puppet::HTTP::Resolver # @param [Resolv::DNS] dns # def initialize(client, domain:, dns: Resolv::DNS.new) - @client = client + super(client) @srv_domain = domain @delegate = Puppet::HTTP::DNS.new(dns) end diff --git a/lib/puppet/indirector/catalog/compiler.rb b/lib/puppet/indirector/catalog/compiler.rb index cf4e8c21974..9b579b21195 100644 --- a/lib/puppet/indirector/catalog/compiler.rb +++ b/lib/puppet/indirector/catalog/compiler.rb @@ -91,6 +91,7 @@ def filter(catalog) end def initialize + super() Puppet::Util::Profiler.profile(_("Setup server facts for compiling"), [:compiler, :init_server_facts]) do set_server_facts end diff --git a/lib/puppet/indirector/memory.rb b/lib/puppet/indirector/memory.rb index a6f9239eb2a..29b3d18408d 100644 --- a/lib/puppet/indirector/memory.rb +++ b/lib/puppet/indirector/memory.rb @@ -4,6 +4,7 @@ # Manage a memory-cached list of instances. class Puppet::Indirector::Memory < Puppet::Indirector::Terminus def initialize + super clear end diff --git a/lib/puppet/indirector/report/processor.rb b/lib/puppet/indirector/report/processor.rb index 1826b098c7e..9f999599196 100644 --- a/lib/puppet/indirector/report/processor.rb +++ b/lib/puppet/indirector/report/processor.rb @@ -8,6 +8,7 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code the report types listed in the 'reports' setting." def initialize + super Puppet.settings.use(:main, :reporting, :metrics) end diff --git a/lib/puppet/indirector/terminus.rb b/lib/puppet/indirector/terminus.rb index 812a00d968c..e1c6c38a063 100644 --- a/lib/puppet/indirector/terminus.rb +++ b/lib/puppet/indirector/terminus.rb @@ -48,6 +48,8 @@ def indirection_name # This follows the convention that our terminus is named after the # indirection. def inherited(subclass) + super(subclass) + longname = subclass.to_s if longname =~ /# runtime name # @api public def initialize(runtime, name_or_pattern) + super() unless runtime.nil? || runtime.is_a?(Symbol) runtime = TypeAsserter.assert_instance_of("Runtime 'runtime'", PStringType::NON_EMPTY, runtime).to_sym end diff --git a/lib/puppet/pops/types/p_sem_ver_type.rb b/lib/puppet/pops/types/p_sem_ver_type.rb index ef4187a45f8..90500cc1c4e 100644 --- a/lib/puppet/pops/types/p_sem_ver_type.rb +++ b/lib/puppet/pops/types/p_sem_ver_type.rb @@ -19,6 +19,7 @@ def self.register_ptype(loader, ir) attr_reader :ranges def initialize(ranges) + super() ranges = ranges.map { |range| range.is_a?(SemanticPuppet::VersionRange) ? range : SemanticPuppet::VersionRange.parse(range) } ranges = merge_ranges(ranges) if ranges.size > 1 @ranges = ranges diff --git a/lib/puppet/pops/types/p_sensitive_type.rb b/lib/puppet/pops/types/p_sensitive_type.rb index 507ba51cbd3..f76e9158076 100644 --- a/lib/puppet/pops/types/p_sensitive_type.rb +++ b/lib/puppet/pops/types/p_sensitive_type.rb @@ -42,7 +42,7 @@ def self.register_ptype(loader, ir) end def initialize(type = nil) - @type = type.nil? ? PAnyType.new : type.generalize + super(type.nil? ? PAnyType.new : type.generalize) end def instance?(o, guard = nil) diff --git a/lib/puppet/pops/types/p_timespan_type.rb b/lib/puppet/pops/types/p_timespan_type.rb index 08820187f11..d6aa6046044 100644 --- a/lib/puppet/pops/types/p_timespan_type.rb +++ b/lib/puppet/pops/types/p_timespan_type.rb @@ -5,6 +5,7 @@ class PAbstractTimeDataType < PScalarType # @param from [AbstractTime] lower bound for this type. Nil or :default means unbounded # @param to [AbstractTime] upper bound for this type. Nil or :default means unbounded def initialize(from, to = nil) + super() @from = convert_arg(from, true) @to = convert_arg(to, false) raise ArgumentError, "'from' must be less or equal to 'to'. Got (#{@from}, #{@to}" unless @from <= @to diff --git a/lib/puppet/pops/types/p_type_set_type.rb b/lib/puppet/pops/types/p_type_set_type.rb index 78eea119d86..5a8f502475b 100644 --- a/lib/puppet/pops/types/p_type_set_type.rb +++ b/lib/puppet/pops/types/p_type_set_type.rb @@ -89,6 +89,7 @@ def self.register_ptype(loader, ir) # # @api private def initialize(name_or_init_hash, init_hash_expression = nil, name_authority = nil) + super() @types = EMPTY_HASH @references = EMPTY_HASH diff --git a/lib/puppet/pops/types/p_uri_type.rb b/lib/puppet/pops/types/p_uri_type.rb index 92483bc35b3..ea999667f51 100644 --- a/lib/puppet/pops/types/p_uri_type.rb +++ b/lib/puppet/pops/types/p_uri_type.rb @@ -100,6 +100,7 @@ def from_hash(init_hash) attr_reader :parameters def initialize(parameters = nil) + super() if parameters.is_a?(String) parameters = TypeAsserter.assert_instance_of('URI-Type parameter', Pcore::TYPE_URI, parameters, true) @parameters = uri_to_hash(URI.parse(parameters)) diff --git a/lib/puppet/pops/types/ruby_method.rb b/lib/puppet/pops/types/ruby_method.rb index 7f2e1e32dd9..cf7e04fa32b 100644 --- a/lib/puppet/pops/types/ruby_method.rb +++ b/lib/puppet/pops/types/ruby_method.rb @@ -24,6 +24,7 @@ def self.from_asserted_hash(init_hash) attr_reader :body, :parameters def initialize(body, parameters = nil) + super() @body = body @parameters = parameters end diff --git a/lib/puppet/pops/types/types.rb b/lib/puppet/pops/types/types.rb index daefea17b3e..94cee8c20a3 100644 --- a/lib/puppet/pops/types/types.rb +++ b/lib/puppet/pops/types/types.rb @@ -419,6 +419,7 @@ def self.register_ptype(loader, ir) attr_reader :type def initialize(type) + super() @type = type end @@ -766,6 +767,7 @@ def self.register_ptype(loader, ir) attr_reader :values, :case_insensitive def initialize(values, case_insensitive = false) + super() @values = values.uniq.sort.freeze @case_insensitive = case_insensitive end @@ -937,6 +939,7 @@ def on_error(from, abs = false) end def initialize(from, to = Float::INFINITY) + super() from = -Float::INFINITY if from.nil? || from == :default to = Float::INFINITY if to.nil? || to == :default raise ArgumentError, "'from' must be less or equal to 'to'. Got (#{from}, #{to}" if from > to @@ -1320,6 +1323,7 @@ def self.register_ptype(loader, ir) attr_reader :size_type def initialize(size_type) + super() @size_type = size_type.nil? ? nil : size_type.to_size end @@ -1509,6 +1513,7 @@ def self.register_ptype(loader, ir) attr_reader :size_type_or_value def initialize(size_type_or_value, deprecated_multi_args = EMPTY_ARRAY) + super() unless deprecated_multi_args.empty? if Puppet[:strict] != :off #TRANSLATORS 'PStringType#initialize' is a class and method name and should not be translated @@ -1730,6 +1735,7 @@ def self.append_flags_group(rx_string, options) end def initialize(pattern) + super() if pattern.is_a?(Regexp) @regexp = pattern @pattern = PRegexpType.regexp_to_s(pattern) @@ -1778,6 +1784,7 @@ def self.register_ptype(loader, ir) attr_reader :patterns def initialize(patterns) + super() @patterns = patterns.freeze end @@ -1848,6 +1855,7 @@ def self.register_ptype(loader, ir) attr_reader :value def initialize(value = nil) + super() @value = value end @@ -1942,6 +1950,7 @@ def name end def initialize(key_type, value_type) + super() @key_type = key_type @value_type = value_type end @@ -1993,6 +2002,7 @@ def self.register_ptype(loader, ir) end def initialize(elements) + super() @elements = elements.freeze end @@ -2200,6 +2210,7 @@ def callable_args?(callable_t, guard) end def initialize(types, size_type = nil) + super() @types = types @size_type = size_type.nil? ? nil : size_type.to_size end @@ -2375,6 +2386,7 @@ def self.register_ptype(loader, ir) # @param block_type [PAnyType] # @param return_type [PAnyType] def initialize(param_types, block_type = nil, return_type = nil) + super() @param_types = param_types @block_type = block_type @return_type = return_type == PAnyType::DEFAULT ? nil : return_type @@ -2902,6 +2914,7 @@ def self.maybe_create(types) # @param types [Array[PAnyType]] the variants def initialize(types) + super() @types = types.freeze end @@ -3164,6 +3177,7 @@ def self.register_ptype(loader, ir) end def initialize(class_name) + super() @class_name = class_name end @@ -3213,6 +3227,7 @@ def self.register_ptype(loader, ir) attr_reader :type_name, :title, :downcased_name def initialize(type_name, title = nil) + super() @type_name = type_name.freeze @title = title.freeze @downcased_name = type_name.nil? ? nil : @type_name.downcase.freeze @@ -3309,6 +3324,7 @@ def self.register_ptype(loader, ir) attr_reader :type_string def initialize(type_string) + super() @type_string = type_string end @@ -3368,6 +3384,7 @@ def self.register_ptype(loader, ir) # @param type_expr [Model::PopsObject] The expression that describes the aliased type # @param resolved_type [PAnyType] the resolve type (only used for the DEFAULT initialization) def initialize(name, type_expr, resolved_type = nil) + super() @name = name @type_expr = type_expr @resolved_type = resolved_type diff --git a/lib/puppet/property.rb b/lib/puppet/property.rb index 31833dd0625..b7514e2e7f1 100644 --- a/lib/puppet/property.rb +++ b/lib/puppet/property.rb @@ -282,6 +282,8 @@ def safe_insync?(is) # @api private # def self.method_added(sym) + super(sym) + raise "Puppet::Property#safe_insync? shouldn't be overridden; please override insync? instead" if sym == :safe_insync? end diff --git a/lib/puppet/property/ensure.rb b/lib/puppet/property/ensure.rb index ca7f8b53035..1c934a5f3be 100644 --- a/lib/puppet/property/ensure.rb +++ b/lib/puppet/property/ensure.rb @@ -43,6 +43,8 @@ def self.defaultvalues end def self.inherited(sub) + super(sub) + # Add in the two properties that everyone will have. sub.class_eval do end diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 1e00a1ef193..01a31188c54 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -1467,6 +1467,7 @@ class << self @subclasses = [] def self.inherited(sub) + super(sub) @subclasses << sub end diff --git a/lib/puppet/util/package/version/debian.rb b/lib/puppet/util/package/version/debian.rb index 3f7c4a2542d..7c5c1d2411f 100644 --- a/lib/puppet/util/package/version/debian.rb +++ b/lib/puppet/util/package/version/debian.rb @@ -57,7 +57,7 @@ def <=>(other) private - def initialize(epoch, upstream_version, debian_revision) + def initialize(epoch, upstream_version, debian_revision) # rubocop:disable Lint/MissingSuper @epoch = epoch @upstream_version = upstream_version @debian_revision = debian_revision diff --git a/lib/puppet/util/package/version/rpm.rb b/lib/puppet/util/package/version/rpm.rb index ad5c15681b8..914226b130f 100644 --- a/lib/puppet/util/package/version/rpm.rb +++ b/lib/puppet/util/package/version/rpm.rb @@ -63,7 +63,7 @@ def rpm_compareEVR(a, b) super(a, b) end - def initialize(epoch, version, release, arch) + def initialize(epoch, version, release, arch) # rubocop:disable Lint/MissingSuper @epoch = epoch @version = version @release = release diff --git a/lib/puppet/util/rdoc/generators/puppet_generator.rb b/lib/puppet/util/rdoc/generators/puppet_generator.rb index 71b1bda30fe..07daa347f5c 100644 --- a/lib/puppet/util/rdoc/generators/puppet_generator.rb +++ b/lib/puppet/util/rdoc/generators/puppet_generator.rb @@ -65,6 +65,7 @@ def PuppetGenerator.for(options) end def initialize(options) #:not-new: + super() @options = options load_html_template end diff --git a/spec/unit/pops/loaders/loaders_spec.rb b/spec/unit/pops/loaders/loaders_spec.rb index 7f159641841..4f89e217ea6 100644 --- a/spec/unit/pops/loaders/loaders_spec.rb +++ b/spec/unit/pops/loaders/loaders_spec.rb @@ -156,7 +156,7 @@ def expect_loader_hierarchy(loaders, expected_loaders) expect_loader_hierarchy( Puppet::Pops::Loaders.new(empty_test_env), [ - [nil, Puppet::Pops::Loader::StaticLoader], + ['static', Puppet::Pops::Loader::StaticLoader], ['puppet_system', Puppet::Pops::Loader::ModuleLoaders::LibRootedFileBased], [empty_test_env.name, Puppet::Pops::Loader::Runtime3TypeLoader], ['environment', Puppet::Pops::Loader::SimpleEnvironmentLoader], @@ -171,7 +171,7 @@ def expect_loader_hierarchy(loaders, expected_loaders) expect_loader_hierarchy( Puppet::Pops::Loaders.new(empty_test_env), [ - [nil, Puppet::Pops::Loader::StaticLoader], + ['static', Puppet::Pops::Loader::StaticLoader], ['puppet_system', Puppet::Pops::Loader::ModuleLoaders::LibRootedFileBased], ['environment', Puppet::Pops::Loader::ModuleLoaders::EmptyLoader], ['environment private', Puppet::Pops::Loader::DependencyLoader], @@ -183,7 +183,7 @@ def expect_loader_hierarchy(loaders, expected_loaders) expect_loader_hierarchy( Puppet::Pops::Loaders.new(empty_test_env, true), [ - [nil, Puppet::Pops::Loader::StaticLoader], + ['static', Puppet::Pops::Loader::StaticLoader], ['puppet_system', Puppet::Pops::Loader::ModuleLoaders::LibRootedFileBased], ['cached_puppet_lib', Puppet::Pops::Loader::ModuleLoaders::LibRootedFileBased], [empty_test_env.name, Puppet::Pops::Loader::Runtime3TypeLoader], From 3b981fe98f8ae36acfef33828acd7143a32f501c Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Mon, 31 Jul 2023 21:31:11 -0700 Subject: [PATCH 4/8] Lint/ToJSON (NEEDS WORK) Calling `JSON.generate(obj, {})` on an object will have its `to_json` method called and the options has will be passed as an argument. If the object doesn't accept the argument, then it will result in: ArgumentError (wrong number of arguments (given 1, expected 0)) --- .rubocop_todo.yml | 7 ------- lib/puppet/module_tool/metadata.rb | 2 +- lib/puppet/network/http/error.rb | 4 ++-- lib/puppet/pops/serialization/json.rb | 4 ++-- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 08bf5226930..ffd791f0895 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -623,13 +623,6 @@ Lint/SuppressedException: - 'lib/puppet/util/execution.rb' - 'util/rspec_grouper' -# This cop supports safe auto-correction (--auto-correct). -Lint/ToJSON: - Exclude: - - 'lib/puppet/module_tool/metadata.rb' - - 'lib/puppet/network/http/error.rb' - - 'lib/puppet/pops/serialization/json.rb' - # This cop supports safe auto-correction (--auto-correct). # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. Lint/UnusedMethodArgument: diff --git a/lib/puppet/module_tool/metadata.rb b/lib/puppet/module_tool/metadata.rb index 64752a2c6bf..e8c58275fb3 100644 --- a/lib/puppet/module_tool/metadata.rb +++ b/lib/puppet/module_tool/metadata.rb @@ -97,7 +97,7 @@ def to_hash end alias :to_data_hash :to_hash - def to_json + def to_json(*_args) data = @data.dup.merge('dependencies' => dependencies) contents = data.keys.map do |k| diff --git a/lib/puppet/network/http/error.rb b/lib/puppet/network/http/error.rb index 90d4154d1fd..f0136efec14 100644 --- a/lib/puppet/network/http/error.rb +++ b/lib/puppet/network/http/error.rb @@ -13,7 +13,7 @@ def initialize(message, status, issue_kind) @issue_kind = issue_kind end - def to_json + def to_json(*_args) Puppet::Util::Json.dump({:message => message, :issue_kind => @issue_kind}) end end @@ -67,7 +67,7 @@ def initialize(original_error, issue_kind = Issues::RUNTIME_ERROR) super(_("Server Error: %{message}") % { message: original_error.message }, CODE, issue_kind) end - def to_json + def to_json(*_args) Puppet::Util::Json.dump({:message => message, :issue_kind => @issue_kind}) end end diff --git a/lib/puppet/pops/serialization/json.rb b/lib/puppet/pops/serialization/json.rb index 42f3a9c650e..676083de89b 100644 --- a/lib/puppet/pops/serialization/json.rb +++ b/lib/puppet/pops/serialization/json.rb @@ -39,7 +39,7 @@ def to_a @packer.to_a end - def to_json + def to_json(*_args) @packer.to_json end end @@ -150,7 +150,7 @@ def to_a ::Puppet::Util::Json.load(io_string) end - def to_json + def to_json(*_args) if @indent > 0 ::Puppet::Util::Json.dump(to_a, { :pretty => true, :indent => ' ' * @indent }) else From b9b9076836f42c1d409bdb0f56bbd62bfacf3564 Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Mon, 4 Dec 2023 17:26:26 -0800 Subject: [PATCH 5/8] Lint/UnusedMethodArgument This cop flags methods where `&block` is passed to a method, which is a very common practice. There's also debate[1] as to whether specifying `&block` explicitly is better than implicitly accepting a block. [1] https://github.com/rubocop/rubocop-performance/issues/385 --- .rubocop.yml | 4 ++++ .rubocop_todo.yml | 5 ----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index d5c57cf5150..c54549c28f2 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -28,6 +28,10 @@ Lint/BooleanSymbol: - 'lib/puppet/reference/providers.rb' - 'lib/puppet/parameter/value.rb' +# This breaks the ruby convention of passing &block and using block_given? +Lint/UnusedMethodArgument: + Enabled: false + Metrics/AbcSize: Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index ffd791f0895..6a96d6ad4e0 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -623,11 +623,6 @@ Lint/SuppressedException: - 'lib/puppet/util/execution.rb' - 'util/rspec_grouper' -# This cop supports safe auto-correction (--auto-correct). -# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. -Lint/UnusedMethodArgument: - Enabled: false - Naming/AccessorMethodName: Enabled: false From db6c72932965cace3c2b2c53d67dcc98d8a0b7da Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Mon, 4 Dec 2023 17:43:22 -0800 Subject: [PATCH 6/8] Lint/SuppressedException StopIteration is used for flow control. Ignore scripts in util directory. Rescuing LoadError for CreateSymbolicLinkW is left over from 2003, which is long since EOL. If we get Errno::EAGAIN, then use `retry` to make it explicit. --- .rubocop.yml | 1 + .rubocop_todo.yml | 17 ----------------- lib/puppet/application/face_base.rb | 1 + lib/puppet/ffi/windows/functions.rb | 1 - lib/puppet/forge/errors.rb | 1 + lib/puppet/functions/each.rb | 8 ++++---- lib/puppet/functions/filter.rb | 4 ++-- lib/puppet/functions/map.rb | 8 ++++---- lib/puppet/functions/slice.rb | 4 ++-- lib/puppet/pops/time/timespan.rb | 1 + lib/puppet/pops/types/iterable.rb | 4 ++-- lib/puppet/pops/types/p_runtime_type.rb | 1 + lib/puppet/util/command_line.rb | 2 +- lib/puppet/util/execution.rb | 3 +++ 14 files changed, 23 insertions(+), 33 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index c54549c28f2..0ed151d9216 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -16,6 +16,7 @@ AllCops: - 'ext/suse/puppet.spec' - 'lib/puppet/vendor/**/*' - 'lib/puppet/pops/parser/eparser.rb' + - 'util/**/*' # puppet uses symbol booleans in types and providers to work around long standing # bugs when trying to manage falsey pararameters and properties diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 6a96d6ad4e0..12fcc055456 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -606,23 +606,6 @@ Lint/RescueException: - 'lib/puppet/util/command_line/trollop.rb' - 'util/rspec_grouper' -# Configuration parameters: AllowComments, AllowNil. -Lint/SuppressedException: - Exclude: - - 'lib/puppet/application/face_base.rb' - - 'lib/puppet/ffi/windows/functions.rb' - - 'lib/puppet/forge/errors.rb' - - 'lib/puppet/functions/each.rb' - - 'lib/puppet/functions/filter.rb' - - 'lib/puppet/functions/map.rb' - - 'lib/puppet/functions/slice.rb' - - 'lib/puppet/pops/time/timespan.rb' - - 'lib/puppet/pops/types/iterable.rb' - - 'lib/puppet/pops/types/p_runtime_type.rb' - - 'lib/puppet/util/command_line.rb' - - 'lib/puppet/util/execution.rb' - - 'util/rspec_grouper' - Naming/AccessorMethodName: Enabled: false diff --git a/lib/puppet/application/face_base.rb b/lib/puppet/application/face_base.rb index 07ae18e6366..899f7a6be06 100644 --- a/lib/puppet/application/face_base.rb +++ b/lib/puppet/application/face_base.rb @@ -130,6 +130,7 @@ def parse_options begin super rescue OptionParser::InvalidOption + # fall through end face = @face.name diff --git a/lib/puppet/ffi/windows/functions.rb b/lib/puppet/ffi/windows/functions.rb index 87d9e09e40f..6ec1d2ecd66 100644 --- a/lib/puppet/ffi/windows/functions.rb +++ b/lib/puppet/ffi/windows/functions.rb @@ -477,7 +477,6 @@ module Functions ffi_lib :kernel32 attach_function_private :CreateSymbolicLinkW, [:lpwstr, :lpwstr, :dword], :boolean - rescue LoadError end # https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getcurrentdirectory diff --git a/lib/puppet/forge/errors.rb b/lib/puppet/forge/errors.rb index d0b000338a4..6c60f86a03e 100644 --- a/lib/puppet/forge/errors.rb +++ b/lib/puppet/forge/errors.rb @@ -88,6 +88,7 @@ def initialize(options) @message ||= body['message'].strip end rescue Puppet::Util::Json::ParseError + # fall through end message = if @message diff --git a/lib/puppet/functions/each.rb b/lib/puppet/functions/each.rb index 2f42fdde9e1..678f765bce1 100644 --- a/lib/puppet/functions/each.rb +++ b/lib/puppet/functions/each.rb @@ -121,7 +121,7 @@ def foreach_Hash_1(hash) hash.each_pair do |pair| yield(pair) end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end # produces the receiver hash @@ -132,7 +132,7 @@ def foreach_Hash_2(hash) hash.each_pair do |pair| yield(*pair) end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end # produces the receiver hash @@ -144,7 +144,7 @@ def foreach_Enumerable_1(enumerable) enum.each do |value| yield value end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end # produces the receiver enumerable @@ -159,7 +159,7 @@ def foreach_Enumerable_2(enumerable) enum.each_with_index do |value, index| yield(index, value) end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end end # produces the receiver diff --git a/lib/puppet/functions/filter.rb b/lib/puppet/functions/filter.rb index 33170afa141..db786884d8a 100644 --- a/lib/puppet/functions/filter.rb +++ b/lib/puppet/functions/filter.rb @@ -113,7 +113,7 @@ def filter_Enumerable_1(enumerable) enum.each do |value| result << value if yield(value) end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end result end @@ -130,7 +130,7 @@ def filter_Enumerable_2(enumerable) enum.each_with_index do |value, index| result << value if yield(index, value) end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end result end diff --git a/lib/puppet/functions/map.rb b/lib/puppet/functions/map.rb index c34aaf61b5f..7704e4eab49 100644 --- a/lib/puppet/functions/map.rb +++ b/lib/puppet/functions/map.rb @@ -92,7 +92,7 @@ def map_Hash_1(hash) result = [] begin hash.each {|x, y| result << yield([x, y]) } - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end result end @@ -101,7 +101,7 @@ def map_Hash_2(hash) result = [] begin hash.each {|x, y| result << yield(x, y) } - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end result end @@ -113,7 +113,7 @@ def map_Enumerable_1(enumerable) enum.each do |val| result << yield(val) end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end result end @@ -128,7 +128,7 @@ def map_Enumerable_2(enumerable) enum.each_with_index do |val, index| result << yield(index, val) end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end result end diff --git a/lib/puppet/functions/slice.rb b/lib/puppet/functions/slice.rb index f0b6a779e85..76bd7d4de8f 100644 --- a/lib/puppet/functions/slice.rb +++ b/lib/puppet/functions/slice.rb @@ -85,7 +85,7 @@ def slice_Common(o, slice_size, filler, pblock) result << enumerator.next end end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end else begin @@ -96,7 +96,7 @@ def slice_Common(o, slice_size, filler, pblock) end pblock.call(*a) end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end end if pblock diff --git a/lib/puppet/pops/time/timespan.rb b/lib/puppet/pops/time/timespan.rb index e3c6f40d42e..f138be35ab3 100644 --- a/lib/puppet/pops/time/timespan.rb +++ b/lib/puppet/pops/time/timespan.rb @@ -111,6 +111,7 @@ def self.parse(str, format = Format::DEFAULTS) begin return fmt.parse(str) rescue ArgumentError + # fall through end end raise ArgumentError, _("Unable to parse '%{str}' using any of the formats %{formats}") % { str: str, formats: format.join(', ') } diff --git a/lib/puppet/pops/types/iterable.rb b/lib/puppet/pops/types/iterable.rb index 7997e564719..9d498d3156b 100644 --- a/lib/puppet/pops/types/iterable.rb +++ b/lib/puppet/pops/types/iterable.rb @@ -241,7 +241,7 @@ def step(step, &block) else loop { yield(*r.next) } end - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end self else @@ -292,7 +292,7 @@ def next if skip > 0 begin skip.times { @enumeration.next } - rescue StopIteration + rescue StopIteration # rubocop:disable Lint/SuppressedException end end result diff --git a/lib/puppet/pops/types/p_runtime_type.rb b/lib/puppet/pops/types/p_runtime_type.rb index d848426b367..3718b482ab3 100644 --- a/lib/puppet/pops/types/p_runtime_type.rb +++ b/lib/puppet/pops/types/p_runtime_type.rb @@ -53,6 +53,7 @@ def iterable?(guard = nil) c = ClassLoader.provide(self) return c < Iterable unless c.nil? rescue ArgumentError + # fall through end end false diff --git a/lib/puppet/util/command_line.rb b/lib/puppet/util/command_line.rb index 0f23e98e62a..d63239d7bf3 100644 --- a/lib/puppet/util/command_line.rb +++ b/lib/puppet/util/command_line.rb @@ -6,7 +6,7 @@ if not defined? ::Bundler begin require 'rubygems' - rescue LoadError + rescue LoadError # rubocop:disable Lint/SuppressedException end end diff --git a/lib/puppet/util/execution.rb b/lib/puppet/util/execution.rb index aad07a333bf..16c49cde021 100644 --- a/lib/puppet/util/execution.rb +++ b/lib/puppet/util/execution.rb @@ -239,6 +239,7 @@ def self.execute(command, options = NoOptionsSpecified) begin output << reader.read_nonblock(4096) if ready rescue Errno::EAGAIN + retry rescue EOFError wait_flags = 0 end @@ -250,7 +251,9 @@ def self.execute(command, options = NoOptionsSpecified) output << reader.read_nonblock(4096) end rescue Errno::EAGAIN + retry rescue EOFError + # done reading, continue end # Force to external encoding to preserve prior behavior when reading a file. From 0ca2680015efa1afc11ddeca8cc4684cd054596a Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Tue, 5 Dec 2023 15:38:33 -0800 Subject: [PATCH 7/8] Lint/RescueException Rescuing Exception is generally not recommended, because it will also rescue SystemExit and SystemStackError (and more), preventing an application from gracefully exiting. Rescuing Exception is sometimes needed when calling 3rd party code, because that code might raise an exception that doesn't inherit from StandardError. For example, autoloading a provider might raise a LoadError if the provider relies on a missing gem. Since LoadError extends ScriptError which extends Exception, it is not caught when doing `rescue => e` since that only rescues StandardErrors. In cases where we rescue Exception and immediately re-raise, then ignore the cop, since a SystemExit will cause us to exit. If we rescue the Exception, but try to continue along, then first rescue SystemExit and re-raise that. The Windows daemon code is fragile, so just ignore the cop there. --- .rubocop_todo.yml | 12 ------------ ext/windows/service/daemon.rb | 10 +++++----- lib/puppet/configurer/fact_handler.rb | 2 +- lib/puppet/generate/type.rb | 14 ++++++++++---- lib/puppet/settings.rb | 4 +++- lib/puppet/transaction/resource_harness.rb | 2 +- lib/puppet/util.rb | 2 +- lib/puppet/util/autoload.rb | 2 +- lib/puppet/util/command_line/trollop.rb | 4 +++- 9 files changed, 25 insertions(+), 27 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 12fcc055456..09ce5e0ea54 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -594,18 +594,6 @@ Lint/NestedMethodDefinition: - 'lib/puppet/pops/types/types.rb' - 'lib/puppet/type.rb' -Lint/RescueException: - Exclude: - - 'ext/windows/service/daemon.rb' - - 'lib/puppet/configurer/fact_handler.rb' - - 'lib/puppet/generate/type.rb' - - 'lib/puppet/settings.rb' - - 'lib/puppet/transaction/resource_harness.rb' - - 'lib/puppet/util.rb' - - 'lib/puppet/util/autoload.rb' - - 'lib/puppet/util/command_line/trollop.rb' - - 'util/rspec_grouper' - Naming/AccessorMethodName: Enabled: false diff --git a/ext/windows/service/daemon.rb b/ext/windows/service/daemon.rb index 9dab31542bd..ec5b2f05f2f 100755 --- a/ext/windows/service/daemon.rb +++ b/ext/windows/service/daemon.rb @@ -91,13 +91,13 @@ def service_main(*argsv) sleep(runinterval) service.log_debug('Service worker thread woken up') end - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException service.log_exception(e) end end @run_thread.join - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException log_exception(e) ensure log_notice('Service stopped') @@ -151,7 +151,7 @@ def report_windows_event(type,id,message) :event_id => id, # 0x01 or 0x02, 0x03 etc. :data => message # "the message" ) - rescue Exception + rescue Exception # rubocop:disable Lint/RescueException # Ignore all errors ensure if (!eventlog.nil?) @@ -167,7 +167,7 @@ def parse_runinterval(puppet_path) runinterval = 1800 log_err("Failed to determine runinterval, defaulting to #{runinterval} seconds") end - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException log_exception(e) runinterval = 1800 end @@ -182,7 +182,7 @@ def parse_log_level(puppet_path,cmdline_debug) loglevel = :notice log_err("Failed to determine loglevel, defaulting to #{loglevel}") end - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException log_exception(e) loglevel = :notice end diff --git a/lib/puppet/configurer/fact_handler.rb b/lib/puppet/configurer/fact_handler.rb index a07a060301e..576bb2d3483 100644 --- a/lib/puppet/configurer/fact_handler.rb +++ b/lib/puppet/configurer/fact_handler.rb @@ -21,7 +21,7 @@ def find_facts facts rescue SystemExit,NoMemoryError raise - rescue Exception => detail + rescue Exception => detail # rubocop:disable Lint/RescueException message = _("Could not retrieve local facts: %{detail}") % { detail: detail } Puppet.log_exception(detail, message) raise Puppet::Error, message, detail.backtrace diff --git a/lib/puppet/generate/type.rb b/lib/puppet/generate/type.rb index 86f91e8f527..4ec68f1792c 100644 --- a/lib/puppet/generate/type.rb +++ b/lib/puppet/generate/type.rb @@ -191,7 +191,7 @@ def self.generate(inputs, outputdir = nil, force = false) require input.path rescue SystemExit raise - rescue Exception => e + rescue Exception => e # rubocop:disable Lint/RescueException # Log the exception and move on to the next input @bad_input = true Puppet.log_exception(e, _("Failed to load custom type '%{type_name}' from '%{input}': %{message}") % { type_name: type_name, input: input, message: e.message }) @@ -211,7 +211,9 @@ def self.generate(inputs, outputdir = nil, force = false) # Create the model begin model = Models::Type::Type.new(type) - rescue Exception => e + rescue SystemExit + raise + rescue Exception => e # rubocop:disable Lint/RescueException @bad_input = true # Move on to the next input Puppet.log_exception(e, "#{input}: #{e.message}") @@ -221,7 +223,9 @@ def self.generate(inputs, outputdir = nil, force = false) # Render the template begin result = model.render(templates[input.template_path]) - rescue Exception => e + rescue SystemExit + raise + rescue Exception => e # rubocop:disable Lint/RescueException @bad_input = true Puppet.log_exception(e) raise @@ -235,7 +239,9 @@ def self.generate(inputs, outputdir = nil, force = false) Puppet::FileSystem.open(effective_output_path, nil, 'w:UTF-8') do |file| file.write(result) end - rescue Exception => e + rescue SystemExit + raise + rescue Exception => e # rubocop:disable Lint/RescueException @bad_input = true Puppet.log_exception(e, _("Failed to generate '%{effective_output_path}': %{message}") % { effective_output_path: effective_output_path, message: e.message }) # Move on to the next input diff --git a/lib/puppet/settings.rb b/lib/puppet/settings.rb index da6eeab39ea..a16820f0347 100644 --- a/lib/puppet/settings.rb +++ b/lib/puppet/settings.rb @@ -1570,7 +1570,9 @@ def set(name, value) if default.has_hook? default.handle(value) end - rescue Exception => e + rescue SystemExit + raise + rescue Exception => e # rubocop:disable Lint/RescueException @values[name] = old_value raise e end diff --git a/lib/puppet/transaction/resource_harness.rb b/lib/puppet/transaction/resource_harness.rb index 00f861a4ccc..e04433ba347 100644 --- a/lib/puppet/transaction/resource_harness.rb +++ b/lib/puppet/transaction/resource_harness.rb @@ -151,7 +151,7 @@ def sync_if_needed(param, context) param.is_to_s(current_value), param.should_to_s(param.should)) + detail.to_s event - rescue Exception => detail + rescue Exception => detail # rubocop:disable Lint/RescueException # Execution will halt on Exceptions, they get raised to the application event = create_change_event(param, current_value, historical_value) event.status = "failure" diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb index e709949948a..de7458b3dda 100644 --- a/lib/puppet/util.rb +++ b/lib/puppet/util.rb @@ -705,7 +705,7 @@ def exit_on_fail(message, code = 1) # Now we need to catch *any* other kind of exception, because we may be calling third-party # code (e.g. webrick), and we have no idea what they might throw. - rescue Exception => err + rescue Exception => err # rubocop:disable Lint/RescueException ## NOTE: when debugging spec failures, these two lines can be very useful #puts err.inspect #puts Puppet::Util.pretty_backtrace(err.backtrace) diff --git a/lib/puppet/util/autoload.rb b/lib/puppet/util/autoload.rb index edb430bc3e9..4faa6e28598 100644 --- a/lib/puppet/util/autoload.rb +++ b/lib/puppet/util/autoload.rb @@ -80,7 +80,7 @@ def load_file(name, env) return true rescue SystemExit,NoMemoryError raise - rescue Exception => detail + rescue Exception => detail # rubocop:disable Lint/RescueException message = _("Could not autoload %{name}: %{detail}") % { name: name, detail: detail } Puppet.log_exception(detail, message) raise Puppet::Error, message, detail.backtrace diff --git a/lib/puppet/util/command_line/trollop.rb b/lib/puppet/util/command_line/trollop.rb index b0602003793..a255a2d85a1 100644 --- a/lib/puppet/util/command_line/trollop.rb +++ b/lib/puppet/util/command_line/trollop.rb @@ -533,7 +533,9 @@ def width #:nodoc: x = Curses::cols Curses::close_screen x - rescue Exception + rescue SystemExit + raise + rescue Exception # rubocop:disable Lint/RescueException 80 end else From 0cd3012c5fc9d600385b8ed4d76aaef4dd7b5b2e Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Tue, 5 Dec 2023 16:41:16 -0800 Subject: [PATCH 8/8] Lint/NestedMethodDefinition --- .rubocop.yml | 21 +++++++++++++++++++++ .rubocop_todo.yml | 14 -------------- lib/puppet/type.rb | 2 +- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 0ed151d9216..2f8e08198ec 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -33,6 +33,27 @@ Lint/BooleanSymbol: Lint/UnusedMethodArgument: Enabled: false +# Nested methods are bad because the nested method is defined in the outer scope +# and the nested method is redefined each time the outer method is called. +# However, `Puppet::Functions.create_loaded_function` calls `class_eval` to +# evaluate the function and that avoids the first issue. Secondly, the type +# system always memoizes the result, so the nested method is only called once. +Lint/NestedMethodDefinition: + Enabled: true + Exclude: + - 'lib/puppet/pops/types/p_binary_type.rb' + - 'lib/puppet/pops/types/p_init_type.rb' + - 'lib/puppet/pops/types/p_object_type.rb' + - 'lib/puppet/pops/types/p_sem_ver_range_type.rb' + - 'lib/puppet/pops/types/p_sem_ver_type.rb' + - 'lib/puppet/pops/types/p_sensitive_type.rb' + - 'lib/puppet/pops/types/p_timespan_type.rb' + - 'lib/puppet/pops/types/p_timestamp_type.rb' + - 'lib/puppet/pops/types/p_uri_type.rb' + - 'lib/puppet/pops/types/types.rb' + # AllowedMethods: this requires rubocop 1.37.0 + # - 'create_loaded_function' + Metrics/AbcSize: Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 09ce5e0ea54..5787367f75f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -580,20 +580,6 @@ Layout/TrailingEmptyLines: Layout/TrailingWhitespace: Enabled: false -Lint/NestedMethodDefinition: - Exclude: - - 'lib/puppet/pops/types/p_binary_type.rb' - - 'lib/puppet/pops/types/p_init_type.rb' - - 'lib/puppet/pops/types/p_object_type.rb' - - 'lib/puppet/pops/types/p_sem_ver_range_type.rb' - - 'lib/puppet/pops/types/p_sem_ver_type.rb' - - 'lib/puppet/pops/types/p_sensitive_type.rb' - - 'lib/puppet/pops/types/p_timespan_type.rb' - - 'lib/puppet/pops/types/p_timestamp_type.rb' - - 'lib/puppet/pops/types/p_uri_type.rb' - - 'lib/puppet/pops/types/types.rb' - - 'lib/puppet/type.rb' - Naming/AccessorMethodName: Enabled: false diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 01a31188c54..f2b6ee4cdf5 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -1855,7 +1855,7 @@ class << self # Provides the ability to add documentation to a provider. # - def self.doc + def self.doc # rubocop:disable Lint/NestedMethodDefinition # Since we're mixing @doc with text from other sources, we must normalize # its indentation with scrub. But we don't need to manually scrub the # provider's doc string, since markdown_definitionlist sanitizes its inputs.