Class: PuppetLint

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet-lint.rb,
lib/puppet-lint/version.rb

Overview

Public: The public interface to puppet-lint.

Defined Under Namespace

Classes: Bin, CheckPlugin, Checks, Configuration, Data, Lexer, LexerError, LineLengthCheck, NoCodeError, NoFix, OptParser, Plugins, RakeTask, Report, SyntaxError

Constant Summary collapse

VERSION =
'3.1.0'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializePuppetLint

Public: Initialise a new PuppetLint object.



64
65
66
67
68
# File 'lib/puppet-lint.rb', line 64

def initialize
  @code = nil
  @statistics = { error: 0, warning: 0, fixed: 0, ignored: 0 }
  @manifest = ''
end

Instance Attribute Details

#codeObject

Public: Gets/Sets the String manifest code to be checked.



33
34
35
# File 'lib/puppet-lint.rb', line 33

def code
  @code
end

#manifestObject (readonly)

Public: Gets the String manifest with the errors fixed.



36
37
38
# File 'lib/puppet-lint.rb', line 36

def manifest
  @manifest
end

#pathObject

Public: Gets/Sets the String path to the manifest to be checked.



53
54
55
# File 'lib/puppet-lint.rb', line 53

def path
  @path
end

#problemsObject (readonly)

Public: Returns an Array of Hashes describing the problems found in the manifest.

Each Hash will contain *at least*:

:check   - The Symbol name of the check that generated the problem.
:kind    - The Symbol kind of the problem (:error, :warning, or
           :fixed).
:line    - The Integer line number of the location of the problem in
           the manifest.
:column  - The Integer column number of the location of the problem in
           the manifest.
:message - The String message describing the problem that was found.


50
51
52
# File 'lib/puppet-lint.rb', line 50

def problems
  @problems
end

#statisticsObject (readonly)

Public: Returns a Hash of linter statistics

:error   - An Integer count of errors found in the manifest.
:warning - An Integer count of warnings found in the manifest.
:fixed   - An Integer count of problems found in the manifest that were
           automatically fixed.


61
62
63
# File 'lib/puppet-lint.rb', line 61

def statistics
  @statistics
end

Class Method Details

.configurationObject

Public: Access PuppetLint’s configuration from outside the class.

Returns a PuppetLint::Configuration object.



73
74
75
# File 'lib/puppet-lint.rb', line 73

def self.configuration
  @configuration ||= PuppetLint::Configuration.new
end

.new_check(name, &block) ⇒ Object

Public: Define a new check.

name - A unique name for the check as a Symbol. block - The check logic. This must contain a ‘check` method and optionally

a `fix` method.

Returns nothing.

Examples

PuppetLint.new_check(:foo) do
  def check
  end
end


247
248
249
250
251
252
253
254
# File 'lib/puppet-lint.rb', line 247

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.class_exec(&block)
  PuppetLint.configuration.add_check(name, klass)
  PuppetLint::Data.ignore_overrides[name] ||= {}
end

Instance Method Details

#configurationObject

Public: Access PuppetLint’s configuration from inside the class.

Returns a PuppetLint::Configuration object.



80
81
82
# File 'lib/puppet-lint.rb', line 80

def configuration
  self.class.configuration
end

#errors?Boolean

Public: Determine if PuppetLint found any errors in the manifest.

Returns true if errors were found, otherwise returns false.

Returns:

  • (Boolean)


194
195
196
# File 'lib/puppet-lint.rb', line 194

def errors?
  @statistics[:error] != 0
end

#file=(path) ⇒ Object

Public: Set the path of the manifest file to be tested and read the contents of the file.

Returns nothing.



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/puppet-lint.rb', line 88

def file=(path)
  return unless File.exist?(path)

  @path = path
  File.open(path, 'rb:UTF-8') do |f|
    @code = f.read
  end

  # 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
end

#format_message(message) ⇒ Object

Internal: Format a problem message and print it to STDOUT.

message - A Hash containing all the information about a problem.

Returns nothing.



122
123
124
125
126
127
# File 'lib/puppet-lint.rb', line 122

def format_message(message)
  format = log_format
  puts format % message

  puts "  #{message[:reason]}" if message[:kind] == :ignored && !message[:reason].nil?
end

#get_context(message) ⇒ Object

Internal: Get the line of the manifest on which the problem was found

message - A Hash containing all the information about a problem.

Returns the problematic line as a string.



144
145
146
# File 'lib/puppet-lint.rb', line 144

def get_context(message)
  PuppetLint::Data.manifest_lines[message[:line] - 1].strip
end

#log_formatObject

Internal: Retrieve the format string to be used when writing problems to STDOUT. If the user has not specified a custom log format, build one for them.

Returns a format String to be used with String#%.



106
107
108
109
110
111
112
113
114
115
# File 'lib/puppet-lint.rb', line 106

def log_format
  if configuration.log_format.nil? || configuration.log_format.empty?
    format = '%{KIND}: %{message} on line %{line}'
    format.prepend('%{path} - ') if configuration.with_filename
    format.concat(' (check: %{check})')
    configuration.log_format = format
  end

  configuration.log_format
end

Internal: Print out the line of the manifest on which the problem was found as well as a marker pointing to the location on the line.

message - A Hash containing all the information about a problem.

Returns nothing.



154
155
156
157
158
159
160
161
# File 'lib/puppet-lint.rb', line 154

def print_context(message)
  return if message[:check] == 'documentation'
  return if message[:kind] == :fixed
  line = get_context(message)
  offset = line.index(%r{\S}) || 1
  puts "\n  #{line.strip}"
  printf("%#{message[:column] + 2 - offset}s\n\n", '^')
end

Internal: Format a problem message and print it to STDOUT so GitHub Actions recognizes it as an annotation.

message - A Hash containing all the information about a problem.

Returns nothing.



135
136
137
# File 'lib/puppet-lint.rb', line 135

def print_github_annotation(message)
  puts PuppetLint::Report::GitHubActionsReporter.format_problem(path, message)
end

Public: Print any problems that were found out to stdout.

Returns nothing.



229
230
231
# File 'lib/puppet-lint.rb', line 229

def print_problems
  report(@problems)
end

#report(problems) ⇒ Object

Internal: Print the reported problems with a manifest to stdout.

problems - An Array of problem Hashes as returned by

PuppetLint::Checks#run.

Returns array of problem.



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/puppet-lint.rb', line 169

def report(problems)
  json = []
  problems.each do |message|
    next if message[:kind] == :ignored && !PuppetLint.configuration.show_ignored

    message[:KIND] = message[:kind].to_s.upcase

    next unless message[:kind] == :fixed || [message[:kind], :all].include?(configuration.error_level)

    if configuration.json || configuration.sarif
      message['context'] = get_context(message) if configuration.with_context
      json << message
    else
      format_message(message)
      print_context(message) if configuration.with_context
      print_github_annotation(message) if configuration.github_actions
    end
  end
  $stderr.puts 'Try running `puppet parser validate <file>`' if problems.any? { |p| p[:check] == :syntax }
  json
end

#runObject

Public: Run the loaded manifest code through the lint checks and print the results of the checks to stdout.

Returns nothing. Raises PuppetLint::NoCodeError if no manifest code has been loaded.



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/puppet-lint.rb', line 210

def run
  raise PuppetLint::NoCodeError if @code.nil?

  if @code.empty?
    @problems = []
    @manifest = ''
    return
  end

  linter = PuppetLint::Checks.new
  @problems = linter.run(@path, @code)
  @problems.each { |problem| @statistics[problem[:kind]] += 1 }

  @manifest = linter.manifest if PuppetLint.configuration.fix
end

#warnings?Boolean

Public: Determine if PuppetLint found any warnings in the manifest.

Returns true if warnings were found, otherwise returns false.

Returns:

  • (Boolean)


201
202
203
# File 'lib/puppet-lint.rb', line 201

def warnings?
  @statistics[:warning] != 0
end