puppet-lint 0.4.0.pre1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/.travis.yml +3 -4
  2. data/Gemfile +2 -5
  3. data/README.md +2 -149
  4. data/Rakefile +0 -5
  5. data/lib/puppet-lint.rb +74 -20
  6. data/lib/puppet-lint/bin.rb +20 -85
  7. data/lib/puppet-lint/checkplugin.rb +158 -12
  8. data/lib/puppet-lint/checks.rb +39 -222
  9. data/lib/puppet-lint/configuration.rb +12 -31
  10. data/lib/puppet-lint/data.rb +329 -0
  11. data/lib/puppet-lint/lexer.rb +37 -30
  12. data/lib/puppet-lint/lexer/token.rb +14 -16
  13. data/lib/puppet-lint/monkeypatches/string_prepend.rb +6 -0
  14. data/lib/puppet-lint/optparser.rb +105 -0
  15. data/lib/puppet-lint/plugins.rb +28 -9
  16. data/lib/puppet-lint/plugins/check_classes.rb +162 -238
  17. data/lib/puppet-lint/plugins/check_comments.rb +40 -25
  18. data/lib/puppet-lint/plugins/check_conditionals.rb +16 -20
  19. data/lib/puppet-lint/plugins/check_documentation.rb +14 -20
  20. data/lib/puppet-lint/plugins/check_nodes.rb +23 -0
  21. data/lib/puppet-lint/plugins/check_resources.rb +127 -141
  22. data/lib/puppet-lint/plugins/check_strings.rb +133 -107
  23. data/lib/puppet-lint/plugins/check_variables.rb +11 -11
  24. data/lib/puppet-lint/plugins/check_whitespace.rb +86 -92
  25. data/lib/puppet-lint/tasks/puppet-lint.rb +17 -1
  26. data/lib/puppet-lint/version.rb +1 -1
  27. data/puppet-lint.gemspec +4 -2
  28. data/spec/fixtures/test/manifests/ignore.pp +1 -0
  29. data/spec/fixtures/test/manifests/ignore_reason.pp +1 -0
  30. data/spec/puppet-lint/bin_spec.rb +104 -84
  31. data/spec/puppet-lint/configuration_spec.rb +19 -19
  32. data/spec/puppet-lint/ignore_overrides_spec.rb +97 -0
  33. data/spec/puppet-lint/lexer/token_spec.rb +9 -9
  34. data/spec/puppet-lint/lexer_spec.rb +352 -325
  35. data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +77 -23
  36. data/spec/puppet-lint/plugins/check_classes/class_inherits_from_params_class_spec.rb +14 -12
  37. data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +18 -14
  38. data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +30 -30
  39. data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +31 -26
  40. data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +34 -28
  41. data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +14 -12
  42. data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +74 -30
  43. data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +27 -20
  44. data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +78 -13
  45. data/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +17 -12
  46. data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +13 -10
  47. data/spec/puppet-lint/plugins/check_documentation/documentation_spec.rb +21 -16
  48. data/spec/puppet-lint/plugins/check_nodes/unquoted_node_name_spec.rb +69 -0
  49. data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +42 -38
  50. data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +22 -10
  51. data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +81 -18
  52. data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +69 -112
  53. data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +27 -20
  54. data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +177 -171
  55. data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +165 -88
  56. data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +97 -22
  57. data/spec/puppet-lint/plugins/check_strings/puppet_url_without_modules_spec.rb +25 -0
  58. data/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb +97 -111
  59. data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +10 -9
  60. data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +53 -53
  61. data/spec/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb +26 -14
  62. data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +10 -9
  63. data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +31 -15
  64. data/spec/puppet-lint/plugins/check_whitespace/arrow_alignment_spec.rb +340 -322
  65. data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +30 -23
  66. data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +42 -41
  67. data/spec/puppet-lint_spec.rb +3 -3
  68. data/spec/spec_helper.rb +109 -116
  69. metadata +109 -50
  70. data/spec/puppet-lint/plugins/check_classes/class_parameter_defaults_spec.rb +0 -60
data/.travis.yml CHANGED
@@ -1,11 +1,10 @@
1
+ before_install: gem update --system 2.1.11
1
2
  rvm:
2
3
  - 1.8.7
3
4
  - 1.9.2
4
5
  - 1.9.3
5
- branches:
6
- only:
7
- - master
8
- - dust_bunny
6
+ - 2.0.0
7
+ - 2.1.0
9
8
  notifications:
10
9
  email:
11
10
  - tim@github.com
data/Gemfile CHANGED
@@ -1,6 +1,3 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
- gem 'rake'
4
- gem 'rspec'
5
- gem 'ruby-prof'
6
- gem 'rcov', :platform => :ruby_18
3
+ gemspec
data/README.md CHANGED
@@ -2,12 +2,11 @@
2
2
 
3
3
  [![Build
4
4
  Status](https://secure.travis-ci.org/rodjek/puppet-lint.png)](http://travis-ci.org/rodjek/puppet-lint)
5
- [![Dependency
6
- Status](https://gemnasium.com/rodjek/puppet-lint.png)](http://gemnasium.com/rodjek/puppet-lint)
5
+ [![Inline docs](http://inch-ci.org/github/rodjek/puppet-lint.png?branch=master)](http://inch-ci.org/github/rodjek/puppet-lint)
7
6
 
8
7
  The goal of this project is to implement as many of the recommended Puppet
9
8
  style guidelines from the [Puppet Labs style
10
- guide](http://docs.puppetlabs.com/guides/style_guide.html) as practical.
9
+ guide](http://docs.puppetlabs.com/guides/style_guide.html) as practical. It is not meant to validate syntax. Please use `puppet parser validate` for that.
11
10
 
12
11
  ## Installation
13
12
 
@@ -82,151 +81,6 @@ At the moment, the following tests have been implemented:
82
81
  * When using top-scope variables, including facts, Puppet modules should
83
82
  explicitly specify the empty namespace.
84
83
 
85
- ## Fixing problems
86
-
87
- ### right_to_left_relationship
88
-
89
- ```
90
- WARNING: right-to-left (<-) relationship on line X
91
- ```
92
-
93
- While right to left relationships are perfectly valid, it's highly recommended
94
- that you don't use them as most people think and read from left to right and
95
- this can lead to confusion.
96
-
97
- Bad:
98
-
99
- ```
100
- Service['httpd'] <- Package['httpd']
101
- ```
102
-
103
- Good:
104
-
105
- ```
106
- Package['httpd'] -> Service['httpd']
107
- ```
108
-
109
- ### autoloader_layout
110
-
111
- ```
112
- ERROR: mymodule::myclass not in autoload module layout on line X
113
- ```
114
-
115
- Puppet attempts to autoload only the required manifests for the resources and
116
- classes specified in your manifests. In order to do this, the autoloader
117
- expects your manifests to be laid out on disk in a particular format. For
118
- example, when you use `mymodule::myclass` in your manifests, Puppet will
119
- attempt to read `<modulepath>/mymodule/manifests/myclass.pp`. The only
120
- exception to this is when you reference `mymodule` itself (without any
121
- subclass/subtype) in which case it will read
122
- `<modulepath>/mymodule/manifests/init.pp`.
123
-
124
- ### parameter_order
125
-
126
- ```
127
- WARNING: optional parameter listed before required parameter on line X
128
- ```
129
-
130
- In parameterised class and defined type definitions, parameters that are
131
- required should be listed before optional parameters (those with default
132
- values).
133
-
134
- Bad:
135
-
136
- ```
137
- class foo($bar='baz', $gronk) {
138
- ```
139
-
140
- Good:
141
-
142
- ```
143
- class foo($gronk, $bar='baz') {
144
- ```
145
-
146
- ### inherits_across_namespaces
147
-
148
- Placeholder
149
-
150
- ### nested_classes_or_defines
151
-
152
- Placeholder
153
-
154
- ### variable_scope
155
-
156
- Placeholder
157
-
158
- ### selector_inside_resource
159
-
160
- Placeholder
161
-
162
- ### case_without_default
163
-
164
- Placeholder
165
-
166
- ### unquoted_resource_title
167
-
168
- Placeholder
169
-
170
- ### ensure_first_param
171
-
172
- Placeholder
173
-
174
- ### unquoted_file_mode
175
-
176
- Placeholder
177
-
178
- ### 4digit_file_mode
179
-
180
- Placeholder
181
-
182
- ### ensure_not_symlink_target
183
-
184
- Placeholder
185
-
186
- ### double_quoted_strings
187
-
188
- Placeholder
189
-
190
- ### only_variable_string
191
-
192
- Placeholder
193
-
194
- ### variables_not_enclosed
195
-
196
- Placeholder
197
-
198
- ### single_quote_string_with_variables
199
-
200
- Placeholder
201
-
202
- ### quoted_booleans
203
-
204
- Placeholder
205
-
206
- ### variable_contains_dash
207
-
208
- Placeholder
209
-
210
- ### hard_tabs
211
-
212
- Placeholder
213
-
214
- ### trailing_whitespace
215
-
216
- Placeholder
217
-
218
- ### 80chars
219
-
220
- Placeholder
221
-
222
- ### 2sp_soft_tabs
223
-
224
- Placeholder
225
-
226
- ### arrow_alignment
227
-
228
- Placeholder
229
-
230
84
  ## Disabling checks
231
85
 
232
86
  ### puppet-lint
@@ -254,7 +108,6 @@ For a list of all the flags just type:
254
108
  puppet-lint --help
255
109
  ```
256
110
 
257
-
258
111
  ### Rake task
259
112
 
260
113
  You can also disable checks when running puppet-lint through the supplied Rake
data/Rakefile CHANGED
@@ -4,8 +4,3 @@ require 'rspec/core/rake_task'
4
4
  task :default => :test
5
5
 
6
6
  RSpec::Core::RakeTask.new(:test)
7
-
8
- RSpec::Core::RakeTask.new(:cov) do |t|
9
- t.rcov = true
10
- t.rcov_opts = '--exclude "spec" --xrefs'
11
- end
data/lib/puppet-lint.rb CHANGED
@@ -1,23 +1,52 @@
1
+ require 'set'
1
2
  require 'puppet-lint/version'
2
3
  require 'puppet-lint/lexer'
3
4
  require 'puppet-lint/configuration'
5
+ require 'puppet-lint/data'
4
6
  require 'puppet-lint/checks'
5
7
  require 'puppet-lint/bin'
6
8
  require 'puppet-lint/monkeypatches'
7
9
 
8
10
  class PuppetLint::NoCodeError < StandardError; end
11
+ class PuppetLint::NoFix < StandardError; end
9
12
 
13
+ # Public: The public interface to puppet-lint.
10
14
  class PuppetLint
11
15
  # Public: Gets/Sets the String manifest code to be checked.
12
16
  attr_accessor :code
13
17
 
18
+ # Public: Gets the String manifest with the errors fixed.
14
19
  attr_reader :manifest
15
20
 
21
+ # Public: Returns an Array of Hashes describing the problems found in the
22
+ # manifest.
23
+ #
24
+ # Each Hash will contain *at least*:
25
+ # :check - The Symbol name of the check that generated the problem.
26
+ # :kind - The Symbol kind of the problem (:error, :warning, or
27
+ # :fixed).
28
+ # :line - The Integer line number of the location of the problem in
29
+ # the manifest.
30
+ # :column - The Integer column number of the location of the problem in
31
+ # the manifest.
32
+ # :message - The String message describing the problem that was found.
33
+ attr_reader :problems
34
+
35
+ # Public: Gets/Sets the String path to the manifest to be checked.
36
+ attr_accessor :path
37
+
38
+ # Public: Returns a Hash of linter statistics
39
+ #
40
+ # :error - An Integer count of errors found in the manifest.
41
+ # :warning - An Integer count of warnings found in the manifest.
42
+ # :fixed - An Integer count of problems found in the manifest that were
43
+ # automatically fixed.
44
+ attr_reader :statistics
45
+
16
46
  # Public: Initialise a new PuppetLint object.
17
47
  def initialize
18
48
  @code = nil
19
- @statistics = {:error => 0, :warning => 0, :fixed => 0}
20
- @fileinfo = {:path => ''}
49
+ @statistics = {:error => 0, :warning => 0, :fixed => 0, :ignored => 0}
21
50
  @manifest = ''
22
51
  end
23
52
 
@@ -41,9 +70,7 @@ class PuppetLint
41
70
  # Returns nothing.
42
71
  def file=(path)
43
72
  if File.exist? path
44
- @fileinfo[:path] = path
45
- @fileinfo[:fullpath] = File.expand_path(path)
46
- @fileinfo[:filename] = File.basename(path)
73
+ @path = path
47
74
  @code = File.read(path)
48
75
  end
49
76
  end
@@ -56,7 +83,7 @@ class PuppetLint
56
83
  def log_format
57
84
  if configuration.log_format == ''
58
85
  ## recreate previous old log format as far as thats possible.
59
- format = '%{KIND}: %{message} on line %{linenumber}'
86
+ format = '%{KIND}: %{message} on line %{line}'
60
87
  if configuration.with_filename
61
88
  format.prepend '%{path} - '
62
89
  end
@@ -73,22 +100,22 @@ class PuppetLint
73
100
  def format_message(message)
74
101
  format = log_format
75
102
  puts format % message
103
+ if message[:kind] == :ignored && !message[:reason].nil?
104
+ puts " #{message[:reason]}"
105
+ end
76
106
  end
77
107
 
78
108
  # Internal: Print out the line of the manifest on which the problem was found
79
109
  # as well as a marker pointing to the location on the line.
80
110
  #
81
111
  # message - A Hash containing all the information about a problem.
82
- # linter - The PuppetLint::Checks object that was used to test the manifest.
83
112
  #
84
113
  # Returns nothing.
85
- def print_context(message, linter)
86
- # XXX: I don't really like the way this has been implemented (passing the
87
- # linter object down through layers of functions. Refactor me!
114
+ def print_context(message)
88
115
  return if message[:check] == 'documentation'
89
116
  return if message[:kind] == :fixed
90
- line = linter.manifest_lines[message[:linenumber] - 1]
91
- offset = line.index(/\S/)
117
+ line = PuppetLint::Data.manifest_lines[message[:line] - 1]
118
+ offset = line.index(/\S/) || 1
92
119
  puts "\n #{line.strip}"
93
120
  printf "%#{message[:column] + 2 - offset}s\n\n", '^'
94
121
  end
@@ -97,20 +124,18 @@ class PuppetLint
97
124
  #
98
125
  # problems - An Array of problem Hashes as returned by
99
126
  # PuppetLint::Checks#run.
100
- # linter - The PuppetLint::Checks object that was used to test the
101
- # manifest.
102
127
  #
103
128
  # Returns nothing.
104
- def report(problems, linter)
129
+ def report(problems)
105
130
  problems.each do |message|
106
- @statistics[message[:kind]] += 1
131
+ next if message[:kind] == :ignored && !PuppetLint.configuration.show_ignored
107
132
 
108
- message.merge!(@fileinfo) {|key, v1, v2| v1 }
109
133
  message[:KIND] = message[:kind].to_s.upcase
134
+ message[:linenumber] = message[:line]
110
135
 
111
136
  if message[:kind] == :fixed || [message[:kind], :all].include?(configuration.error_level)
112
137
  format_message message
113
- print_context(message, linter) if configuration.with_context
138
+ print_context(message) if configuration.with_context
114
139
  end
115
140
  end
116
141
  end
@@ -140,11 +165,40 @@ class PuppetLint
140
165
  end
141
166
 
142
167
  linter = PuppetLint::Checks.new
143
- problems = linter.run(@fileinfo, @code)
168
+ @problems = linter.run(@path, @code)
169
+ @problems.each { |problem| @statistics[problem[:kind]] += 1 }
144
170
 
145
171
  @manifest = linter.manifest if PuppetLint.configuration.fix
172
+ end
173
+
174
+ # Public: Print any problems that were found out to stdout.
175
+ #
176
+ # Returns nothing.
177
+ def print_problems
178
+ report @problems
179
+ end
146
180
 
147
- report problems, linter
181
+ # Public: Define a new check.
182
+ #
183
+ # name - A unique name for the check as a Symbol.
184
+ # block - The check logic. This must contain a `check` method and optionally
185
+ # a `fix` method.
186
+ #
187
+ # Returns nothing.
188
+ #
189
+ # Examples
190
+ #
191
+ # PuppetLint.new_check(:foo) do
192
+ # def check
193
+ # end
194
+ # end
195
+ def self.new_check(name, &block)
196
+ class_name = name.to_s.split('_').map(&:capitalize).join
197
+ klass = PuppetLint.const_set("Check#{class_name}", Class.new(PuppetLint::CheckPlugin))
198
+ klass.const_set('NAME', name)
199
+ klass.class_exec(&block)
200
+ PuppetLint.configuration.add_check(name, klass)
201
+ PuppetLint::Data.ignore_overrides[name] ||= {}
148
202
  end
149
203
  end
150
204
 
@@ -1,10 +1,16 @@
1
- require 'optparse'
1
+ require 'puppet-lint/optparser'
2
2
 
3
+ # Internal: The logic of the puppet-lint bin script, contained in a class for
4
+ # ease of testing.
3
5
  class PuppetLint::Bin
4
6
  # Public: Initialise a new PuppetLint::Bin.
5
7
  #
6
8
  # args - An Array of command line argument Strings to be passed to the option
7
9
  # parser.
10
+ #
11
+ # Examples
12
+ #
13
+ # PuppetLint::Bin.new(ARGV).run
8
14
  def initialize(args)
9
15
  @args = args
10
16
  end
@@ -13,88 +19,7 @@ class PuppetLint::Bin
13
19
  #
14
20
  # Returns an Integer exit code to be passed back to the shell.
15
21
  def run
16
- help = <<-EOHELP
17
- Puppet-lint
18
-
19
- Basic Command Line Usage:
20
- puppet-lint [OPTIONS] [PATH]
21
-
22
- PATH The path to the Puppet manifest.
23
-
24
- Options:
25
- EOHELP
26
-
27
- opts = OptionParser.new do |opts|
28
- opts.banner = help
29
-
30
- opts.on("--version", "Display current version.") do
31
- puts "Puppet-lint " + PuppetLint::VERSION
32
- return 0
33
- end
34
-
35
- opts.on('--with-context', 'Show where in the manifest the problem is') do
36
- PuppetLint.configuration.with_context = true
37
- end
38
-
39
- opts.on("--with-filename", "Display the filename before the warning") do
40
- PuppetLint.configuration.with_filename = true
41
- end
42
-
43
- opts.on("--fail-on-warnings", "Return a non-zero exit status for warnings.") do
44
- PuppetLint.configuration.fail_on_warnings = true
45
- end
46
-
47
- opts.on("--error-level LEVEL", [:all, :warning, :error], "The level of error to return.", "(warning, error, all)") do |el|
48
- PuppetLint.configuration.error_level = el
49
- end
50
-
51
- opts.on("-l", '--load FILE', 'Load a file containing custom puppet-lint checks.') do |f|
52
- load f
53
- end
54
-
55
- opts.on('-f', '--fix', 'Attempt to automatically fix errors') do
56
- PuppetLint.configuration.fix = true
57
- end
58
-
59
- opts.on("--log-format FORMAT",
60
- "Change the log format.", "Overrides --with-filename.",
61
- "The following placeholders can be used:",
62
- "%{filename} - Filename without path.",
63
- "%{path} - Path as provided.",
64
- "%{fullpath} - Full path.",
65
- "%{linenumber} - Line number.",
66
- "%{kind} - The kind of message.",
67
- " - (warning, error)",
68
- "%{KIND} - Uppercase version of %{kind}",
69
- "%{check} - Name of the check.",
70
- "%{message} - The message."
71
- ) do |format|
72
- PuppetLint.configuration.log_format = format
73
- end
74
-
75
- opts.separator ""
76
- opts.separator " Disable checks:"
77
-
78
- PuppetLint.configuration.checks.each do |check|
79
- opts.on("--no-#{check}-check", "Skip the #{check} check") do
80
- PuppetLint.configuration.send("disable_#{check}")
81
- end
82
- end
83
-
84
- opts.load('/etc/puppet-lint.rc')
85
-
86
- if ENV['HOME']
87
- opts.load(File.expand_path('~/.puppet-lint.rc'))
88
- if opts.load(File.expand_path('~/.puppet-lintrc'))
89
- $stderr.puts 'Depreciated: Found ~/.puppet-lintrc instead of ~/.puppet-lint.rc'
90
- end
91
- end
92
-
93
- opts.load('.puppet-lint.rc')
94
- if opts.load('.puppet-lintrc')
95
- $stderr.puts 'Depreciated: Read .puppet-lintrc instead of .puppet-lint.rc'
96
- end
97
- end
22
+ opts = PuppetLint::OptParser.build
98
23
 
99
24
  begin
100
25
  opts.parse!(@args)
@@ -104,6 +29,11 @@ class PuppetLint::Bin
104
29
  return 1
105
30
  end
106
31
 
32
+ if PuppetLint.configuration.display_version
33
+ puts "puppet-lint #{PuppetLint::VERSION}"
34
+ return 0
35
+ end
36
+
107
37
  if @args[0].nil?
108
38
  puts "puppet-lint: no file specified"
109
39
  puts "puppet-lint: try 'puppet-lint --help' for more information"
@@ -118,18 +48,23 @@ class PuppetLint::Bin
118
48
  path = @args
119
49
  end
120
50
 
51
+ if path.length > 1
52
+ PuppetLint.configuration.with_filename = true
53
+ end
54
+
121
55
  return_val = 0
122
56
  path.each do |f|
123
57
  l = PuppetLint.new
124
58
  l.file = f
125
59
  l.run
60
+ l.print_problems
126
61
  if l.errors? or (l.warnings? and PuppetLint.configuration.fail_on_warnings)
127
62
  return_val = 1
128
63
  end
129
64
 
130
- if PuppetLint.configuration.fix
65
+ if PuppetLint.configuration.fix && !l.problems.any? { |e| e[:check] == :syntax }
131
66
  File.open(f, 'w') do |fd|
132
- fd.puts l.manifest
67
+ fd.write l.manifest
133
68
  end
134
69
  end
135
70
  end