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 =
'5.1.0'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializePuppetLint

Public: Initialise a new PuppetLint object.



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

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.



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

def code
  @code
end

#manifestObject (readonly)

Public: Gets the String manifest with the errors fixed.



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

def manifest
  @manifest
end

#pathObject

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



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

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.


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

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.


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

def statistics
  @statistics
end

Class Method Details

.configurationObject

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

Returns a PuppetLint::Configuration object.



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

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

.new_check(name) ⇒ 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


252
253
254
255
256
257
258
259
# File 'lib/puppet-lint.rb', line 252

def self.new_check(name, &)
  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(&)
  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.



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

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)


199
200
201
# File 'lib/puppet-lint.rb', line 199

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.



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

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].unpack1('V') == 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.



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

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

  puts "  #{message[:reason]}" if message[:kind] == :ignored && !message[:reason].nil?
  print_context(message)
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#%.



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

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
162
163
164
# File 'lib/puppet-lint.rb', line 154

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", '^')
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 an array of problems.



234
235
236
# File 'lib/puppet-lint.rb', line 234

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.



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/puppet-lint.rb', line 172

def report(problems)
  json = []
  print_stdout = !(configuration.json || configuration.sarif)

  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)

    message[:context] = get_context(message) if configuration.with_context

    json << message

    if print_stdout
      format_message(message)
      print_github_annotation(message) if configuration.github_actions
    end
  end
  warn '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.



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/puppet-lint.rb', line 215

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)


206
207
208
# File 'lib/puppet-lint.rb', line 206

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