diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9981a989..92293f1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,8 +13,8 @@ jobs: fail-fast: false matrix: ruby_version: - - '2.5' - '2.7' + - '3.2' name: "spec (ruby ${{ matrix.ruby_version }})" uses: "puppetlabs/cat-github-actions/.github/workflows/gem_ci.yml@main" secrets: "inherit" @@ -26,8 +26,8 @@ jobs: fail-fast: false matrix: ruby_version: - - '2.5' - '2.7' + - '3.2' name: "acceptance (ruby ${{ matrix.ruby_version }})" needs: "spec" uses: "puppetlabs/cat-github-actions/.github/workflows/gem_acceptance.yml@main" diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 3674ba43..75df5b7b 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -12,8 +12,8 @@ jobs: fail-fast: false matrix: ruby_version: - - '2.5' - '2.7' + - '3.2' name: "spec (ruby ${{ matrix.ruby_version }})" uses: "puppetlabs/cat-github-actions/.github/workflows/gem_ci.yml@main" secrets: "inherit" @@ -25,8 +25,8 @@ jobs: fail-fast: false matrix: ruby_version: - - '2.5' - '2.7' + - '3.2' name: "acceptance (ruby ${{ matrix.ruby_version }})" needs: "spec" uses: "puppetlabs/cat-github-actions/.github/workflows/gem_acceptance.yml@main" diff --git a/.rubocop.yml b/.rubocop.yml index 903a5414..a52a34e8 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1 +1,3 @@ -inherit_from: rubocop_baseline.yml +inherit_from: + - rubocop_baseline.yml + - .rubocop_todo.yml diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000..f2348889 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,161 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2023-04-04 08:44:46 UTC using RuboCop version 1.48.1. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Severity, Include. +# Include: **/*.gemspec +Gemspec/RequireMFA: + Exclude: + - 'puppet-lint.gemspec' + +# Offense count: 4 +# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches. +Lint/DuplicateBranch: + Exclude: + - 'lib/puppet-lint/lexer/string_slurper.rb' + - 'lib/puppet-lint/lexer/token.rb' + +# Offense count: 9 +# Configuration parameters: MaximumRangeSize. +Lint/MissingCopEnableDirective: + Exclude: + - 'lib/puppet-lint.rb' + - 'lib/puppet-lint/lexer.rb' + - 'lib/puppet-lint/lexer/string_slurper.rb' + - 'lib/puppet-lint/lexer/token.rb' + - 'lib/puppet-lint/report/codeclimate.rb' + - 'lib/puppet-lint/report/github.rb' + - 'lib/puppet-lint/tasks/puppet-lint.rb' + - 'spec/unit/puppet-lint/puppet-lint_spec.rb' + +# Offense count: 58 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 142 + +# Offense count: 34 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode. +# AllowedMethods: refine +Metrics/BlockLength: + Max: 104 + +# Offense count: 2 +# Configuration parameters: CountBlocks. +Metrics/BlockNesting: + Max: 5 + +# Offense count: 7 +# Configuration parameters: CountComments, CountAsOne. +Metrics/ClassLength: + Max: 387 + +# Offense count: 33 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/CyclomaticComplexity: + Max: 33 + +# Offense count: 80 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +Metrics/MethodLength: + Max: 108 + +# Offense count: 26 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/PerceivedComplexity: + Max: 31 + +# Offense count: 182 +# Configuration parameters: ForbiddenDelimiters. +# ForbiddenDelimiters: (?i-mx:(^|\s)(EO[A-Z]{1}|END)(\s|$)) +Naming/HeredocDelimiterNaming: + Enabled: false + +# Offense count: 2 +# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. +# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to +Naming/MethodParameterName: + Exclude: + - 'lib/puppet-lint/monkeypatches.rb' + +# Offense count: 7 +# Configuration parameters: MinSize. +Performance/CollectionLiteralInLoop: + Exclude: + - 'lib/puppet-lint/bin.rb' + - 'lib/puppet-lint/data.rb' + - 'lib/puppet-lint/plugins/check_resources/ensure_first_param.rb' + - 'lib/puppet-lint/plugins/check_whitespace/trailing_whitespace.rb' + +# Offense count: 406 +# Configuration parameters: Prefixes, AllowedPatterns. +# Prefixes: when, with, without +RSpec/ContextWording: + Enabled: false + +# Offense count: 41 +# Configuration parameters: IgnoredMetadata. +RSpec/DescribeClass: + Enabled: false + +# Offense count: 50 +# Configuration parameters: CountAsOne. +RSpec/ExampleLength: + Max: 148 + +# Offense count: 8 +# Configuration parameters: Include, CustomTransform, IgnoreMethods, SpecSuffixOnly. +# Include: **/*_spec*rb*, **/spec/**/* +RSpec/FilePath: + Exclude: + - 'spec/unit/puppet-lint/bin_spec.rb' + - 'spec/unit/puppet-lint/checks_spec.rb' + - 'spec/unit/puppet-lint/configuration_spec.rb' + - 'spec/unit/puppet-lint/data_spec.rb' + - 'spec/unit/puppet-lint/lexer/string_slurper_spec.rb' + - 'spec/unit/puppet-lint/lexer/token_spec.rb' + - 'spec/unit/puppet-lint/lexer_spec.rb' + - 'spec/unit/puppet-lint/puppet-lint_spec.rb' + +# Offense count: 138 +RSpec/MultipleExpectations: + Max: 137 + +# Offense count: 3 +# Configuration parameters: AllowSubject. +RSpec/MultipleMemoizedHelpers: + Max: 13 + +# Offense count: 52 +# Configuration parameters: AllowedGroups. +RSpec/NestedGroups: + Max: 5 + +# Offense count: 8 +RSpec/RepeatedExampleGroupDescription: + Exclude: + - 'spec/unit/puppet-lint/plugins/check_resources/file_mode_spec.rb' + - 'spec/unit/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb' + - 'spec/unit/puppet-lint/plugins/legacy_facts/legacy_facts_spec.rb' + +# Offense count: 106 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: + Enabled: false + +# Offense count: 9 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: Mode. +Style/StringConcatenation: + Exclude: + - 'lib/puppet-lint/bin.rb' + - 'lib/puppet-lint/plugins.rb' + - 'lib/puppet-lint/plugins/top_scope_facts/top_scope_facts.rb' + - 'spec/unit/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb' diff --git a/Gemfile b/Gemfile index e52713ed..f172fbbc 100644 --- a/Gemfile +++ b/Gemfile @@ -30,7 +30,7 @@ group :development do end group :rubocop do - gem 'rubocop', '~> 1.6.1', require: false - gem 'rubocop-rspec', '~> 2.0.1', require: false - gem 'rubocop-performance', '~> 1.9.1', require: false + gem 'rubocop', '~> 1.48.1', require: false + gem 'rubocop-rspec', '~> 2.19', require: false + gem 'rubocop-performance', '~> 1.16', require: false end diff --git a/lib/puppet-lint.rb b/lib/puppet-lint.rb index 2ce571d2..580dbd60 100644 --- a/lib/puppet-lint.rb +++ b/lib/puppet-lint.rb @@ -95,7 +95,7 @@ def file=(path) # Check if the input is an SE Linux policy package file (which also use # the .pp extension), which all have the first 4 bytes 0xf97cff8f. - @code = '' if @code[0..3].unpack('V').first == 0xf97cff8f + @code = '' if @code[0..3].unpack1('V') == 0xf97cff8f end # Internal: Retrieve the format string to be used when writing problems to @@ -155,8 +155,10 @@ def get_context(message) def print_context(message) return if message[:check] == 'documentation' return if message[:kind] == :fixed + line = message[:context] return unless line + offset = line.index(%r{\S}) || 1 puts "\n #{line.strip}" printf("%#{message[:column] + 2 - offset}s\n\n", '^') @@ -188,7 +190,7 @@ def report(problems) print_github_annotation(message) if configuration.github_actions end end - $stderr.puts 'Try running `puppet parser validate `' if problems.any? { |p| p[:check] == :syntax } + warn 'Try running `puppet parser validate `' if problems.any? { |p| p[:check] == :syntax } json end @@ -251,7 +253,7 @@ def print_problems def self.new_check(name, &block) class_name = name.to_s.split('_').map(&:capitalize).join klass = PuppetLint.const_set("Check#{class_name}", Class.new(PuppetLint::CheckPlugin)) - klass.const_set('NAME', name) + klass.const_set(:NAME, name) klass.class_exec(&block) PuppetLint.configuration.add_check(name, klass) PuppetLint::Data.ignore_overrides[name] ||= {} diff --git a/lib/puppet-lint/bin.rb b/lib/puppet-lint/bin.rb index 7ae04d8d..aa697b81 100644 --- a/lib/puppet-lint/bin.rb +++ b/lib/puppet-lint/bin.rb @@ -49,7 +49,7 @@ def run begin path = @args[0] - full_path = File.expand_path(path, ENV['PWD']) + full_path = File.expand_path(path, ENV.fetch('PWD', nil)) full_base_path = if File.directory?(full_path) full_path else @@ -79,19 +79,17 @@ def run path.each do |f| next if ignore_paths.any? { |p| File.fnmatch(p, f) } + l = PuppetLint.new l.file = f l.run all_problems << l.print_problems - if l.errors? || (l.warnings? && PuppetLint.configuration.fail_on_warnings) - return_val = 1 - end + return_val = 1 if l.errors? || (l.warnings? && PuppetLint.configuration.fail_on_warnings) next unless PuppetLint.configuration.fix && l.problems.none? { |r| r[:check] == :syntax } - File.open(f, 'wb') do |fd| - fd.write(l.manifest) - end + + File.binwrite(f, l.manifest) end if PuppetLint.configuration.sarif @@ -105,9 +103,7 @@ def run puts JSON.pretty_generate(all_problems) end - if PuppetLint.configuration.codeclimate_report_file - PuppetLint::Report::CodeClimateReporter.write_report_file(all_problems, PuppetLint.configuration.codeclimate_report_file) - end + PuppetLint::Report::CodeClimateReporter.write_report_file(all_problems, PuppetLint.configuration.codeclimate_report_file) if PuppetLint.configuration.codeclimate_report_file return_val rescue PuppetLint::NoCodeError @@ -148,7 +144,7 @@ def report_sarif(problems, base_path, base_path_uri) 'ruleIndex' => rule_index, 'message' => { 'text' => message[:message] }, 'locations' => [{ 'physicalLocation' => { 'artifactLocation' => { 'uri' => relative_path, 'uriBaseId' => 'ROOTPATH' }, -'region' => { 'startLine' => message[:line], 'startColumn' => message[:column] } } }], + 'region' => { 'startLine' => message[:line], 'startColumn' => message[:column] } } }] } results << result end diff --git a/lib/puppet-lint/checkplugin.rb b/lib/puppet-lint/checkplugin.rb index 0069476d..9561483a 100644 --- a/lib/puppet-lint/checkplugin.rb +++ b/lib/puppet-lint/checkplugin.rb @@ -179,10 +179,10 @@ def manifest_lines # Returns a Hash of default problem information. def default_info @default_info ||= { - check: self.class.const_get('NAME'), + check: self.class.const_get(:NAME), fullpath: fullpath, path: path, - filename: filename, + filename: filename } end @@ -202,14 +202,10 @@ def notify(kind, problem) problem[:kind] = kind problem.merge!(default_info) { |_key, v1, _v2| v1 } - unless [:warning, :error, :fixed].include?(kind) - raise ArgumentError, 'unknown value passed for kind' - end + raise ArgumentError, 'unknown value passed for kind' unless [:warning, :error, :fixed].include?(kind) [:message, :line, :column, :check].each do |attr| - unless problem.key?(attr) - raise ArgumentError, "problem hash must contain #{attr.inspect}" - end + raise ArgumentError, "problem hash must contain #{attr.inspect}" unless problem.key?(attr) end @problems << problem diff --git a/lib/puppet-lint/checks.rb b/lib/puppet-lint/checks.rb index ebef7366..399508f5 100644 --- a/lib/puppet-lint/checks.rb +++ b/lib/puppet-lint/checks.rb @@ -39,7 +39,7 @@ def load_data(path, content) column: e.column, fullpath: PuppetLint::Data.fullpath, path: PuppetLint::Data.path, - filename: PuppetLint::Data.filename, + filename: PuppetLint::Data.filename } PuppetLint::Data.tokens = [] end @@ -76,15 +76,15 @@ def run(fileinfo, data) kind: :error, check: :syntax, message: 'Syntax error', - fullpath: File.expand_path(fileinfo, ENV['PWD']), + fullpath: File.expand_path(fileinfo, ENV.fetch('PWD', nil)), filename: File.basename(fileinfo), path: fileinfo, line: e.token.line, - column: e.token.column, + column: e.token.column } @problems - rescue => e + rescue StandardError => e $stdout.puts <<-END.gsub(%r{^ {6}}, '') Whoops! It looks like puppet-lint has encountered an error that it doesn't know how to handle. Please open an issue at https://github.com/puppetlabs/puppet-lint @@ -120,10 +120,8 @@ def run(fileinfo, data) # # Returns an Array of String check names. def enabled_checks - @enabled_checks ||= begin - PuppetLint.configuration.checks.select do |check| - PuppetLint.configuration.send("#{check}_enabled?") - end + @enabled_checks ||= PuppetLint.configuration.checks.select do |check| + PuppetLint.configuration.send("#{check}_enabled?") end end @@ -131,6 +129,6 @@ def enabled_checks # # Returns the manifest as a String. def manifest - PuppetLint::Data.tokens.map(&:to_manifest).join('') + PuppetLint::Data.tokens.map(&:to_manifest).join end end diff --git a/lib/puppet-lint/configuration.rb b/lib/puppet-lint/configuration.rb index 041d50ab..c3539ed5 100644 --- a/lib/puppet-lint/configuration.rb +++ b/lib/puppet-lint/configuration.rb @@ -18,7 +18,7 @@ def self.add_check(check) # # Returns true if the check is enabled, otherwise return false. define_method("#{check}_enabled?") do - settings["#{check}_disabled"] == true ? false : true + settings["#{check}_disabled"] != true end # Public: Disable the named check. @@ -153,6 +153,6 @@ def defaults self.show_ignored = false self.ignore_paths = ['vendor/**/*.pp'] self.github_actions = ENV.key?('GITHUB_ACTION') - self.codeclimate_report_file = ENV['CODECLIMATE_REPORT_FILE'] + self.codeclimate_report_file = ENV.fetch('CODECLIMATE_REPORT_FILE', nil) end end diff --git a/lib/puppet-lint/data.rb b/lib/puppet-lint/data.rb index 09707f04..940029bf 100644 --- a/lib/puppet-lint/data.rb +++ b/lib/puppet-lint/data.rb @@ -72,7 +72,7 @@ def insert(index, token) unless formatting_tokens.include?(token.type) current_token.next_token.prev_code_token = token unless current_token.next_token.nil? - next_nf_idx = tokens[index..-1].index { |r| !formatting_tokens.include?(r.type) } + next_nf_idx = tokens[index..].index { |r| !formatting_tokens.include?(r.type) } unless next_nf_idx.nil? next_nf_token = tokens[index + next_nf_idx] token.next_code_token = next_nf_token @@ -92,9 +92,7 @@ def insert(index, token) end current_token.next_token = token - unless formatting_tokens.include?(token.type) - current_token.next_code_token = token - end + current_token.next_code_token = token unless formatting_tokens.include?(token.type) tokens.insert(index, token) end @@ -123,7 +121,7 @@ def path=(val) @fullpath = nil @filename = nil else - @fullpath = File.expand_path(val, ENV['PWD']) + @fullpath = File.expand_path(val, ENV.fetch('PWD', nil)) @filename = File.basename(val) end end @@ -184,12 +182,14 @@ def resource_indexes next unless colon_token.next_code_token && colon_token.next_code_token.type != :LBRACE next if classref?(colon_token) - rel_start_idx = tokens[marker..-1].index(colon_token) + rel_start_idx = tokens[marker..].index(colon_token) break if rel_start_idx.nil? + start_idx = rel_start_idx + marker end_token = colon_token.next_token_of([:SEMIC, :RBRACE]) - rel_end_idx = tokens[start_idx..-1].index(end_token) + rel_end_idx = tokens[start_idx..].index(end_token) raise PuppetLint::SyntaxError, colon_token if rel_end_idx.nil? + marker = rel_end_idx + start_idx result << { @@ -197,7 +197,7 @@ def resource_indexes end: marker, tokens: tokens[start_idx..marker], type: find_resource_type_token(start_idx), - param_tokens: find_resource_param_tokens(tokens[start_idx..marker]), + param_tokens: find_resource_param_tokens(tokens[start_idx..marker]) } end result @@ -237,9 +237,7 @@ def find_resource_param_tokens(resource_tokens) break unless resource_tokens.include?(iter_token) - if iter_token && iter_token.next_code_token.type == :FARROW - param_tokens << iter_token - end + param_tokens << iter_token if iter_token && iter_token.next_code_token.type == :FARROW end param_tokens @@ -306,7 +304,7 @@ def definition_indexes(type) paren_depth = 0 in_params = false inherited_class = nil - tokens[i + 1..-1].each_with_index do |definition_token, j| + tokens[i + 1..].each_with_index do |definition_token, j| case definition_token.type when :INHERITS inherited_class = definition_token.next_code_token @@ -320,19 +318,17 @@ def definition_indexes(type) brace_depth += 1 when :RBRACE brace_depth -= 1 - if brace_depth.zero? && !in_params - if token.next_code_token.type != :LBRACE - result << { - start: i, - end: i + j + 1, - tokens: tokens[i..(i + j + 1)], - param_tokens: param_tokens(tokens[i..(i + j + 1)]), - type: type, - name_token: token.next_code_token, - inherited_token: inherited_class, - } - break - end + if brace_depth.zero? && !in_params && (token.next_code_token.type != :LBRACE) + result << { + start: i, + end: i + j + 1, + tokens: tokens[i..(i + j + 1)], + param_tokens: param_tokens(tokens[i..(i + j + 1)]), + type: type, + name_token: token.next_code_token, + inherited_token: inherited_class + } + break end end end @@ -367,7 +363,7 @@ def function_indexes level = 0 real_idx = 0 in_paren = false - tokens[token_idx + 1..-1].each_with_index do |cur_token, cur_token_idx| + tokens[token_idx + 1..].each_with_index do |cur_token, cur_token_idx| break if level.zero? && in_paren break if level.zero? && cur_token.type == :NEWLINE @@ -382,7 +378,7 @@ def function_indexes functions << { start: token_idx, end: real_idx, - tokens: tokens[token_idx..real_idx], + tokens: tokens[token_idx..real_idx] } end functions @@ -406,7 +402,7 @@ def array_indexes next unless token.type == :LBRACK real_idx = 0 - tokens[token_idx + 1..-1].each_with_index do |cur_token, cur_token_idx| + tokens[token_idx + 1..].each_with_index do |cur_token, cur_token_idx| real_idx = token_idx + 1 + cur_token_idx break if cur_token.type == :RBRACK end @@ -418,7 +414,7 @@ def array_indexes arrays << { start: token_idx, end: real_idx, - tokens: tokens[token_idx..real_idx], + tokens: tokens[token_idx..real_idx] } end arrays @@ -445,18 +441,18 @@ def hash_indexes level = 0 real_idx = 0 - tokens[token_idx + 1..-1].each_with_index do |cur_token, cur_token_idx| + tokens[token_idx + 1..].each_with_index do |cur_token, cur_token_idx| real_idx = token_idx + 1 + cur_token_idx level += 1 if cur_token.type == :LBRACE level -= 1 if cur_token.type == :RBRACE - break if level < 0 + break if level.negative? end hashes << { start: token_idx, end: real_idx, - tokens: tokens[token_idx..real_idx], + tokens: tokens[token_idx..real_idx] } end hashes @@ -482,7 +478,7 @@ def defaults_indexes real_idx = 0 - tokens[token_idx + 1..-1].each_with_index do |cur_token, cur_token_idx| + tokens[token_idx + 1..].each_with_index do |cur_token, cur_token_idx| real_idx = token_idx + 1 + cur_token_idx break if cur_token.type == :RBRACE end @@ -490,7 +486,7 @@ def defaults_indexes defaults << { start: token_idx, end: real_idx, - tokens: tokens[token_idx..real_idx], + tokens: tokens[token_idx..real_idx] } end defaults @@ -564,7 +560,7 @@ def parse_control_comments comment_token_types.include?(token.type) end control_comment_tokens = comment_tokens.select do |token| - token.value.strip =~ %r{\Alint\:(ignore\:[\w\d]+|endignore)} + token.value.strip =~ %r{\Alint:(ignore:[\w\d]+|endignore)} end stack = [] @@ -574,12 +570,12 @@ def parse_control_comments comment_words = token.value.strip.split(%r{\s+}) comment_words.each_with_index do |word, i| - if %r{\Alint\:(ignore|endignore)}.match?(word) + if %r{\Alint:(ignore|endignore)}.match?(word) comment_data << word else # Once we reach the first non-controlcomment word, assume the rest # of the words are the reason. - reason = comment_words[i..-1] + reason = comment_words[i..] break end end @@ -604,7 +600,7 @@ def parse_control_comments if top_override.nil? # TODO: refactor to provide a way to expose problems from # PuppetLint::Data via the normal problem reporting mechanism. - $stderr.puts "WARNING: lint:endignore comment with no opening lint:ignore: comment found on line #{token.line}" + warn "WARNING: lint:endignore comment with no opening lint:ignore: comment found on line #{token.line}" else top_override.each do |start| next if start.nil? @@ -620,7 +616,7 @@ def parse_control_comments end stack.each do |control| - $stderr.puts "WARNING: lint:ignore:#{control[0][2]} comment on line #{control[0][0]} with no closing lint:endignore comment" + warn "WARNING: lint:ignore:#{control[0][2]} comment on line #{control[0][0]} with no closing lint:endignore comment" end end end diff --git a/lib/puppet-lint/lexer.rb b/lib/puppet-lint/lexer.rb index dc1eb85f..b525e85d 100644 --- a/lib/puppet-lint/lexer.rb +++ b/lib/puppet-lint/lexer.rb @@ -1,6 +1,3 @@ -# encoding: utf-8 - -require 'pp' require 'strscan' require 'set' require 'puppet-lint/lexer/token' @@ -56,27 +53,27 @@ def heredoc_queue # From https://github.com/puppetlabs/puppet/blob/master/lib/puppet/pops/parser/lexer2.rb#L116-L137 # or thereabouts KEYWORDS = { - 'case' => true, - 'class' => true, - 'default' => true, - 'define' => true, - 'import' => true, - 'if' => true, - 'elsif' => true, - 'else' => true, + 'case' => true, + 'class' => true, + 'default' => true, + 'define' => true, + 'import' => true, + 'if' => true, + 'elsif' => true, + 'else' => true, 'inherits' => true, - 'node' => true, - 'and' => true, - 'or' => true, - 'undef' => true, - 'false' => true, - 'true' => true, - 'in' => true, - 'unless' => true, + 'node' => true, + 'and' => true, + 'or' => true, + 'undef' => true, + 'false' => true, + 'true' => true, + 'in' => true, + 'unless' => true, 'function' => true, - 'type' => true, - 'attr' => true, - 'private' => true, + 'type' => true, + 'attr' => true, + 'private' => true }.freeze # Internal: A Hash whose keys are Strings representing reserved keywords in @@ -86,9 +83,9 @@ def heredoc_queue # Currently unused APP_MANAGEMENT_TOKENS = { 'application' => true, - 'consumes' => true, - 'produces' => true, - 'site' => true, + 'consumes' => true, + 'produces' => true, + 'site' => true }.freeze # Internal: A Hash whose keys are Symbols representing token types which @@ -104,7 +101,7 @@ def heredoc_queue IF: true, ELSIF: true, LPAREN: true, - EQUALS: true, + EQUALS: true }.freeze # Internal: some commonly used regular expressions @@ -112,7 +109,7 @@ def heredoc_queue # \v == vertical tab # \f == form feed # \p{Zs} == ASCII + Unicode non-linebreaking whitespace - WHITESPACE_RE = RUBY_VERSION == '1.8.7' ? %r{[\t\v\f ]} : %r{[\t\v\f\p{Zs}]} + WHITESPACE_RE = (RUBY_VERSION == '1.8.7') ? %r{[\t\v\f ]} : %r{[\t\v\f\p{Zs}]} LINE_END_RE = %r{(?:\r\n|\r|\n)}.freeze @@ -182,7 +179,7 @@ def heredoc_queue COMMENT: true, MLCOMMENT: true, SLASH_COMMENT: true, - INDENT: true, + INDENT: true }.freeze # Internal: Access the internal token storage. @@ -203,7 +200,7 @@ def tokenise(code) i = 0 while i < code.size - chunk = code[i..-1] + chunk = code[i..] found = false @@ -233,12 +230,12 @@ def tokenise(code) tokens << new_token(:VARIABLE, var_name, opts) elsif %r{\A'.*?'}m.match?(chunk) - str_content = StringScanner.new(code[i + 1..-1]).scan_until(%r{(\A|[^\\])(\\\\)*'}m) + str_content = StringScanner.new(code[i + 1..]).scan_until(%r{(\A|[^\\])(\\\\)*'}m) length = str_content.size + 1 tokens << new_token(:SSTRING, str_content[0..-2]) elsif chunk.start_with?('"') - slurper = PuppetLint::Lexer::StringSlurper.new(code[i + 1..-1]) + slurper = PuppetLint::Lexer::StringSlurper.new(code[i + 1..]) begin string_segments = slurper.parse process_string_segments(string_segments) @@ -271,7 +268,7 @@ def tokenise(code) tokens << new_token(:MLCOMMENT, mlcomment, raw: mlcomment_raw) elsif chunk.match(%r{\A/.*?/}m) && possible_regex? - str_content = StringScanner.new(code[i + 1..-1]).scan_until(%r{(\A|[^\\])(\\\\)*/}m) + str_content = StringScanner.new(code[i + 1..]).scan_until(%r{(\A|[^\\])(\\\\)*/}m) length = str_content.size + 1 tokens << new_token(:REGEX, str_content[0..-2]) @@ -286,7 +283,7 @@ def tokenise(code) length += indent.size else heredoc_tag = heredoc_queue.shift - slurper = PuppetLint::Lexer::StringSlurper.new(code[i + length..-1]) + slurper = PuppetLint::Lexer::StringSlurper.new(code[i + length..]) heredoc_segments = slurper.parse_heredoc(heredoc_tag) process_heredoc_segments(heredoc_segments) length += slurper.consumed_chars @@ -298,7 +295,7 @@ def tokenise(code) unless heredoc_queue.empty? heredoc_tag = heredoc_queue.shift - slurper = PuppetLint::Lexer::StringSlurper.new(code[i + length..-1]) + slurper = PuppetLint::Lexer::StringSlurper.new(code[i + length..]) heredoc_segments = slurper.parse_heredoc(heredoc_tag) process_heredoc_segments(heredoc_segments) length += slurper.consumed_chars @@ -419,11 +416,11 @@ def process_string_segments(segments) lexer = PuppetLint::Lexer.new lexer.tokenise(segment[1]) lexer.tokens.each_with_index do |t, i| - type = i.zero? && t.interpolated_variable? ? :VARIABLE : t.type + type = (i.zero? && t.interpolated_variable?) ? :VARIABLE : t.type tokens << new_token(type, t.value, raw: t.raw) end when :UNENC_VAR - tokens << new_token(:UNENC_VARIABLE, segment[1].gsub(%r{\A\$}, '')) + tokens << new_token(:UNENC_VARIABLE, segment[1].delete_prefix('$')) else tokens << new_token(:DQMID, segment[1]) end @@ -451,11 +448,11 @@ def process_heredoc_segments(segments) lexer = PuppetLint::Lexer.new lexer.tokenise(segment[1]) lexer.tokens.each_with_index do |t, i| - type = i.zero? && t.interpolated_variable? ? :VARIABLE : t.type + type = (i.zero? && t.interpolated_variable?) ? :VARIABLE : t.type tokens << new_token(type, t.value, raw: t.raw) end when :UNENC_VAR - tokens << new_token(:UNENC_VARIABLE, segment[1].gsub(%r{\A\$}, '')) + tokens << new_token(:UNENC_VARIABLE, segment[1].delete_prefix('$')) else tokens << new_token(:HEREDOC_MID, segment[1]) end diff --git a/lib/puppet-lint/lexer/string_slurper.rb b/lib/puppet-lint/lexer/string_slurper.rb index c1426be9..29304fb9 100644 --- a/lib/puppet-lint/lexer/string_slurper.rb +++ b/lib/puppet-lint/lexer/string_slurper.rb @@ -1,11 +1,10 @@ require 'strscan' +# rubocop:disable Style/ClassAndModuleChildren class PuppetLint::Lexer # Internal: A class for slurping strings from a Puppet manifest. class StringSlurper - attr_accessor :scanner - attr_accessor :results - attr_accessor :interp_stack + attr_accessor :scanner, :results, :interp_stack START_INTERP_PATTERN = %r{\$\{}.freeze END_INTERP_PATTERN = %r{\}}.freeze diff --git a/lib/puppet-lint/lexer/token.rb b/lib/puppet-lint/lexer/token.rb index 72720432..d45c2443 100644 --- a/lib/puppet-lint/lexer/token.rb +++ b/lib/puppet-lint/lexer/token.rb @@ -1,3 +1,4 @@ +# rubocop:disable Style/ClassAndModuleChildren class PuppetLint::Lexer # Public: Stores a fragment of the manifest and the information about its # location in the manifest. @@ -175,12 +176,10 @@ def find_token_of(direction, type, opts = {}) token_iter = send("#{direction}_token".to_sym) until token_iter.nil? - if to_find.include?(token_iter.type) - return token_iter if opts[:value].nil? || token_iter.value == opts[:value] - end + return token_iter if to_find.include?(token_iter.type) && (opts[:value].nil? || token_iter.value == opts[:value]) - opening_token = direction == :next ? 'L' : 'R' - closing_token = direction == :next ? 'R' : 'L' + opening_token = (direction == :next) ? 'L' : 'R' + closing_token = (direction == :next) ? 'R' : 'L' if opts[:skip_blocks] case token_iter.type @@ -194,6 +193,7 @@ def find_token_of(direction, type, opts = {}) end return nil if token_iter.nil? + token_iter = token_iter.send("#{direction}_token".to_sym) end nil @@ -202,6 +202,7 @@ def find_token_of(direction, type, opts = {}) def interpolated_variable? return false if type == :TYPE && value != 'type' return true if type == :NAME + PuppetLint::Lexer::KEYWORDS.include?(type.to_s.downcase) end end diff --git a/lib/puppet-lint/monkeypatches.rb b/lib/puppet-lint/monkeypatches.rb index 9c2784eb..72461a91 100644 --- a/lib/puppet-lint/monkeypatches.rb +++ b/lib/puppet-lint/monkeypatches.rb @@ -1,9 +1,9 @@ begin '%{test}' % { test: 'replaced' } == 'replaced' -rescue +rescue StandardError # monkeypatch String#% into Ruby 1.8.7 class String - Percent = instance_method('%') unless defined?(Percent) + Percent = instance_method(:%) unless defined?(Percent) def %(*a, &b) a.flatten! @@ -18,7 +18,7 @@ def %(*a, &b) if a.empty? string else - Percent.bind(string).call(a, &b) + Percent.bind_call(string, a, &b) end end @@ -28,7 +28,7 @@ def expand!(vars = {}) vars.each do |var, value| var = var.to_s var.gsub!(%r{[^a-zA-Z0-9_]}, '') - changed = gsub!(%r{\%\{#{var}\}}, value.to_s) + changed = gsub!(%r{%\{#{var}\}}, value.to_s) end break unless changed end diff --git a/lib/puppet-lint/optparser.rb b/lib/puppet-lint/optparser.rb index 22b0014f..6931be8d 100644 --- a/lib/puppet-lint/optparser.rb +++ b/lib/puppet-lint/optparser.rb @@ -143,7 +143,7 @@ def self.build(args = []) unless args.include?('--no-config') opt_parser.load('/etc/puppet-lint.rc') - if ENV.key?('HOME') && File.readable?(ENV['HOME']) + if File.readable?(Dir.home) home_dotfile_path = File.expand_path('~/.puppet-lint.rc') opt_parser.load(home_dotfile_path) if File.readable?(home_dotfile_path) end diff --git a/lib/puppet-lint/plugins.rb b/lib/puppet-lint/plugins.rb index 49168723..905c5046 100644 --- a/lib/puppet-lint/plugins.rb +++ b/lib/puppet-lint/plugins.rb @@ -55,9 +55,8 @@ def gemspecs def load_prerelease_plugins? # Load prerelease plugins (which ruby defines as any gem which has a letter in its version number). # Can't use puppet-lint configuration object here because this code executes before the command line is parsed. - if ENV['PUPPET_LINT_LOAD_PRERELEASE_PLUGINS'] - return ['true', 'yes'].include?(ENV['PUPPET_LINT_LOAD_PRERELEASE_PLUGINS'].downcase) - end + return ['true', 'yes'].include?(ENV['PUPPET_LINT_LOAD_PRERELEASE_PLUGINS'].downcase) if ENV['PUPPET_LINT_LOAD_PRERELEASE_PLUGINS'] + false end @@ -76,7 +75,7 @@ def gem_directories end end -Dir[File.expand_path('plugins/**/*.rb', File.dirname(__FILE__))].each do |file| +Dir[File.expand_path('plugins/**/*.rb', File.dirname(__FILE__))].sort.each do |file| require file end diff --git a/lib/puppet-lint/plugins/check_classes/arrow_on_right_operand_line.rb b/lib/puppet-lint/plugins/check_classes/arrow_on_right_operand_line.rb index e338a598..a891c410 100644 --- a/lib/puppet-lint/plugins/check_classes/arrow_on_right_operand_line.rb +++ b/lib/puppet-lint/plugins/check_classes/arrow_on_right_operand_line.rb @@ -35,6 +35,7 @@ def fix(problem) # Remove trailing whitespace after left operand (if it exists) return unless left_operand_token.next_token.type == :WHITESPACE + trailing_whitespace_token = left_operand_token.next_token remove_token(trailing_whitespace_token) if [:NEWLINE, :WHITESPACE].include?(trailing_whitespace_token.next_token.type) end diff --git a/lib/puppet-lint/plugins/check_classes/autoloader_layout.rb b/lib/puppet-lint/plugins/check_classes/autoloader_layout.rb index ac88a7d1..1aef1ed6 100644 --- a/lib/puppet-lint/plugins/check_classes/autoloader_layout.rb +++ b/lib/puppet-lint/plugins/check_classes/autoloader_layout.rb @@ -12,14 +12,12 @@ def check split_title = title_token.value.split('::') mod = split_title.first expected_path = if split_title.length > 1 - "/#{mod}/manifests/#{split_title[1..-1].join('/')}.pp" + "/#{mod}/manifests/#{split_title[1..].join('/')}.pp" else "/#{title_token.value}/manifests/init.pp" end - if PuppetLint.configuration.relative - expected_path = expected_path.gsub(%r{^/}, '').split('/')[1..-1].join('/') - end + expected_path = expected_path.gsub(%r{^/}, '').split('/')[1..].join('/') if PuppetLint.configuration.relative next if fullpath.end_with?(expected_path) diff --git a/lib/puppet-lint/plugins/check_classes/class_inherits_from_params_class.rb b/lib/puppet-lint/plugins/check_classes/class_inherits_from_params_class.rb index 574f4e1e..56bdb63f 100644 --- a/lib/puppet-lint/plugins/check_classes/class_inherits_from_params_class.rb +++ b/lib/puppet-lint/plugins/check_classes/class_inherits_from_params_class.rb @@ -5,7 +5,7 @@ PuppetLint.new_check(:class_inherits_from_params_class) do def check class_indexes.each do |class_idx| - next unless class_idx[:inherited_token] && class_idx[:inherited_token]&.value&.end_with?('::params') + next unless class_idx[:inherited_token]&.value&.end_with?('::params') notify( :warning, @@ -18,4 +18,4 @@ def check end end end -PuppetLint.configuration.send('disable_class_inherits_from_params_class') +PuppetLint.configuration.send(:disable_class_inherits_from_params_class) diff --git a/lib/puppet-lint/plugins/check_classes/code_on_top_scope.rb b/lib/puppet-lint/plugins/check_classes/code_on_top_scope.rb index 53e41121..44259392 100644 --- a/lib/puppet-lint/plugins/check_classes/code_on_top_scope.rb +++ b/lib/puppet-lint/plugins/check_classes/code_on_top_scope.rb @@ -20,4 +20,4 @@ def check end end end -PuppetLint.configuration.send('disable_code_on_top_scope') +PuppetLint.configuration.send(:disable_code_on_top_scope) diff --git a/lib/puppet-lint/plugins/check_classes/nested_classes_or_defines.rb b/lib/puppet-lint/plugins/check_classes/nested_classes_or_defines.rb index a93712c5..4ed25869 100644 --- a/lib/puppet-lint/plugins/check_classes/nested_classes_or_defines.rb +++ b/lib/puppet-lint/plugins/check_classes/nested_classes_or_defines.rb @@ -2,18 +2,18 @@ # defined inside another class. # # https://puppet.com/docs/puppet/latest/style_guide.html#nested-classes-or-defined-types +CLASS_DEFINE_TOKENS = Set[:CLASS, :DEFINE] PuppetLint.new_check(:nested_classes_or_defines) do - TOKENS = Set[:CLASS, :DEFINE] - def check class_indexes.each do |class_idx| # Skip the first token so that we don't pick up the first :CLASS - class_tokens = class_idx[:tokens][1..-1] + class_tokens = class_idx[:tokens][1..] class_tokens.each do |token| - next unless TOKENS.include?(token.type) + next unless CLASS_DEFINE_TOKENS.include?(token.type) next if token.next_code_token.type == :LBRACE - type = token.type == :CLASS ? 'class' : 'defined type' + + type = (token.type == :CLASS) ? 'class' : 'defined type' notify( :warning, diff --git a/lib/puppet-lint/plugins/check_classes/parameter_order.rb b/lib/puppet-lint/plugins/check_classes/parameter_order.rb index 7ebe06d7..a1deb2b9 100644 --- a/lib/puppet-lint/plugins/check_classes/parameter_order.rb +++ b/lib/puppet-lint/plugins/check_classes/parameter_order.rb @@ -11,13 +11,14 @@ def check paren_stack = [] hash_or_array_stack = [] class_idx[:param_tokens].each_with_index do |token, i| - if token.type == :LPAREN + case token.type + when :LPAREN paren_stack.push(true) - elsif token.type == :RPAREN + when :RPAREN paren_stack.pop - elsif token.type == :LBRACE || token.type == :LBRACK + when :LBRACE, :LBRACK hash_or_array_stack.push(true) - elsif token.type == :RBRACE || token.type == :RBRACK + when :RBRACE, :RBRACK hash_or_array_stack.pop end @@ -34,8 +35,8 @@ def check message: msg, line: token.line, column: token.column, - description: 'Test the manifest tokens for any parameterised classes or defined types that take '\ - 'parameters and record a warning if there are any optional parameters listed before required parameters.', + description: 'Test the manifest tokens for any parameterised classes or defined types that take ' \ + 'parameters and record a warning if there are any optional parameters listed before required parameters.', help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#display-order-of-parameters', ) end @@ -58,9 +59,7 @@ def required_parameter?(token) data_type = token.prev_token_of(:TYPE, skip_blocks: true) return false if data_type && data_type.value == 'Optional' - if token.next_code_token.nil? || [:COMMA, :RPAREN].include?(token.next_code_token.type) - return !(token.prev_code_token && token.prev_code_token.type == :EQUALS) - end + return !(token.prev_code_token && token.prev_code_token.type == :EQUALS) if token.next_code_token.nil? || [:COMMA, :RPAREN].include?(token.next_code_token.type) false end diff --git a/lib/puppet-lint/plugins/check_classes/variable_scope.rb b/lib/puppet-lint/plugins/check_classes/variable_scope.rb index bb4ef23a..6136e0c7 100644 --- a/lib/puppet-lint/plugins/check_classes/variable_scope.rb +++ b/lib/puppet-lint/plugins/check_classes/variable_scope.rb @@ -5,35 +5,35 @@ # not. # # https://puppet.com/docs/puppet/latest/style_guide.html#namespacing-variables -PuppetLint.new_check(:variable_scope) do - DEFAULT_SCOPE_VARS = Set[ - 'name', - 'title', - 'module_name', - 'environment', - 'clientcert', - 'clientversion', - 'servername', - 'serverip', - 'serverversion', - 'caller_module_name', - 'alias', - 'audit', - 'before', - 'loglevel', - 'noop', - 'notify', - 'require', - 'schedule', - 'stage', - 'subscribe', - 'tag', - 'facts', - 'trusted', - 'server_facts', - ] - POST_VAR_TOKENS = Set[:COMMA, :EQUALS, :RPAREN] +DEFAULT_SCOPE_VARS = Set[ + 'name', + 'title', + 'module_name', + 'environment', + 'clientcert', + 'clientversion', + 'servername', + 'serverip', + 'serverversion', + 'caller_module_name', + 'alias', + 'audit', + 'before', + 'loglevel', + 'noop', + 'notify', + 'require', + 'schedule', + 'stage', + 'subscribe', + 'tag', + 'facts', + 'trusted', + 'server_facts', +] +POST_VAR_TOKENS = Set[:COMMA, :EQUALS, :RPAREN] +PuppetLint.new_check(:variable_scope) do def check variables_in_scope = DEFAULT_SCOPE_VARS.clone @@ -93,7 +93,7 @@ def check end_token = nil brace_depth = 0 - tokens[start_idx..-1].each do |sub_token| + tokens[start_idx..].each do |sub_token| case sub_token.type when :LBRACE brace_depth += 1 @@ -117,9 +117,7 @@ def check msg = 'top-scope variable being used without an explicit namespace' referenced_variables.each do |token| - unless future_parser_scopes[token.line].nil? - next if future_parser_scopes[token.line].include?(token.value.gsub(%r{\[.+\]\Z}, '')) - end + next if !future_parser_scopes[token.line].nil? && future_parser_scopes[token.line].include?(token.value.gsub(%r{\[.+\]\Z}, '')) next if token.value.include?('::') next if %r{^(facts|trusted)\[.+\]}.match?(token.value) @@ -132,8 +130,8 @@ def check line: token.line, column: token.column, description: 'Test the manifest tokens for any variables that are referenced in the manifest. ' \ - 'If the variables are not fully qualified or one of the variables automatically created in the scope, ' \ - 'check that they have been defined in the local scope and record a warning for each variable that has not.', + 'If the variables are not fully qualified or one of the variables automatically created in the scope, ' \ + 'check that they have been defined in the local scope and record a warning for each variable that has not.', help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#namespacing-variables', ) end diff --git a/lib/puppet-lint/plugins/check_conditionals/case_without_default.rb b/lib/puppet-lint/plugins/check_conditionals/case_without_default.rb index 3973ef4d..060208a6 100644 --- a/lib/puppet-lint/plugins/check_conditionals/case_without_default.rb +++ b/lib/puppet-lint/plugins/check_conditionals/case_without_default.rb @@ -10,7 +10,7 @@ def check next unless tokens[token_idx].type == :CASE depth = 0 - tokens[(token_idx + 1)..-1].each_index do |case_token_idx| + tokens[(token_idx + 1)..].each_index do |case_token_idx| idx = case_token_idx + token_idx + 1 if tokens[idx].type == :LBRACE depth += 1 @@ -27,7 +27,7 @@ def check case_indexes.each_with_index do |kase, kase_index| case_tokens = tokens[kase[:start]..kase[:end]] - case_indexes[(kase_index + 1)..-1].each do |successor_kase| + case_indexes[(kase_index + 1)..].each do |successor_kase| case_tokens -= tokens[successor_kase[:start]..successor_kase[:end]] end diff --git a/lib/puppet-lint/plugins/check_documentation/documentation.rb b/lib/puppet-lint/plugins/check_documentation/documentation.rb index 0bcb51b6..a0549298 100644 --- a/lib/puppet-lint/plugins/check_documentation/documentation.rb +++ b/lib/puppet-lint/plugins/check_documentation/documentation.rb @@ -3,10 +3,10 @@ # record a warning for each instance found. # # https://puppet.com/docs/puppet/latest/style_guide.html#public-and-private -PuppetLint.new_check(:documentation) do - COMMENT_TOKENS = Set[:COMMENT, :MLCOMMENT, :SLASH_COMMENT] - WHITESPACE_TOKENS = Set[:WHITESPACE, :NEWLINE, :INDENT] +COMMENT_TOKENS = Set[:COMMENT, :MLCOMMENT, :SLASH_COMMENT] +WHITESPACE_TOKENS = Set[:WHITESPACE, :NEWLINE, :INDENT] +PuppetLint.new_check(:documentation) do def check (class_indexes + defined_type_indexes).each do |item_idx| comment_token = find_comment_token(item_idx[:tokens].first) @@ -25,9 +25,9 @@ def check message: "#{type} not documented", line: first_token.line, column: first_token.column, - description: 'Check the manifest tokens for any class or defined type that does not '\ - 'have a comment directly above it (hopefully, explaining the usage of it) and record '\ - 'a warning for each instance found.', + description: 'Check the manifest tokens for any class or defined type that does not ' \ + 'have a comment directly above it (hopefully, explaining the usage of it) and record ' \ + 'a warning for each instance found.', help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#public-and-private', ) end @@ -40,6 +40,7 @@ def find_comment_token(start_token) while !prev_token.nil? && WHITESPACE_TOKENS.include?(prev_token.type) newlines += 1 if prev_token.type == :NEWLINE break if newlines > 1 + prev_token = prev_token.prev_token end diff --git a/lib/puppet-lint/plugins/check_nodes/unquoted_node_name.rb b/lib/puppet-lint/plugins/check_nodes/unquoted_node_name.rb index 8f1be047..1c9c8662 100644 --- a/lib/puppet-lint/plugins/check_nodes/unquoted_node_name.rb +++ b/lib/puppet-lint/plugins/check_nodes/unquoted_node_name.rb @@ -7,7 +7,7 @@ def check node_tokens = tokens.select { |token| token.type == :NODE } node_tokens.each do |node| node_token_idx = tokens.index(node) - node_lbrace_tok = tokens[node_token_idx..-1].find { |token| token.type == :LBRACE } + node_lbrace_tok = tokens[node_token_idx..].find { |token| token.type == :LBRACE } if node_lbrace_tok.nil? notify( :error, diff --git a/lib/puppet-lint/plugins/check_resources/ensure_first_param.rb b/lib/puppet-lint/plugins/check_resources/ensure_first_param.rb index a5eff9de..f5eee84c 100644 --- a/lib/puppet-lint/plugins/check_resources/ensure_first_param.rb +++ b/lib/puppet-lint/plugins/check_resources/ensure_first_param.rb @@ -21,8 +21,8 @@ def check line: ensure_token.line, column: ensure_token.column, resource: resource, - description: 'Check the tokens of each resource instance for an ensure parameter and if '\ - 'found, check that it is the first parameter listed. If it is not the first parameter, record a warning.', + description: 'Check the tokens of each resource instance for an ensure parameter and if ' \ + 'found, check that it is the first parameter listed. If it is not the first parameter, record a warning.', help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#attribute-ordering', ) end @@ -37,9 +37,7 @@ def fix(problem) ensure_param_comma_token = ensure_param_name_token.next_token_of([:COMMA, :SEMIC]) - if first_param_name_token.nil? || first_param_comma_token.nil? || ensure_param_comma_token.nil? - raise PuppetLint::NoFix - end + raise PuppetLint::NoFix if first_param_name_token.nil? || first_param_comma_token.nil? || ensure_param_comma_token.nil? first_param_name_idx = tokens.index(first_param_name_token) first_param_comma_idx = tokens.index(first_param_comma_token) diff --git a/lib/puppet-lint/plugins/check_resources/ensure_not_symlink_target.rb b/lib/puppet-lint/plugins/check_resources/ensure_not_symlink_target.rb index 66868abc..9d21b7fd 100644 --- a/lib/puppet-lint/plugins/check_resources/ensure_not_symlink_target.rb +++ b/lib/puppet-lint/plugins/check_resources/ensure_not_symlink_target.rb @@ -21,8 +21,8 @@ def check column: value_token.column, param_token: ensure_token, value_token: value_token, - description: 'Check the tokens of each File resource instance for an ensure parameter and '\ - 'record a warning if the value of that parameter looks like a symlink target (starts with a \'/\').', + description: 'Check the tokens of each File resource instance for an ensure parameter and ' \ + 'record a warning if the value of that parameter looks like a symlink target (starts with a \'/\').', help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#symbolic-links', ) end diff --git a/lib/puppet-lint/plugins/check_resources/file_mode.rb b/lib/puppet-lint/plugins/check_resources/file_mode.rb index 93f15dc9..5e7e0299 100644 --- a/lib/puppet-lint/plugins/check_resources/file_mode.rb +++ b/lib/puppet-lint/plugins/check_resources/file_mode.rb @@ -3,12 +3,12 @@ # not a 4 digit octal value (0755) or a symbolic mode ('o=rwx,g+r'). # # https://puppet.com/docs/puppet/latest/style_guide.html#file-modes -PuppetLint.new_check(:file_mode) do - MSG = 'mode should be represented as a 4 digit octal value or symbolic mode'.freeze - SYM_RE = '([ugoa]*[-=+][-=+rstwxXugo]*)(,[ugoa]*[-=+][-=+rstwxXugo]*)*'.freeze - IGNORE_TYPES = Set[:VARIABLE, :UNDEF, :FUNCTION_NAME] - MODE_RE = %r{\A([0-7]{4}|#{SYM_RE})\Z}.freeze +MSG = 'mode should be represented as a 4 digit octal value or symbolic mode'.freeze +SYM_RE = '([ugoa]*[-=+][-=+rstwxXugo]*)(,[ugoa]*[-=+][-=+rstwxXugo]*)*'.freeze +IGNORE_TYPES = Set[:VARIABLE, :UNDEF, :FUNCTION_NAME] +MODE_RE = %r{\A([0-7]{4}|#{SYM_RE})\Z}.freeze +PuppetLint.new_check(:file_mode) do def check resource_indexes.each do |resource| next unless resource[:type].value == 'file' || resource[:type].value == 'concat' @@ -30,7 +30,7 @@ def check column: value_token.column, token: value_token, description: 'Check the tokens of each File resource instance for a mode parameter and if found, ' \ - 'record a warning if the value of that parameter is not a 4 digit octal value (0755) or a symbolic mode (\'o=rwx,g\+r\').', + 'record a warning if the value of that parameter is not a 4 digit octal value (0755) or a symbolic mode (\'o=rwx,g\+r\').', help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#file-modes', ) end diff --git a/lib/puppet-lint/plugins/check_resources/unquoted_file_mode.rb b/lib/puppet-lint/plugins/check_resources/unquoted_file_mode.rb index 9a0add99..8374745b 100644 --- a/lib/puppet-lint/plugins/check_resources/unquoted_file_mode.rb +++ b/lib/puppet-lint/plugins/check_resources/unquoted_file_mode.rb @@ -3,9 +3,9 @@ # not a quoted string. # # https://puppet.com/docs/puppet/latest/style_guide.html#file-modes -PuppetLint.new_check(:unquoted_file_mode) do - TOKEN_TYPES = Set[:NAME, :NUMBER] +TOKEN_TYPES = Set[:NAME, :NUMBER] +PuppetLint.new_check(:unquoted_file_mode) do def check resource_indexes.each do |resource| next unless resource[:type].value == 'file' || resource[:type].value == 'concat' @@ -23,8 +23,8 @@ def check line: value_token.line, column: value_token.column, token: value_token, - description: 'Check the tokens of each File resource instance for a mode parameter '\ - 'and if found, record a warning if the value of that parameter is not a quoted string.', + description: 'Check the tokens of each File resource instance for a mode parameter ' \ + 'and if found, record a warning if the value of that parameter is not a quoted string.', help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#file-modes', ) end diff --git a/lib/puppet-lint/plugins/check_strings/double_quoted_strings.rb b/lib/puppet-lint/plugins/check_strings/double_quoted_strings.rb index ddcbd059..4fc3e945 100644 --- a/lib/puppet-lint/plugins/check_strings/double_quoted_strings.rb +++ b/lib/puppet-lint/plugins/check_strings/double_quoted_strings.rb @@ -3,9 +3,9 @@ # each instance found. # # https://puppet.com/docs/puppet/latest/style_guide.html#quoting -PuppetLint.new_check(:double_quoted_strings) do - ESCAPE_CHAR_RE = %r{(\\\$|\\"|\\'|'|\r|\t|\\t|\\s|\n|\\n|\\\\)}.freeze +ESCAPE_CHAR_RE = %r{(\\\$|\\"|\\'|'|\r|\t|\\t|\\s|\n|\\n|\\\\)}.freeze +PuppetLint.new_check(:double_quoted_strings) do def check invalid_tokens = tokens.select do |token| token.type == :STRING && @@ -19,8 +19,8 @@ def check line: token.line, column: token.column, token: token, - description: 'Check the manifest tokens for any double quoted strings that don\'t '\ - 'contain any variables or common escape characters and record a warning for each instance found.', + description: 'Check the manifest tokens for any double quoted strings that don\'t ' \ + 'contain any variables or common escape characters and record a warning for each instance found.', help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#quoting', ) end diff --git a/lib/puppet-lint/plugins/check_strings/only_variable_string.rb b/lib/puppet-lint/plugins/check_strings/only_variable_string.rb index d74fddc1..063e1562 100644 --- a/lib/puppet-lint/plugins/check_strings/only_variable_string.rb +++ b/lib/puppet-lint/plugins/check_strings/only_variable_string.rb @@ -2,9 +2,9 @@ # a single variable only and record a warning for each instance found. # # https://puppet.com/docs/puppet/latest/style_guide.html#quoting -PuppetLint.new_check(:only_variable_string) do - VAR_TYPES = Set[:VARIABLE, :UNENC_VARIABLE] +VAR_TYPES = Set[:VARIABLE, :UNENC_VARIABLE] +PuppetLint.new_check(:only_variable_string) do def check tokens.each_with_index do |start_token, start_token_idx| next unless start_token.type == :DQPRE && start_token.value == '' @@ -20,9 +20,8 @@ def check eos_offset += 3 when :DQPOST if eos_token.value == '' - if eos_token.next_code_token && eos_token.next_code_token.type == :FARROW - break - end + break if eos_token.next_code_token && eos_token.next_code_token.type == :FARROW + notify( :warning, message: 'string containing only a variable', diff --git a/lib/puppet-lint/plugins/check_strings/quoted_booleans.rb b/lib/puppet-lint/plugins/check_strings/quoted_booleans.rb index 4d14338e..2c26a9c0 100644 --- a/lib/puppet-lint/plugins/check_strings/quoted_booleans.rb +++ b/lib/puppet-lint/plugins/check_strings/quoted_booleans.rb @@ -3,10 +3,10 @@ # found. # # No style guide reference -PuppetLint.new_check(:quoted_booleans) do - STRING_TYPES = Set[:STRING, :SSTRING] - BOOLEANS = Set['true', 'false'] +STRING_TYPES = Set[:STRING, :SSTRING] +BOOLEANS = Set['true', 'false'] +PuppetLint.new_check(:quoted_booleans) do def check invalid_tokens = tokens.select do |token| STRING_TYPES.include?(token.type) && BOOLEANS.include?(token.value) @@ -29,4 +29,4 @@ def fix(problem) problem[:token].type = problem[:token].value.upcase.to_sym end end -PuppetLint.configuration.send('disable_quoted_booleans') +PuppetLint.configuration.send(:disable_quoted_booleans) diff --git a/lib/puppet-lint/plugins/check_strings/single_quote_string_with_variables.rb b/lib/puppet-lint/plugins/check_strings/single_quote_string_with_variables.rb index 63da996b..aa269255 100644 --- a/lib/puppet-lint/plugins/check_strings/single_quote_string_with_variables.rb +++ b/lib/puppet-lint/plugins/check_strings/single_quote_string_with_variables.rb @@ -14,8 +14,8 @@ def check message: 'single quoted string containing a variable found', line: token.line, column: token.column, - description: 'Check the manifest tokens for any single quoted strings containing '\ - 'a enclosed variable and record an error for each instance found.', + description: 'Check the manifest tokens for any single quoted strings containing ' \ + 'a enclosed variable and record an error for each instance found.', help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#quoting', ) end diff --git a/lib/puppet-lint/plugins/check_strings/variables_not_enclosed.rb b/lib/puppet-lint/plugins/check_strings/variables_not_enclosed.rb index ac1faeb4..945cee0a 100644 --- a/lib/puppet-lint/plugins/check_strings/variables_not_enclosed.rb +++ b/lib/puppet-lint/plugins/check_strings/variables_not_enclosed.rb @@ -6,14 +6,14 @@ # found. # # https://puppet.com/docs/puppet/latest/style_guide.html#quoting -PuppetLint.new_check(:variables_not_enclosed) do - STRING_TOKEN_TYPES = Set[ - :DQMID, - :DQPOST, - :HEREDOC_MID, - :HEREDOC_POST, - ] +STRING_TOKEN_TYPES = Set[ + :DQMID, + :DQPOST, + :HEREDOC_MID, + :HEREDOC_POST, +] +PuppetLint.new_check(:variables_not_enclosed) do def check invalid_tokens = tokens.select do |token| token.type == :UNENC_VARIABLE @@ -74,6 +74,7 @@ def handle_variable_containing_dash(var_token) var_token.value = var_name return if str_token.nil? + str_token.value = "-#{text}#{str_token.value}" end diff --git a/lib/puppet-lint/plugins/check_variables/variable_contains_dash.rb b/lib/puppet-lint/plugins/check_variables/variable_contains_dash.rb index 32625f73..59d44b0a 100644 --- a/lib/puppet-lint/plugins/check_variables/variable_contains_dash.rb +++ b/lib/puppet-lint/plugins/check_variables/variable_contains_dash.rb @@ -2,16 +2,16 @@ # record a warning for each instance found. # # No style guide reference -PuppetLint.new_check(:variable_contains_dash) do - VARIABLE_DASH_TYPES = Set[:VARIABLE, :UNENC_VARIABLE] +VARIABLE_DASH_TYPES = Set[:VARIABLE, :UNENC_VARIABLE] +PuppetLint.new_check(:variable_contains_dash) do def check invalid_tokens = tokens.select do |token| VARIABLE_DASH_TYPES.include?(token.type) end invalid_tokens.each do |token| - next unless %r{-}.match?(token.value.gsub(%r{\[.+?\]}, '')) + next unless token.value.gsub(%r{\[.+?\]}, '').include?('-') notify( :warning, diff --git a/lib/puppet-lint/plugins/check_variables/variable_is_lowercase.rb b/lib/puppet-lint/plugins/check_variables/variable_is_lowercase.rb index 7f686807..0804f5a9 100644 --- a/lib/puppet-lint/plugins/check_variables/variable_is_lowercase.rb +++ b/lib/puppet-lint/plugins/check_variables/variable_is_lowercase.rb @@ -2,9 +2,9 @@ # letter and record a warning for each instance found. # # No style guide reference -PuppetLint.new_check(:variable_is_lowercase) do - VARIABLE_LOWERCASE_TYPES = Set[:VARIABLE, :UNENC_VARIABLE] +VARIABLE_LOWERCASE_TYPES = Set[:VARIABLE, :UNENC_VARIABLE] +PuppetLint.new_check(:variable_is_lowercase) do def check invalid_tokens = tokens.select do |token| VARIABLE_LOWERCASE_TYPES.include?(token.type) diff --git a/lib/puppet-lint/plugins/check_whitespace/140chars.rb b/lib/puppet-lint/plugins/check_whitespace/140chars.rb index 5f21cd17..bc63d095 100644 --- a/lib/puppet-lint/plugins/check_whitespace/140chars.rb +++ b/lib/puppet-lint/plugins/check_whitespace/140chars.rb @@ -10,6 +10,7 @@ def check result = PuppetLint::LineLengthCheck.check(idx + 1, line, 140) next if result.nil? + notify(*result) end end diff --git a/lib/puppet-lint/plugins/check_whitespace/80chars.rb b/lib/puppet-lint/plugins/check_whitespace/80chars.rb index 87321b64..e1f143fe 100644 --- a/lib/puppet-lint/plugins/check_whitespace/80chars.rb +++ b/lib/puppet-lint/plugins/check_whitespace/80chars.rb @@ -9,8 +9,9 @@ def check result = PuppetLint::LineLengthCheck.check(idx + 1, line, 80) next if result.nil? + notify(*result) end end end -PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.send(:disable_80chars) diff --git a/lib/puppet-lint/plugins/check_whitespace/arrow_alignment.rb b/lib/puppet-lint/plugins/check_whitespace/arrow_alignment.rb index cbaa42d5..d993db7c 100644 --- a/lib/puppet-lint/plugins/check_whitespace/arrow_alignment.rb +++ b/lib/puppet-lint/plugins/check_whitespace/arrow_alignment.rb @@ -2,9 +2,9 @@ # are not aligned with other arrows in that grouping. # # https://puppet.com/docs/puppet/latest/style_guide.html#spacing-indentation-and-whitespace -PuppetLint.new_check(:arrow_alignment) do - COMMENT_TYPES = Set[:COMMENT, :SLASH_COMMENT, :MLCOMMENT] +COMMENT_TYPES = Set[:COMMENT, :SLASH_COMMENT, :MLCOMMENT] +PuppetLint.new_check(:arrow_alignment) do def check resource_indexes.each do |res_idx| arrow_column = [0] @@ -24,7 +24,8 @@ def check next if resource_tokens[first_arrow].line == resource_tokens[last_arrow].line resource_tokens.each do |token| - if token.type == :FARROW + case token.type + when :FARROW param_token = token.prev_code_token if param_token.type == :DQPOST @@ -54,17 +55,15 @@ def check this_arrow_column += 1 end - if arrow_column[level_idx] < this_arrow_column - arrow_column[level_idx] = this_arrow_column - end + arrow_column[level_idx] = this_arrow_column if arrow_column[level_idx] < this_arrow_column (level_tokens[level_idx] ||= []) << token - elsif token.type == :LBRACE + when :LBRACE level_idx += 1 arrow_column << 0 level_tokens[level_idx] ||= [] param_column << nil - elsif token.type == :RBRACE || token.type == :SEMIC + when :RBRACE, :SEMIC if (level_tokens[level_idx] ||= []).map(&:line).uniq.length > 1 level_tokens[level_idx].each do |arrow_tok| next if arrow_tok.column == arrow_column[level_idx] || level_tokens[level_idx].size == 1 @@ -117,7 +116,8 @@ def fix(problem) new_ws_len += (problem[:arrow_column] - problem[:token].column) end - raise PuppetLint::NoFix if new_ws_len < 0 + raise PuppetLint::NoFix if new_ws_len.negative? + new_ws = ' ' * new_ws_len if problem[:token].prev_token.type == :WHITESPACE diff --git a/lib/puppet-lint/plugins/check_whitespace/hard_tabs.rb b/lib/puppet-lint/plugins/check_whitespace/hard_tabs.rb index 8e8e54c8..e6fd2632 100644 --- a/lib/puppet-lint/plugins/check_whitespace/hard_tabs.rb +++ b/lib/puppet-lint/plugins/check_whitespace/hard_tabs.rb @@ -2,9 +2,9 @@ # characters and record an error for each instance found. # # https://puppet.com/docs/puppet/latest/style_guide.html#spacing-indentation-and-whitespace -PuppetLint.new_check(:hard_tabs) do - WHITESPACE_TYPES = Set[:INDENT, :WHITESPACE] +WHITESPACE_TYPES = Set[:INDENT, :WHITESPACE] +PuppetLint.new_check(:hard_tabs) do def check invalid_tokens = tokens.select do |token| WHITESPACE_TYPES.include?(token.type) && token.value.include?("\t") diff --git a/lib/puppet-lint/plugins/check_whitespace/line_length.rb b/lib/puppet-lint/plugins/check_whitespace/line_length.rb index 57d14de4..88c6536a 100644 --- a/lib/puppet-lint/plugins/check_whitespace/line_length.rb +++ b/lib/puppet-lint/plugins/check_whitespace/line_length.rb @@ -18,12 +18,12 @@ def self.check(line_number, content, character_count) [ :warning, - message: "line has more than #{character_count} characters", - line: line_number, - column: character_count, - description: 'Test the raw manifest string for lines containing more than #{character_count} characters and record a warning for each instance found. '\ - 'The only exceptions to this rule are lines containing URLs and template() calls which would hurt readability if split.', - help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#spacing-indentation-and-whitespace', + { message: "line has more than #{character_count} characters", + line: line_number, + column: character_count, + description: "Test the raw manifest string for lines containing more than #{character_count} characters and record a warning for each instance found. " \ + 'The only exceptions to this rule are lines containing URLs and template() calls which would hurt readability if split.', + help_uri: 'https://puppet.com/docs/puppet/latest/style_guide.html#spacing-indentation-and-whitespace' }, ] end end diff --git a/lib/puppet-lint/plugins/legacy_facts/legacy_facts.rb b/lib/puppet-lint/plugins/legacy_facts/legacy_facts.rb index 6fad162e..dd63656a 100644 --- a/lib/puppet-lint/plugins/legacy_facts/legacy_facts.rb +++ b/lib/puppet-lint/plugins/legacy_facts/legacy_facts.rb @@ -6,111 +6,111 @@ # # This plugin was adopted in to puppet-lint from https://github.com/mmckinst/puppet-lint-legacy_facts-check # Thanks to @mmckinst, @seanmil, @rodjek, @baurmatt, @bart2 and @joshcooper for the original work. -PuppetLint.new_check(:legacy_facts) do - LEGACY_FACTS_VAR_TYPES = Set[:VARIABLE, :UNENC_VARIABLE] - - # These facts that can't be converted to new facts. - UNCONVERTIBLE_FACTS = ['memoryfree_mb', 'memorysize_mb', 'swapfree_mb', - 'swapsize_mb', 'blockdevices', 'interfaces', 'zones', - 'sshfp_dsa', 'sshfp_ecdsa', 'sshfp_ed25519', - 'sshfp_rsa'].freeze - - # These facts will depend on how a system is set up and can't just be - # enumerated like the EASY_FACTS below. - # - # For example a server might have two block devices named 'sda' and 'sdb' so - # there would be a $blockdeivce_sda_vendor and $blockdeivce_sdb_vendor fact - # for each device. Or it could have 26 block devices going all the way up to - # 'sdz'. There is no way to know what the possibilities are so we have to use - # a regex to match them. - REGEX_FACTS = [%r{^blockdevice_(?.*)_(?model|size|vendor)$}, - %r{^(?ipaddress|ipaddress6|macaddress|mtu|netmask|netmask6|network|network6)_(?.*)$}, - %r{^processor(?[0-9]+)$}, - %r{^sp_(?.*)$}, - %r{^ssh(?dsa|ecdsa|ed25519|rsa)key$}, - %r{^ldom_(?.*)$}, - %r{^zone_(?.*)_(?brand|iptype|name|uuid|id|path|status)$}].freeze - - # These facts have a one to one correlation between a legacy fact and a new - # structured fact. - EASY_FACTS = { - 'architecture' => "facts['os']['architecture']", - 'augeasversion' => "facts['augeas']['version']", - 'bios_release_date' => "facts['dmi']['bios']['release_date']", - 'bios_vendor' => "facts['dmi']['bios']['vendor']", - 'bios_version' => "facts['dmi']['bios']['version']", - 'boardassettag' => "facts['dmi']['board']['asset_tag']", - 'boardmanufacturer' => "facts['dmi']['board']['manufacturer']", - 'boardproductname' => "facts['dmi']['board']['product']", - 'boardserialnumber' => "facts['dmi']['board']['serial_number']", - 'chassisassettag' => "facts['dmi']['chassis']['asset_tag']", - 'chassistype' => "facts['dmi']['chassis']['type']", - 'domain' => "facts['networking']['domain']", - 'fqdn' => "facts['networking']['fqdn']", - 'gid' => "facts['identity']['group']", - 'hardwareisa' => "facts['processors']['isa']", - 'hardwaremodel' => "facts['os']['hardware']", - 'hostname' => "facts['networking']['hostname']", - 'id' => "facts['identity']['user']", - 'ipaddress' => "facts['networking']['ip']", - 'ipaddress6' => "facts['networking']['ip6']", - 'lsbdistcodename' => "facts['os']['distro']['codename']", - 'lsbdistdescription' => "facts['os']['distro']['description']", - 'lsbdistid' => "facts['os']['distro']['id']", - 'lsbdistrelease' => "facts['os']['distro']['release']['full']", - 'lsbmajdistrelease' => "facts['os']['distro']['release']['major']", - 'lsbminordistrelease' => "facts['os']['distro']['release']['minor']", - 'lsbrelease' => "facts['os']['distro']['release']['specification']", - 'macaddress' => "facts['networking']['mac']", - 'macosx_buildversion' => "facts['os']['macosx']['build']", - 'macosx_productname' => "facts['os']['macosx']['product']", - 'macosx_productversion' => "facts['os']['macosx']['version']['full']", - 'macosx_productversion_major' => "facts['os']['macosx']['version']['major']", - 'macosx_productversion_minor' => "facts['os']['macosx']['version']['minor']", - 'manufacturer' => "facts['dmi']['manufacturer']", - 'memoryfree' => "facts['memory']['system']['available']", - 'memorysize' => "facts['memory']['system']['total']", - 'netmask' => "facts['networking']['netmask']", - 'netmask6' => "facts['networking']['netmask6']", - 'network' => "facts['networking']['network']", - 'network6' => "facts['networking']['network6']", - 'operatingsystem' => "facts['os']['name']", - 'operatingsystemmajrelease' => "facts['os']['release']['major']", - 'operatingsystemrelease' => "facts['os']['release']['full']", - 'osfamily' => "facts['os']['family']", - 'physicalprocessorcount' => "facts['processors']['physicalcount']", - 'processorcount' => "facts['processors']['count']", - 'productname' => "facts['dmi']['product']['name']", - 'rubyplatform' => "facts['ruby']['platform']", - 'rubysitedir' => "facts['ruby']['sitedir']", - 'rubyversion' => "facts['ruby']['version']", - 'selinux' => "facts['os']['selinux']['enabled']", - 'selinux_config_mode' => "facts['os']['selinux']['config_mode']", - 'selinux_config_policy' => "facts['os']['selinux']['config_policy']", - 'selinux_current_mode' => "facts['os']['selinux']['current_mode']", - 'selinux_enforced' => "facts['os']['selinux']['enforced']", - 'selinux_policyversion' => "facts['os']['selinux']['policy_version']", - 'serialnumber' => "facts['dmi']['product']['serial_number']", - 'swapencrypted' => "facts['memory']['swap']['encrypted']", - 'swapfree' => "facts['memory']['swap']['available']", - 'swapsize' => "facts['memory']['swap']['total']", - 'system32' => "facts['os']['windows']['system32']", - 'uptime' => "facts['system_uptime']['uptime']", - 'uptime_days' => "facts['system_uptime']['days']", - 'uptime_hours' => "facts['system_uptime']['hours']", - 'uptime_seconds' => "facts['system_uptime']['seconds']", - 'uuid' => "facts['dmi']['product']['uuid']", - 'xendomains' => "facts['xen']['domains']", - 'zonename' => "facts['solaris_zones']['current']", - }.freeze - - # A list of valid hash key token types - HASH_KEY_TYPES = Set[ - :STRING, # Double quoted string - :SSTRING, # Single quoted string - :NAME, # Unquoted single word - ].freeze +LEGACY_FACTS_VAR_TYPES = Set[:VARIABLE, :UNENC_VARIABLE] + +# These facts that can't be converted to new facts. +UNCONVERTIBLE_FACTS = ['memoryfree_mb', 'memorysize_mb', 'swapfree_mb', + 'swapsize_mb', 'blockdevices', 'interfaces', 'zones', + 'sshfp_dsa', 'sshfp_ecdsa', 'sshfp_ed25519', + 'sshfp_rsa'].freeze + +# These facts will depend on how a system is set up and can't just be +# enumerated like the EASY_FACTS below. +# +# For example a server might have two block devices named 'sda' and 'sdb' so +# there would be a $blockdeivce_sda_vendor and $blockdeivce_sdb_vendor fact +# for each device. Or it could have 26 block devices going all the way up to +# 'sdz'. There is no way to know what the possibilities are so we have to use +# a regex to match them. +REGEX_FACTS = [%r{^blockdevice_(?.*)_(?model|size|vendor)$}, + %r{^(?ipaddress|ipaddress6|macaddress|mtu|netmask|netmask6|network|network6)_(?.*)$}, + %r{^processor(?[0-9]+)$}, + %r{^sp_(?.*)$}, + %r{^ssh(?dsa|ecdsa|ed25519|rsa)key$}, + %r{^ldom_(?.*)$}, + %r{^zone_(?.*)_(?brand|iptype|name|uuid|id|path|status)$}].freeze + +# These facts have a one to one correlation between a legacy fact and a new +# structured fact. +EASY_FACTS = { + 'architecture' => "facts['os']['architecture']", + 'augeasversion' => "facts['augeas']['version']", + 'bios_release_date' => "facts['dmi']['bios']['release_date']", + 'bios_vendor' => "facts['dmi']['bios']['vendor']", + 'bios_version' => "facts['dmi']['bios']['version']", + 'boardassettag' => "facts['dmi']['board']['asset_tag']", + 'boardmanufacturer' => "facts['dmi']['board']['manufacturer']", + 'boardproductname' => "facts['dmi']['board']['product']", + 'boardserialnumber' => "facts['dmi']['board']['serial_number']", + 'chassisassettag' => "facts['dmi']['chassis']['asset_tag']", + 'chassistype' => "facts['dmi']['chassis']['type']", + 'domain' => "facts['networking']['domain']", + 'fqdn' => "facts['networking']['fqdn']", + 'gid' => "facts['identity']['group']", + 'hardwareisa' => "facts['processors']['isa']", + 'hardwaremodel' => "facts['os']['hardware']", + 'hostname' => "facts['networking']['hostname']", + 'id' => "facts['identity']['user']", + 'ipaddress' => "facts['networking']['ip']", + 'ipaddress6' => "facts['networking']['ip6']", + 'lsbdistcodename' => "facts['os']['distro']['codename']", + 'lsbdistdescription' => "facts['os']['distro']['description']", + 'lsbdistid' => "facts['os']['distro']['id']", + 'lsbdistrelease' => "facts['os']['distro']['release']['full']", + 'lsbmajdistrelease' => "facts['os']['distro']['release']['major']", + 'lsbminordistrelease' => "facts['os']['distro']['release']['minor']", + 'lsbrelease' => "facts['os']['distro']['release']['specification']", + 'macaddress' => "facts['networking']['mac']", + 'macosx_buildversion' => "facts['os']['macosx']['build']", + 'macosx_productname' => "facts['os']['macosx']['product']", + 'macosx_productversion' => "facts['os']['macosx']['version']['full']", + 'macosx_productversion_major' => "facts['os']['macosx']['version']['major']", + 'macosx_productversion_minor' => "facts['os']['macosx']['version']['minor']", + 'manufacturer' => "facts['dmi']['manufacturer']", + 'memoryfree' => "facts['memory']['system']['available']", + 'memorysize' => "facts['memory']['system']['total']", + 'netmask' => "facts['networking']['netmask']", + 'netmask6' => "facts['networking']['netmask6']", + 'network' => "facts['networking']['network']", + 'network6' => "facts['networking']['network6']", + 'operatingsystem' => "facts['os']['name']", + 'operatingsystemmajrelease' => "facts['os']['release']['major']", + 'operatingsystemrelease' => "facts['os']['release']['full']", + 'osfamily' => "facts['os']['family']", + 'physicalprocessorcount' => "facts['processors']['physicalcount']", + 'processorcount' => "facts['processors']['count']", + 'productname' => "facts['dmi']['product']['name']", + 'rubyplatform' => "facts['ruby']['platform']", + 'rubysitedir' => "facts['ruby']['sitedir']", + 'rubyversion' => "facts['ruby']['version']", + 'selinux' => "facts['os']['selinux']['enabled']", + 'selinux_config_mode' => "facts['os']['selinux']['config_mode']", + 'selinux_config_policy' => "facts['os']['selinux']['config_policy']", + 'selinux_current_mode' => "facts['os']['selinux']['current_mode']", + 'selinux_enforced' => "facts['os']['selinux']['enforced']", + 'selinux_policyversion' => "facts['os']['selinux']['policy_version']", + 'serialnumber' => "facts['dmi']['product']['serial_number']", + 'swapencrypted' => "facts['memory']['swap']['encrypted']", + 'swapfree' => "facts['memory']['swap']['available']", + 'swapsize' => "facts['memory']['swap']['total']", + 'system32' => "facts['os']['windows']['system32']", + 'uptime' => "facts['system_uptime']['uptime']", + 'uptime_days' => "facts['system_uptime']['days']", + 'uptime_hours' => "facts['system_uptime']['hours']", + 'uptime_seconds' => "facts['system_uptime']['seconds']", + 'uuid' => "facts['dmi']['product']['uuid']", + 'xendomains' => "facts['xen']['domains']", + 'zonename' => "facts['solaris_zones']['current']" +}.freeze + +# A list of valid hash key token types +HASH_KEY_TYPES = Set[ + :STRING, # Double quoted string + :SSTRING, # Single quoted string + :NAME, # Unquoted single word +].freeze +PuppetLint.new_check(:legacy_facts) do def check tokens.select { |x| LEGACY_FACTS_VAR_TYPES.include?(x.type) }.each do |token| fact_name = '' @@ -137,12 +137,13 @@ def check end next unless EASY_FACTS.include?(fact_name) || UNCONVERTIBLE_FACTS.include?(fact_name) || fact_name.match(Regexp.union(REGEX_FACTS)) + notify :warning, { message: "legacy fact '#{fact_name}'", line: token.line, column: token.column, token: token, - fact_name: fact_name, + fact_name: fact_name } end end diff --git a/lib/puppet-lint/plugins/top_scope_facts/top_scope_facts.rb b/lib/puppet-lint/plugins/top_scope_facts/top_scope_facts.rb index e2de194f..e14a1223 100644 --- a/lib/puppet-lint/plugins/top_scope_facts/top_scope_facts.rb +++ b/lib/puppet-lint/plugins/top_scope_facts/top_scope_facts.rb @@ -13,8 +13,9 @@ # # This plugin was adopted in to puppet-lint from https://github.com/mmckinst/puppet-lint-top_scope_facts-check # Thanks to @mmckinst, @seanmil and @alexjfisher for the original work. +TOP_SCOPE_FACTS_VAR_TYPES = Set[:VARIABLE, :UNENC_VARIABLE] + PuppetLint.new_check(:top_scope_facts) do - TOP_SCOPE_FACTS_VAR_TYPES = Set[:VARIABLE, :UNENC_VARIABLE] def check whitelist = ['trusted', 'facts'] + (PuppetLint.configuration.top_scope_variables || []) whitelist = whitelist.join('|') @@ -27,7 +28,7 @@ def check message: 'top scope fact instead of facts hash', line: token.line, column: token.column, - token: token, + token: token } end end diff --git a/lib/puppet-lint/report/codeclimate.rb b/lib/puppet-lint/report/codeclimate.rb index 56f31bb3..8a922938 100644 --- a/lib/puppet-lint/report/codeclimate.rb +++ b/lib/puppet-lint/report/codeclimate.rb @@ -3,6 +3,7 @@ require 'digest' require 'json' +# rubocop:disable Style/ClassAndModuleChildren class PuppetLint::Report # Formats problems and writes them to a file as a code climate compatible report. class CodeClimateReporter @@ -29,9 +30,9 @@ def self.write_report_file(problems, report_file) path: message[:path], lines: { begin: message[:line], - end: message[:line], + end: message[:line] } - }, + } } issue[:fingerprint] = Digest::MD5.hexdigest(Marshal.dump(issue)) diff --git a/lib/puppet-lint/report/github.rb b/lib/puppet-lint/report/github.rb index b6964c48..c7afc07c 100644 --- a/lib/puppet-lint/report/github.rb +++ b/lib/puppet-lint/report/github.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# rubocop:disable Style/ClassAndModuleChildren class PuppetLint::Report # This formatter formats report data as GitHub Workflow commands resulting # in GitHub check annotations when run within GitHub Actions. diff --git a/lib/puppet-lint/tasks/puppet-lint.rb b/lib/puppet-lint/tasks/puppet-lint.rb index cd0e2524..bda63e80 100644 --- a/lib/puppet-lint/tasks/puppet-lint.rb +++ b/lib/puppet-lint/tasks/puppet-lint.rb @@ -12,24 +12,12 @@ # # require 'puppet-lint' # PuppetLint::RakeTask.new -class PuppetLint::RakeTask < ::Rake::TaskLib +class PuppetLint::RakeTask < Rake::TaskLib include ::Rake::DSL if defined?(::Rake::DSL) DEFAULT_PATTERN = '**/*.pp'.freeze - attr_accessor :name - attr_accessor :pattern - attr_accessor :ignore_paths - attr_accessor :with_filename - attr_accessor :disable_checks - attr_accessor :only_checks - attr_accessor :fail_on_warnings - attr_accessor :error_level - attr_accessor :log_format - attr_accessor :with_context - attr_accessor :fix - attr_accessor :show_ignored - attr_accessor :relative + attr_accessor :name, :pattern, :ignore_paths, :with_filename, :disable_checks, :only_checks, :fail_on_warnings, :error_level, :log_format, :with_context, :fix, :show_ignored, :relative # Public: Initialise a new PuppetLint::RakeTask. # @@ -80,13 +68,9 @@ def define(args, &task_block) PuppetLint.configuration.send("#{config}=".to_sym, value) unless value.nil? end - if PuppetLint.configuration.ignore_paths && @ignore_paths.empty? - @ignore_paths = PuppetLint.configuration.ignore_paths - end + @ignore_paths = PuppetLint.configuration.ignore_paths if PuppetLint.configuration.ignore_paths && @ignore_paths.empty? - if PuppetLint.configuration.pattern - @pattern = PuppetLint.configuration.pattern - end + @pattern = PuppetLint.configuration.pattern if PuppetLint.configuration.pattern RakeFileUtils.send(:verbose, true) do linter = PuppetLint.new @@ -97,18 +81,15 @@ def define(args, &task_block) matched_files.to_a.each do |puppet_file| next unless File.file?(puppet_file) + linter.file = puppet_file linter.run all_problems << linter.print_problems - if PuppetLint.configuration.fix && linter.problems.none? { |e| e[:check] == :syntax } - IO.write(puppet_file, linter.manifest) - end + File.write(puppet_file, linter.manifest) if PuppetLint.configuration.fix && linter.problems.none? { |e| e[:check] == :syntax } end - if PuppetLint.configuration.codeclimate_report_file - PuppetLint::Report::CodeClimateReporter.write_report_file(all_problems, PuppetLint.configuration.codeclimate_report_file) - end + PuppetLint::Report::CodeClimateReporter.write_report_file(all_problems, PuppetLint.configuration.codeclimate_report_file) if PuppetLint.configuration.codeclimate_report_file abort if linter.errors? || ( linter.warnings? && PuppetLint.configuration.fail_on_warnings diff --git a/lib/puppet-lint/tasks/release_test.rb b/lib/puppet-lint/tasks/release_test.rb index b908fd72..3d6057b5 100644 --- a/lib/puppet-lint/tasks/release_test.rb +++ b/lib/puppet-lint/tasks/release_test.rb @@ -27,7 +27,7 @@ def run_cmd(message, *cmd) [output.strip, status.success?] end -def with_puppet_lint_head +def with_puppet_lint_head(&block) print(' Updating Gemfile to use puppet-lint HEAD... ') buffer = Parser::Source::Buffer.new('Gemfile') @@ -49,7 +49,7 @@ def with_puppet_lint_head puts 'Done' - Bundler.with_clean_env { yield } + Bundler.with_clean_env(&block) run_cmd('Restoring Gemfile', 'git', 'checkout', '--', 'Gemfile') end @@ -58,9 +58,9 @@ def with_puppet_lint_head branch = if ENV['GITHUB_REF'] ENV['GITHUB_REF'] elsif ENV['APPVEYOR'] - ENV['APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH'] + ENV.fetch('APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH', nil) elsif ENV['TRAVIS'] - ENV['TRAVIS_PULL_REQUEST_BRANCH'] + ENV.fetch('TRAVIS_PULL_REQUEST_BRANCH', nil) else false end diff --git a/puppet-lint.gemspec b/puppet-lint.gemspec index bbc3dcfb..64ba7d85 100644 --- a/puppet-lint.gemspec +++ b/puppet-lint.gemspec @@ -1,4 +1,4 @@ -$LOAD_PATH.push(File.expand_path('../lib', __FILE__)) +$LOAD_PATH.push(File.expand_path('lib', __dir__)) require 'puppet-lint/version' Gem::Specification.new do |spec| @@ -32,5 +32,5 @@ Gem::Specification.new do |spec| ] spec.license = 'MIT' - spec.required_ruby_version = Gem::Requirement.new('>= 2.5'.freeze) + spec.required_ruby_version = Gem::Requirement.new('>= 2.7'.freeze) end diff --git a/rubocop_baseline.yml b/rubocop_baseline.yml index e47cbcb1..4cf2aa0f 100644 --- a/rubocop_baseline.yml +++ b/rubocop_baseline.yml @@ -3,6 +3,9 @@ require: - rubocop-performance - rubocop-rspec AllCops: + NewCops: enable + ExtraDetails: true + DisplayStyleGuide: true TargetRubyVersion: '2.7' DisplayCopNames: true SuggestExtensions: false @@ -78,443 +81,3 @@ Style/Documentation: - spec/**/* Style/WordArray: EnforcedStyle: brackets -Performance/AncestorsInclude: - Enabled: true -Performance/BigDecimalWithNumericArgument: - Enabled: true -Performance/BlockGivenWithExplicitBlock: - Enabled: true -Performance/CaseWhenSplat: - Enabled: true -Performance/ConstantRegexp: - Enabled: true -Performance/MethodObjectAsBlock: - Enabled: true -Performance/RedundantSortBlock: - Enabled: true -Performance/RedundantStringChars: - Enabled: true -Performance/ReverseFirst: - Enabled: true -Performance/SortReverse: - Enabled: true -Performance/Squeeze: - Enabled: true -Performance/StringInclude: - Enabled: true -Performance/Sum: - Enabled: true -Style/CollectionMethods: - Enabled: true -Style/MethodCalledOnDoEndBlock: - Enabled: true -Style/StringMethods: - Enabled: true -Bundler/InsecureProtocolSource: - Enabled: false -Gemspec/DuplicatedAssignment: - Enabled: false -Gemspec/OrderedDependencies: - Enabled: false -Gemspec/RequiredRubyVersion: - Enabled: false -Gemspec/RubyVersionGlobalsUsage: - Enabled: false -Layout/ArgumentAlignment: - Enabled: false -Layout/BeginEndAlignment: - Enabled: false -Layout/ClosingHeredocIndentation: - Enabled: false -Layout/EmptyComment: - Enabled: false -Layout/EmptyLineAfterGuardClause: - Enabled: false -Layout/EmptyLinesAroundArguments: - Enabled: false -Layout/EmptyLinesAroundAttributeAccessor: - Enabled: false -Layout/EndOfLine: - Enabled: false -Layout/FirstArgumentIndentation: - Enabled: false -Layout/HashAlignment: - Enabled: false -Layout/HeredocIndentation: - Enabled: false -Layout/LeadingEmptyLines: - Enabled: false -Layout/SpaceAroundMethodCallOperator: - Enabled: false -Layout/SpaceInsideArrayLiteralBrackets: - Enabled: false -Layout/SpaceInsideReferenceBrackets: - Enabled: false -Lint/BigDecimalNew: - Enabled: false -Lint/BooleanSymbol: - Enabled: false -Lint/ConstantDefinitionInBlock: - Enabled: false -Lint/DeprecatedOpenSSLConstant: - Enabled: false -Lint/DisjunctiveAssignmentInConstructor: - Enabled: false -Lint/DuplicateElsifCondition: - Enabled: false -Lint/DuplicateRequire: - Enabled: false -Lint/DuplicateRescueException: - Enabled: false -Lint/EmptyConditionalBody: - Enabled: false -Lint/EmptyFile: - Enabled: false -Lint/ErbNewArguments: - Enabled: false -Lint/FloatComparison: - Enabled: false -Lint/HashCompareByIdentity: - Enabled: false -Lint/IdentityComparison: - Enabled: false -Lint/InterpolationCheck: - Enabled: false -Lint/MissingCopEnableDirective: - Enabled: false -Lint/MixedRegexpCaptureTypes: - Enabled: false -Lint/NestedPercentLiteral: - Enabled: false -Lint/NonDeterministicRequireOrder: - Enabled: false -Lint/OrderedMagicComments: - Enabled: false -Lint/OutOfRangeRegexpRef: - Enabled: false -Lint/RaiseException: - Enabled: false -Lint/RedundantCopEnableDirective: - Enabled: false -Lint/RedundantRequireStatement: - Enabled: false -Lint/RedundantSafeNavigation: - Enabled: false -Lint/RedundantWithIndex: - Enabled: false -Lint/RedundantWithObject: - Enabled: false -Lint/RegexpAsCondition: - Enabled: false -Lint/ReturnInVoidContext: - Enabled: false -Lint/SafeNavigationConsistency: - Enabled: false -Lint/SafeNavigationWithEmpty: - Enabled: false -Lint/SelfAssignment: - Enabled: false -Lint/SendWithMixinArgument: - Enabled: false -Lint/ShadowedArgument: - Enabled: false -Lint/StructNewOverride: - Enabled: false -Lint/ToJSON: - Enabled: false -Lint/TopLevelReturnWithArgument: - Enabled: false -Lint/TrailingCommaInAttributeDeclaration: - Enabled: false -Lint/UnreachableLoop: - Enabled: false -Lint/UriEscapeUnescape: - Enabled: false -Lint/UriRegexp: - Enabled: false -Lint/UselessMethodDefinition: - Enabled: false -Lint/UselessTimes: - Enabled: false -Metrics/AbcSize: - Enabled: false -Metrics/BlockLength: - Enabled: false -Metrics/BlockNesting: - Enabled: false -Metrics/ClassLength: - Enabled: false -Metrics/CyclomaticComplexity: - Enabled: false -Metrics/MethodLength: - Enabled: false -Metrics/ModuleLength: - Enabled: false -Metrics/ParameterLists: - Enabled: false -Metrics/PerceivedComplexity: - Enabled: false -Migration/DepartmentName: - Enabled: false -Naming/AccessorMethodName: - Enabled: false -Naming/BlockParameterName: - Enabled: false -Naming/HeredocDelimiterCase: - Enabled: false -Naming/HeredocDelimiterNaming: - Enabled: false -Naming/MemoizedInstanceVariableName: - Enabled: false -Naming/MethodParameterName: - Enabled: false -Naming/RescuedExceptionsVariableName: - Enabled: false -Naming/VariableNumber: - Enabled: false -Performance/BindCall: - Enabled: false -Performance/DeletePrefix: - Enabled: false -Performance/DeleteSuffix: - Enabled: false -Performance/InefficientHashSearch: - Enabled: false -Performance/UnfreezeString: - Enabled: false -Performance/UriDefaultParser: - Enabled: false -RSpec/Be: - Enabled: false -RSpec/Capybara/CurrentPathExpectation: - Enabled: false -RSpec/Capybara/FeatureMethods: - Enabled: false -RSpec/Capybara/VisibilityMatcher: - Enabled: false -RSpec/ContextMethod: - Enabled: false -RSpec/ContextWording: - Enabled: false -RSpec/DescribeClass: - Enabled: false -RSpec/EmptyHook: - Enabled: false -RSpec/EmptyLineAfterExample: - Enabled: false -RSpec/EmptyLineAfterExampleGroup: - Enabled: false -RSpec/EmptyLineAfterHook: - Enabled: false -RSpec/ExampleLength: - Enabled: false -RSpec/ExampleWithoutDescription: - Enabled: false -RSpec/ExpectChange: - Enabled: false -RSpec/ExpectInHook: - Enabled: false -RSpec/FactoryBot/AttributeDefinedStatically: - Enabled: false -RSpec/FactoryBot/CreateList: - Enabled: false -RSpec/FactoryBot/FactoryClassName: - Enabled: false -RSpec/HooksBeforeExamples: - Enabled: false -RSpec/ImplicitBlockExpectation: - Enabled: false -RSpec/ImplicitSubject: - Enabled: false -RSpec/LeakyConstantDeclaration: - Enabled: false -RSpec/LetBeforeExamples: - Enabled: false -RSpec/MissingExampleGroupArgument: - Enabled: false -RSpec/MultipleExpectations: - Enabled: false -RSpec/MultipleMemoizedHelpers: - Enabled: false -RSpec/MultipleSubjects: - Enabled: false -RSpec/NestedGroups: - Enabled: false -RSpec/PredicateMatcher: - Enabled: false -RSpec/ReceiveCounts: - Enabled: false -RSpec/ReceiveNever: - Enabled: false -RSpec/RepeatedExampleGroupBody: - Enabled: false -RSpec/RepeatedExampleGroupDescription: - Enabled: false -RSpec/RepeatedIncludeExample: - Enabled: false -RSpec/ReturnFromStub: - Enabled: false -RSpec/SharedExamples: - Enabled: false -RSpec/StubbedMock: - Enabled: false -RSpec/UnspecifiedException: - Enabled: false -RSpec/VariableDefinition: - Enabled: false -RSpec/VoidExpect: - Enabled: false -RSpec/Yield: - Enabled: false -Security/Open: - Enabled: false -Style/AccessModifierDeclarations: - Enabled: false -Style/AccessorGrouping: - Enabled: false -Style/AsciiComments: - Enabled: false -Style/BisectedAttrAccessor: - Enabled: false -Style/CaseLikeIf: - Enabled: false -Style/ClassEqualityComparison: - Enabled: false -Style/ColonMethodDefinition: - Enabled: false -Style/CombinableLoops: - Enabled: false -Style/CommentedKeyword: - Enabled: false -Style/Dir: - Enabled: false -Style/DoubleCopDisableDirective: - Enabled: false -Style/EmptyBlockParameter: - Enabled: false -Style/EmptyLambdaParameter: - Enabled: false -Style/Encoding: - Enabled: false -Style/EvalWithLocation: - Enabled: false -Style/ExpandPathArguments: - Enabled: false -Style/ExplicitBlockArgument: - Enabled: false -Style/ExponentialNotation: - Enabled: false -Style/FloatDivision: - Enabled: false -Style/FrozenStringLiteralComment: - Enabled: false -Style/GlobalStdStream: - Enabled: false -Style/HashAsLastArrayItem: - Enabled: false -Style/HashLikeCase: - Enabled: false -Style/HashTransformKeys: - Enabled: false -Style/HashTransformValues: - Enabled: false -Style/IfUnlessModifier: - Enabled: false -Style/KeywordParametersOrder: - Enabled: false -Style/MinMax: - Enabled: false -Style/MixinUsage: - Enabled: false -Style/MultilineWhenThen: - Enabled: false -Style/NegatedUnless: - Enabled: false -Style/NumericPredicate: - Enabled: false -Style/OptionalBooleanParameter: - Enabled: false -Style/OrAssignment: - Enabled: false -Style/RandomWithOffset: - Enabled: false -Style/RedundantAssignment: - Enabled: false -Style/RedundantCondition: - Enabled: false -Style/RedundantConditional: - Enabled: false -Style/RedundantFetchBlock: - Enabled: false -Style/RedundantFileExtensionInRequire: - Enabled: false -Style/RedundantRegexpCharacterClass: - Enabled: false -Style/RedundantRegexpEscape: - Enabled: false -Style/RedundantSelfAssignment: - Enabled: false -Style/RedundantSort: - Enabled: false -Style/RescueStandardError: - Enabled: false -Style/SingleArgumentDig: - Enabled: false -Style/SlicingWithRange: - Enabled: false -Style/SoleNestedConditional: - Enabled: false -Style/StderrPuts: - Enabled: false -Style/StringConcatenation: - Enabled: false -Style/Strip: - Enabled: false -Style/SymbolProc: - Enabled: false -Style/TrailingBodyOnClass: - Enabled: false -Style/TrailingBodyOnMethodDefinition: - Enabled: false -Style/TrailingBodyOnModule: - Enabled: false -Style/TrailingCommaInHashLiteral: - Enabled: false -Style/TrailingMethodEndStatement: - Enabled: false -Style/UnpackFirst: - Enabled: false -Lint/DuplicateBranch: - Enabled: false -Lint/DuplicateRegexpCharacterClassElement: - Enabled: false -Lint/EmptyBlock: - Enabled: false -Lint/EmptyClass: - Enabled: false -Lint/NoReturnInBeginEndBlocks: - Enabled: false -Lint/ToEnumArguments: - Enabled: false -Lint/UnexpectedBlockArity: - Enabled: false -Lint/UnmodifiedReduceAccumulator: - Enabled: false -Performance/CollectionLiteralInLoop: - Enabled: false -Style/ArgumentsForwarding: - Enabled: false -Style/CollectionCompact: - Enabled: false -Style/DocumentDynamicEvalDefinition: - Enabled: false -Style/NegatedIfElseCondition: - Enabled: false -Style/NilLambda: - Enabled: false -Style/RedundantArgument: - Enabled: false -Style/SwapValues: - Enabled: false -RSpec/FilePath: - Enabled: false diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 695e35f7..a8ff3314 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -23,8 +23,8 @@ module RSpec::LintExampleGroup class HaveProblem def initialize(method, message) @expected_problem = { - kind: method.to_s.gsub(%r{\Acontain_}, '').to_sym, - message: message, + kind: method.to_s.delete_prefix('contain_').to_sym, + message: message } @description = ["contain a #{@expected_problem[:kind]}"] end @@ -100,6 +100,7 @@ def failure_message_when_negated def method_missing(method, *args, &block) return HaveProblem.new(method, args.first) if method.to_s.start_with?('contain_') + super end diff --git a/spec/spec_helper_acceptance_local.rb b/spec/spec_helper_acceptance_local.rb index b63225f0..4286411a 100644 --- a/spec/spec_helper_acceptance_local.rb +++ b/spec/spec_helper_acceptance_local.rb @@ -17,7 +17,7 @@ def puppet_lint(args = []) { stdout: stdout.chomp, stderr: stderr.chomp, - exit_code: status.exitstatus, + exit_code: status.exitstatus } end diff --git a/spec/unit/puppet-lint/bin_spec.rb b/spec/unit/puppet-lint/bin_spec.rb index ad841d2f..118d054b 100644 --- a/spec/unit/puppet-lint/bin_spec.rb +++ b/spec/unit/puppet-lint/bin_spec.rb @@ -89,6 +89,7 @@ def initialize(args) end its(:exitstatus) { is_expected.to eq(1) } + its(:stdout) do is_expected.to eq( [ @@ -145,6 +146,7 @@ def initialize(args) end its(:exitstatus) { is_expected.to eq(1) } + its(:stdout) do is_expected.to match(%r{WARNING}) is_expected.not_to match(%r{ERROR}) @@ -162,13 +164,14 @@ def initialize(args) end its(:exitstatus) { is_expected.to eq(0) } + its(:stdout) do is_expected.not_to match(%r{ERROR}) is_expected.to match(%r{WARNING}) end end - context 'when asked to display filenames ' do + context 'when asked to display filenames' do let(:args) do [ '--with-filename', @@ -200,6 +203,7 @@ def initialize(args) end its(:exitstatus) { is_expected.to eq(0) } + its(:stdout) do is_expected.to eq( [ @@ -294,8 +298,9 @@ def initialize(args) end its(:exitstatus) { is_expected.to eq(1) } + its(:stdout) do - is_expected.to match(%r{^(/|[A-Za-z]\:).+/spec/fixtures/test/manifests/fail\.pp$}) + is_expected.to match(%r{^(/|[A-Za-z]:).+/spec/fixtures/test/manifests/fail\.pp$}) end end @@ -374,6 +379,7 @@ def initialize(args) end its(:exitstatus) { is_expected.to eq(0) } + its(:stdout) do if respond_to?(:include_json) is_expected.to include_json([[{ 'KIND' => 'WARNING' }]]) @@ -393,6 +399,7 @@ def initialize(args) end its(:exitstatus) { is_expected.to eq(1) } + its(:stdout) do if respond_to?(:include_json) is_expected.to include_json([[{ 'KIND' => 'ERROR' }], [{ 'KIND' => 'WARNING' }]]) @@ -493,6 +500,7 @@ def initialize(args) end its(:exitstatus) { is_expected.to eq(0) } + its(:stdout) do is_expected.to eq( [ @@ -615,6 +623,7 @@ def initialize(args) end its(:exitstatus) { is_expected.to eq(0) } + its(:stdout) do is_expected.to eq('WARNING: variable contains a dash on line 3 (check: variable_contains_dash)') end @@ -629,6 +638,7 @@ def initialize(args) end its(:exitstatus) { is_expected.to eq(0) } + its(:stdout) do is_expected.to eq('WARNING: variable contains an uppercase letter on line 4 (check: variable_is_lowercase)') end diff --git a/spec/unit/puppet-lint/configuration_spec.rb b/spec/unit/puppet-lint/configuration_spec.rb index 3dbcc4d6..f208cf41 100644 --- a/spec/unit/puppet-lint/configuration_spec.rb +++ b/spec/unit/puppet-lint/configuration_spec.rb @@ -14,11 +14,11 @@ config.disable_foo expect(config.settings['foo_disabled']).to be_truthy - expect(config.foo_enabled?).to be_falsey + expect(config).not_to be_foo_enabled config.enable_foo expect(config.settings['foo_disabled']).to be_falsey - expect(config.foo_enabled?).to be_truthy + expect(config).to be_foo_enabled end it 'knows what checks have been added' do @@ -41,7 +41,7 @@ end it 'is able to add options on the fly' do - expect(config.test_option).to eq(nil) + expect(config.test_option).to be_nil config.test_option = 'test' @@ -55,18 +55,18 @@ end expect(config.settings).to eq( - 'with_filename' => false, - 'fail_on_warnings' => false, + 'with_filename' => false, + 'fail_on_warnings' => false, 'codeclimate_report_file' => nil, - 'error_level' => :all, - 'log_format' => '', - 'sarif' => false, - 'with_context' => false, - 'fix' => false, - 'github_actions' => false, - 'show_ignored' => false, - 'json' => false, - 'ignore_paths' => ['vendor/**/*.pp'], + 'error_level' => :all, + 'log_format' => '', + 'sarif' => false, + 'with_context' => false, + 'fix' => false, + 'github_actions' => false, + 'show_ignored' => false, + 'json' => false, + 'ignore_paths' => ['vendor/**/*.pp'], ) end diff --git a/spec/unit/puppet-lint/lexer/string_slurper_spec.rb b/spec/unit/puppet-lint/lexer/string_slurper_spec.rb index 7694a089..c394536d 100644 --- a/spec/unit/puppet-lint/lexer/string_slurper_spec.rb +++ b/spec/unit/puppet-lint/lexer/string_slurper_spec.rb @@ -1,5 +1,3 @@ -# encoding: utf-8 - require 'spec_helper' describe PuppetLint::Lexer::StringSlurper do @@ -452,13 +450,13 @@ end describe '#consumed_chars' do - subject { described_class.new(string).tap(&:parse).consumed_chars } + subject(:consumed_chars) { described_class.new(string).tap(&:parse).consumed_chars } context 'when slurping a string containing multibyte characters' do let(:string) { 'accentués"' } it 'counts the multibyte character as a single consumed character' do - is_expected.to eq(10) + expect(consumed_chars).to eq(10) end end @@ -466,7 +464,7 @@ let(:string) { '"' } it 'consumes only the closing quote' do - is_expected.to eq(1) + expect(consumed_chars).to eq(1) end end end diff --git a/spec/unit/puppet-lint/lexer_spec.rb b/spec/unit/puppet-lint/lexer_spec.rb index a648a9bf..6af805a1 100644 --- a/spec/unit/puppet-lint/lexer_spec.rb +++ b/spec/unit/puppet-lint/lexer_spec.rb @@ -1,5 +1,3 @@ -# encoding: utf-8 - require 'spec_helper' describe PuppetLint::Lexer do @@ -13,7 +11,7 @@ end end - context '#new_token' do + describe '#new_token' do it 'calculates the line number for an empty string' do token = lexer.new_token(:TEST, 'test') expect(token.line).to eq(1) @@ -55,19 +53,19 @@ end it 'calculates the column number for a multi line string' do - lexer.instance_variable_set('@line_no', 4) - lexer.instance_variable_set('@column', 5) + lexer.instance_variable_set(:@line_no, 4) + lexer.instance_variable_set(:@column, 5) lexer.new_token(:SSTRING, "test\ntest") token = lexer.new_token(:TEST, 'test') expect(token.column).to eq(6) end end - context '#process_string_segments' do - subject(:tokens) { lexer.tokens } - + describe '#process_string_segments' do subject(:manifest) { lexer.tokens.map(&:to_manifest).join } + let(:tokens) { lexer.tokens } + before(:each) do lexer.process_string_segments(segments) end @@ -1291,7 +1289,7 @@ it 'does not enclose variable with a chained function call' do manifest = '"This is ${a.test}"' tokens = lexer.tokenise(manifest) - expect(tokens.map(&:to_manifest).join('')).to eq(manifest) + expect(tokens.map(&:to_manifest).join).to eq(manifest) end end @@ -1382,6 +1380,7 @@ expect(token.type).to eq(:TYPE) expect(token.value).to eq('Callable') end + it 'matches Sensitive' do token = lexer.tokenise('Sensitive').first expect(token.type).to eq(:TYPE) @@ -1689,7 +1688,7 @@ END tokens = lexer.tokenise(manifest) - expect(tokens.map(&:to_manifest).join('')).to eq(manifest) + expect(tokens.map(&:to_manifest).join).to eq(manifest) expect(tokens[0].type).to eq(:VARIABLE) expect(tokens[0].value).to eq('str') @@ -1756,7 +1755,7 @@ expect(tokens[7].raw).to eq('$myvar') expect(tokens[7].to_manifest).to eq('$myvar') - expect(tokens.map(&:to_manifest).join('')).to eq(manifest) + expect(tokens.map(&:to_manifest).join).to eq(manifest) end end diff --git a/spec/unit/puppet-lint/plugins/check_classes/parameter_order_spec.rb b/spec/unit/puppet-lint/plugins/check_classes/parameter_order_spec.rb index c4bef2c9..52be7bcd 100644 --- a/spec/unit/puppet-lint/plugins/check_classes/parameter_order_spec.rb +++ b/spec/unit/puppet-lint/plugins/check_classes/parameter_order_spec.rb @@ -27,7 +27,7 @@ expect(problems).to have(1).problem end - col = (type == 'class' ? 23 : 24) + col = ((type == 'class') ? 23 : 24) it 'creates a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(col) end @@ -58,7 +58,7 @@ expect(problems).to have(1).problem end - col = (type == 'class' ? 35 : 36) + col = ((type == 'class') ? 35 : 36) it 'creates a warning' do expect(problems).to contain_warning(msg).on_line(1).in_column(col) end diff --git a/spec/unit/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb b/spec/unit/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb index e8b75f1c..d278129d 100644 --- a/spec/unit/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +++ b/spec/unit/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb @@ -87,15 +87,15 @@ let(:code) do <<-END $mem = inline_template('<% - mem,unit = scope.lookupvar(\'::memorysize\').split + mem,unit = scope.lookupvar('::memorysize').split mem = mem.to_f # Normalize mem to bytes case unit when nil: mem *= (1<<0) - when \'kB\': mem *= (1<<10) - when \'MB\': mem *= (1<<20) - when \'GB\': mem *= (1<<30) - when \'TB\': mem *= (1<<40) + when 'kB': mem *= (1<<10) + when 'MB': mem *= (1<<20) + when 'GB': mem *= (1<<30) + when 'TB': mem *= (1<<40) end %><%= mem.to_i %>') END diff --git a/spec/unit/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb b/spec/unit/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb index 0ac5ebcb..a71f4fae 100644 --- a/spec/unit/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +++ b/spec/unit/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb @@ -98,7 +98,7 @@ class puppet::master::maintenance ( <<-END $string1 = "this string contains \n newline" $string2 = "this string contains \t tab" - $string3 = "this string contains \${escaped} var" + $string3 = "this string contains ${escaped} var" $string4 = "this string contains \\"escaped \\" double quotes" $string5 = "this string contains \\'escaped \\' single quotes" $string6 = "this string contains \r carriage return" diff --git a/spec/unit/puppet-lint/plugins/check_strings/only_variable_string_spec.rb b/spec/unit/puppet-lint/plugins/check_strings/only_variable_string_spec.rb index 800ddc3c..4cef4c1a 100644 --- a/spec/unit/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +++ b/spec/unit/puppet-lint/plugins/check_strings/only_variable_string_spec.rb @@ -45,7 +45,7 @@ <<-END $bar = 'key' $foo = { - \"$bar\" => 1, + "$bar" => 1, } END end diff --git a/spec/unit/puppet-lint/plugins/check_whitespace/140chars_spec.rb b/spec/unit/puppet-lint/plugins/check_whitespace/140chars_spec.rb index ff03e6a6..ceb9a56e 100644 --- a/spec/unit/puppet-lint/plugins/check_whitespace/140chars_spec.rb +++ b/spec/unit/puppet-lint/plugins/check_whitespace/140chars_spec.rb @@ -1,5 +1,3 @@ -# encoding: utf-8 - require 'spec_helper' describe '140chars' do diff --git a/spec/unit/puppet-lint/plugins/check_whitespace/80chars_spec.rb b/spec/unit/puppet-lint/plugins/check_whitespace/80chars_spec.rb index db820b2d..9b9f1570 100644 --- a/spec/unit/puppet-lint/plugins/check_whitespace/80chars_spec.rb +++ b/spec/unit/puppet-lint/plugins/check_whitespace/80chars_spec.rb @@ -1,10 +1,8 @@ -# encoding: utf-8 - require 'spec_helper' describe '80chars' do before(:each) do - PuppetLint.configuration.send('enable_80chars') + PuppetLint.configuration.send(:enable_80chars) end let(:msg) { 'line has more than 80 characters' } diff --git a/spec/unit/puppet-lint/plugins/legacy_facts/legacy_facts_spec.rb b/spec/unit/puppet-lint/plugins/legacy_facts/legacy_facts_spec.rb index d1323610..5e49be60 100644 --- a/spec/unit/puppet-lint/plugins/legacy_facts/legacy_facts_spec.rb +++ b/spec/unit/puppet-lint/plugins/legacy_facts/legacy_facts_spec.rb @@ -250,6 +250,7 @@ it 'onlies detect a single problem' do expect(problems).to have(1).problem end + it 'uses the facts hash' do expect(manifest).to eq("$facts['disks']['sda']['model']") end @@ -261,6 +262,7 @@ it 'onlies detect a single problem' do expect(problems).to have(1).problem end + it 'uses the facts hash' do expect(manifest).to eq("$facts['networking']['interfaces']['em2']['ip6']") end @@ -272,6 +274,7 @@ it 'onlies detect a single problem' do expect(problems).to have(1).problem end + it 'uses the facts hash' do expect(manifest).to eq("$facts['solaris_zones']['zones']['foobar']['uuid']") end @@ -283,6 +286,7 @@ it 'onlies detect a single problem' do expect(problems).to have(1).problem end + it 'uses the facts hash' do expect(manifest).to eq("$facts['processors']['models'][314]") end @@ -294,6 +298,7 @@ it 'onlies detect a single problem' do expect(problems).to have(1).problem end + it 'uses the facts hash' do expect(manifest).to eq("$facts['system_profiler']['l3_cache']") end @@ -305,6 +310,7 @@ it 'onlies detect a single problem' do expect(problems).to have(1).problem end + it 'uses the facts hash' do expect(manifest).to eq("$facts['ssh']['rsa']['key']") end @@ -333,6 +339,7 @@ expect(manifest).to eq("\"$facts['os']['family']\"") end end + context 'fact variable using legacy variable in double quotes "$::gid"' do let(:code) { '"$::gid"' } @@ -344,6 +351,7 @@ expect(manifest).to eq("\"$facts['identity']['group']\"") end end + context 'fact variable using legacy variable in double quotes "$::id"' do let(:code) { '"$::id"' } @@ -355,6 +363,7 @@ expect(manifest).to eq("\"$facts['identity']['user']\"") end end + context 'fact variable using legacy variable in double quotes "$::lsbdistcodename"' do let(:code) { '"$::lsbdistcodename"' } @@ -366,6 +375,7 @@ expect(manifest).to eq("\"$facts['os']['distro']['codename']\"") end end + context 'fact variable using legacy variable in double quotes "$::lsbdistdescription"' do let(:code) { '"$::lsbdistdescription"' } @@ -377,6 +387,7 @@ expect(manifest).to eq("\"$facts['os']['distro']['description']\"") end end + context 'fact variable using legacy variable in double quotes "$::lsbdistid"' do let(:code) { '"$::lsbdistid"' } @@ -388,6 +399,7 @@ expect(manifest).to eq("\"$facts['os']['distro']['id']\"") end end + context 'fact variable using legacy variable in double quotes "$::lsbdistrelease"' do let(:code) { '"$::lsbdistrelease"' } @@ -399,6 +411,7 @@ expect(manifest).to eq("\"$facts['os']['distro']['release']['full']\"") end end + context 'fact variable using legacy variable in double quotes "$::lsbmajdistrelease"' do let(:code) { '"$::lsbmajdistrelease"' } @@ -410,6 +423,7 @@ expect(manifest).to eq("\"$facts['os']['distro']['release']['major']\"") end end + context 'fact variable using legacy variable in double quotes "$::lsbminordistrelease"' do let(:code) { '"$::lsbminordistrelease"' } @@ -421,6 +435,7 @@ expect(manifest).to eq("\"$facts['os']['distro']['release']['minor']\"") end end + context 'fact variable using legacy variable in double quotes "$::lsbrelease"' do let(:code) { '"$::lsbrelease"' } @@ -432,6 +447,7 @@ expect(manifest).to eq("\"$facts['os']['distro']['release']['specification']\"") end end + context "fact variable using facts hash in double quotes \"$facts['lsbrelease']\"" do let(:code) { "\"${facts['lsbrelease']}\"" } diff --git a/spec/unit/puppet-lint/plugins/top_scope_facts/top_scope_facts_spec.rb b/spec/unit/puppet-lint/plugins/top_scope_facts/top_scope_facts_spec.rb index c09f8bae..43d477ef 100644 --- a/spec/unit/puppet-lint/plugins/top_scope_facts/top_scope_facts_spec.rb +++ b/spec/unit/puppet-lint/plugins/top_scope_facts/top_scope_facts_spec.rb @@ -11,6 +11,7 @@ expect(problems).to have(0).problem end end + context 'non-fact variable with two colons' do let(:code) { '$foo::bar' }