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 =
'4.2.3'.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


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

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)


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

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].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.



122
123
124
125
126
127
128
# 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?
  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.



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

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.



155
156
157
158
159
160
161
162
163
164
165
# File 'lib/puppet-lint.rb', line 155

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.



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

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.



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

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.



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

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.



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

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)


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

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