puppet-lint 0.2.0 → 0.2.1

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 (44) hide show
  1. data/lib/puppet-lint.rb +1 -3
  2. data/lib/puppet-lint/configuration.rb +7 -6
  3. data/lib/puppet-lint/plugin.rb +14 -24
  4. data/lib/puppet-lint/plugins/check_classes.rb +14 -10
  5. data/lib/puppet-lint/plugins/check_documentation.rb +10 -14
  6. data/lib/puppet-lint/plugins/check_resources.rb +56 -73
  7. data/lib/puppet-lint/version.rb +1 -1
  8. data/spec/puppet-lint/configuration_spec.rb +4 -1
  9. data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +51 -0
  10. data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +23 -0
  11. data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +45 -0
  12. data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +71 -0
  13. data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +67 -0
  14. data/spec/puppet-lint/plugins/check_classes/parameterised_classes_spec.rb +43 -0
  15. data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +23 -0
  16. data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +93 -0
  17. data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +16 -0
  18. data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +19 -0
  19. data/spec/puppet-lint/plugins/{check_conditionals_spec.rb → check_conditionals/case_without_default_spec.rb} +1 -39
  20. data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +33 -0
  21. data/spec/puppet-lint/plugins/{check_documentation_spec.rb → check_documentation/documentation_spec.rb} +1 -9
  22. data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +23 -0
  23. data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +43 -0
  24. data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +26 -0
  25. data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +43 -0
  26. data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +11 -0
  27. data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +110 -0
  28. data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +83 -0
  29. data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +16 -0
  30. data/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb +55 -0
  31. data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +16 -0
  32. data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +29 -0
  33. data/spec/puppet-lint/plugins/{check_variables_spec.rb → check_variables/variable_contains_dash_spec.rb} +1 -9
  34. data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +20 -0
  35. data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +38 -0
  36. data/spec/puppet-lint/plugins/{check_whitespace_spec.rb → check_whitespace/arrow_alignment_spec.rb} +1 -86
  37. data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +16 -0
  38. data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +16 -0
  39. data/spec/spec_helper.rb +17 -0
  40. metadata +122 -92
  41. data/spec/puppet-lint/plugins/check_classes_spec.rb +0 -390
  42. data/spec/puppet-lint/plugins/check_comments_spec.rb +0 -40
  43. data/spec/puppet-lint/plugins/check_resources_spec.rb +0 -249
  44. data/spec/puppet-lint/plugins/check_strings_spec.rb +0 -175
data/lib/puppet-lint.rb CHANGED
@@ -140,9 +140,7 @@ class PuppetLint
140
140
  raise PuppetLint::NoCodeError
141
141
  end
142
142
 
143
- PuppetLint::CheckPlugin.repository.each do |plugin|
144
- report plugin.new.run(@fileinfo, @data)
145
- end
143
+ report PuppetLint::Checks.new.run(@fileinfo, @data)
146
144
  end
147
145
  end
148
146
 
@@ -38,20 +38,21 @@ class PuppetLint
38
38
  end
39
39
  end
40
40
 
41
- def add_check(check)
41
+ def add_check(check, &b)
42
42
  self.class.add_check(check)
43
+ check_method[check] = b
43
44
  end
44
45
 
45
46
  def settings
46
47
  @settings ||= {}
47
48
  end
48
49
 
50
+ def check_method
51
+ @check_method ||= {}
52
+ end
53
+
49
54
  def checks
50
- self.public_methods.select { |method|
51
- method =~ /^.+_enabled\?$/
52
- }.map { |method|
53
- method[0..-10]
54
- }
55
+ check_method.keys
55
56
  end
56
57
 
57
58
  def defaults
@@ -1,29 +1,14 @@
1
- class PuppetLint
2
-
3
- module Plugin
4
- module ClassMethods
5
- def repository
6
- @repository ||= []
7
- end
8
-
9
- def inherited(klass)
10
- repository << klass
11
- end
12
- end
13
-
14
- def self.included(klass)
15
- klass.extend ClassMethods
16
- end
17
- end
18
- end
19
-
20
- class PuppetLint::CheckPlugin
21
- include PuppetLint::Plugin
1
+ class PuppetLint::Checks
22
2
  attr_reader :problems
23
3
 
24
4
  def initialize
25
5
  @problems = []
26
6
  @default_info = {:check => 'unknown', :linenumber => 0}
7
+
8
+ PuppetLint.configuration.checks.each do |check|
9
+ method = PuppetLint.configuration.check_method[check]
10
+ self.class.send(:define_method, "lint_check_#{check}", &method)
11
+ end
27
12
  end
28
13
 
29
14
  # notify(kind, message_hash) #=> nil
@@ -48,11 +33,15 @@ class PuppetLint::CheckPlugin
48
33
  message_hash
49
34
  end
50
35
 
51
- def run(fileinfo, data)
36
+ def load_data(fileinfo, data)
52
37
  lexer = PuppetLint::Lexer.new
53
38
  @tokens = lexer.tokenise(data)
54
39
  @fileinfo = fileinfo
55
40
  @data = data
41
+ end
42
+
43
+ def run(fileinfo, data)
44
+ load_data(fileinfo, data)
56
45
 
57
46
  enabled_checks.each do |check|
58
47
  @default_info[:check] = check
@@ -230,10 +219,11 @@ class PuppetLint::CheckPlugin
230
219
  def manifest_lines
231
220
  @manifest_lines ||= @data.split("\n")
232
221
  end
222
+ end
233
223
 
224
+ class PuppetLint::CheckPlugin
234
225
  def self.check(name, &b)
235
- PuppetLint.configuration.add_check name
236
- define_method("lint_check_#{name}", b)
226
+ PuppetLint.configuration.add_check(name, &b)
237
227
  end
238
228
  end
239
229
 
@@ -73,16 +73,20 @@ class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
73
73
  depth = 0
74
74
  lparen_idx = nil
75
75
  rparen_idx = nil
76
- tokens[token_idx..-1].each_index do |t|
77
- idx = token_idx + t
78
- if tokens[idx].type == :LPAREN
79
- depth += 1
80
- lparen_idx = idx if depth == 1
81
- elsif tokens[idx].type == :RPAREN
82
- depth -= 1
83
- if depth == 0
84
- rparen_idx = idx
85
- break
76
+ class_name_token = tokens[class_idx[:start]].next_code_token
77
+
78
+ if class_name_token.next_code_token.type == :LPAREN
79
+ tokens[token_idx..-1].each_index do |t|
80
+ idx = token_idx + t
81
+ if tokens[idx].type == :LPAREN
82
+ depth += 1
83
+ lparen_idx = idx if depth == 1
84
+ elsif tokens[idx].type == :RPAREN
85
+ depth -= 1
86
+ if depth == 0
87
+ rparen_idx = idx
88
+ break
89
+ end
86
90
  end
87
91
  end
88
92
  end
@@ -1,28 +1,24 @@
1
1
  class PuppetLint::Plugins::CheckDocumentation < PuppetLint::CheckPlugin
2
- def whitespace_tokens
3
- @whitespace_tokens ||= {
4
- :WHITESPACE => true,
5
- :NEWLINE => true,
6
- :INDENT => true,
7
- }
8
- end
9
-
10
- def comment_tokens
11
- @comment_tokens ||= {
2
+ check 'documentation' do
3
+ comment_tokens = {
12
4
  :COMMENT => true,
13
5
  :MLCOMMENT => true,
14
6
  :SLASH_COMMENT => true,
15
7
  }
16
- end
17
8
 
18
- check 'documentation' do
9
+ whitespace_tokens = {
10
+ :WHITESPACE => true,
11
+ :NEWLINE => true,
12
+ :INDENT => true,
13
+ }
14
+
19
15
  (class_indexes + defined_type_indexes).each do |item_idx|
20
16
  prev_token = tokens[item_idx[:start] - 1]
21
- while whitespace_tokens.include? prev_token.type
17
+ while (!prev_token.nil?) && whitespace_tokens.include?(prev_token.type)
22
18
  prev_token = prev_token.prev_token
23
19
  end
24
20
 
25
- unless comment_tokens.include? prev_token.type
21
+ unless (!prev_token.nil?) && comment_tokens.include?(prev_token.type)
26
22
  first_token = tokens[item_idx[:start]]
27
23
  if first_token.type == :CLASS
28
24
  type = 'class'
@@ -22,17 +22,18 @@ class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
22
22
  # Returns nothing.
23
23
  check 'ensure_first_param' do
24
24
  resource_indexes.each do |resource|
25
- resource_tokens = tokens[resource[:start]..resource[:end]].reject { |r|
26
- formatting_tokens.include? r.type
27
- }
25
+ resource_tokens = tokens[resource[:start]..resource[:end]]
28
26
 
29
- ensure_attr_index = resource_tokens.index { |token|
30
- token.type == :NAME and token.value == 'ensure'
27
+ param_tokens = resource_tokens.select { |resource_token|
28
+ resource_token.type == :NAME && resource_token.next_code_token.type == :FARROW
29
+ }
30
+ ensure_attr_index = param_tokens.index { |resource_token|
31
+ resource_token.value == 'ensure'
31
32
  }
32
33
 
33
34
  unless ensure_attr_index.nil?
34
- if ensure_attr_index > 1
35
- ensure_token = resource_tokens[ensure_attr_index]
35
+ if ensure_attr_index > 0
36
+ ensure_token = param_tokens[ensure_attr_index]
36
37
  notify :warning, {
37
38
  :message => "ensure found on line but it's not the first attribute",
38
39
  :linenumber => ensure_token.line,
@@ -75,31 +76,25 @@ class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
75
76
  # Returns nothing.
76
77
  check 'unquoted_file_mode' do
77
78
  resource_indexes.each do |resource|
78
- resource_tokens = tokens[resource[:start]..resource[:end]].reject { |r|
79
- formatting_tokens.include? r.type
80
- }
81
-
82
- stripped_tokens = tokens[0..resource[:start]].reject { |r|
83
- formatting_tokens.include? r.type
84
- }
79
+ resource_tokens = tokens[resource[:start]..resource[:end]]
80
+ prev_tokens = tokens[0..resource[:start]]
85
81
 
86
- res_type_idx = stripped_tokens.rindex { |r|
82
+ lbrace_idx = prev_tokens.rindex { |r|
87
83
  r.type == :LBRACE
88
- } - 1
84
+ }
89
85
 
90
- resource_type_token = stripped_tokens[res_type_idx]
86
+ resource_type_token = tokens[lbrace_idx].prev_code_token
91
87
  if resource_type_token.value == "file"
92
- resource_tokens.each_index do |resource_token_idx|
93
- attr_token = resource_tokens[resource_token_idx]
94
- if attr_token.type == :NAME and attr_token.value == 'mode'
95
- value_token = resource_tokens[resource_token_idx + 2]
96
- if {:NAME => true, :NUMBER => true}.include? value_token.type
97
- notify :warning, {
98
- :message => 'unquoted file mode',
99
- :linenumber => value_token.line,
100
- :column => value_token.column,
101
- }
102
- end
88
+ resource_tokens.select { |resource_token|
89
+ resource_token.type == :NAME and resource_token.value == 'mode'
90
+ }.each do |resource_token|
91
+ value_token = resource_token.next_code_token.next_code_token
92
+ if {:NAME => true, :NUMBER => true}.include? value_token.type
93
+ notify :warning, {
94
+ :message => 'unquoted file mode',
95
+ :linenumber => value_token.line,
96
+ :column => value_token.column,
97
+ }
103
98
  end
104
99
  end
105
100
  end
@@ -116,36 +111,30 @@ class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
116
111
  sym_mode = /\A([ugoa]*[-=+][-=+rstwxXugo]*)(,[ugoa]*[-=+][-=+rstwxXugo]*)*\Z/
117
112
 
118
113
  resource_indexes.each do |resource|
119
- resource_tokens = tokens[resource[:start]..resource[:end]].reject { |r|
120
- formatting_tokens.include? r.type
121
- }
122
-
123
- stripped_tokens = tokens[0..resource[:start]].reject { |r|
124
- formatting_tokens.include? r.type
125
- }
114
+ resource_tokens = tokens[resource[:start]..resource[:end]]
115
+ prev_tokens = tokens[0..resource[:start]]
126
116
 
127
- res_type_idx = stripped_tokens.rindex { |r|
117
+ lbrace_idx = prev_tokens.rindex { |r|
128
118
  r.type == :LBRACE
129
- } - 1
119
+ }
130
120
 
131
- resource_type_token = stripped_tokens[res_type_idx]
121
+ resource_type_token = tokens[lbrace_idx].prev_code_token
132
122
  if resource_type_token.value == "file"
133
- resource_tokens.each_index do |resource_token_idx|
134
- attr_token = resource_tokens[resource_token_idx]
135
- if attr_token.type == :NAME and attr_token.value == 'mode'
136
- value_token = resource_tokens[resource_token_idx + 2]
123
+ resource_tokens.select { |resource_token|
124
+ resource_token.type == :NAME and resource_token.value == 'mode'
125
+ }.each do |resource_token|
126
+ value_token = resource_token.next_code_token.next_code_token
137
127
 
138
- break if value_token.value =~ /\A[0-7]{4}\Z/
139
- break if value_token.type == :VARIABLE
140
- break if value_token.value =~ sym_mode
141
- break if value_token.type == :UNDEF
128
+ break if value_token.value =~ /\A[0-7]{4}\Z/
129
+ break if value_token.type == :VARIABLE
130
+ break if value_token.value =~ sym_mode
131
+ break if value_token.type == :UNDEF
142
132
 
143
- notify :warning, {
144
- :message => msg,
145
- :linenumber => value_token.line,
146
- :column => value_token.column,
147
- }
148
- end
133
+ notify :warning, {
134
+ :message => msg,
135
+ :linenumber => value_token.line,
136
+ :column => value_token.column,
137
+ }
149
138
  end
150
139
  end
151
140
  end
@@ -158,31 +147,25 @@ class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
158
147
  # Returns nothing.
159
148
  check 'ensure_not_symlink_target' do
160
149
  resource_indexes.each do |resource|
161
- resource_tokens = tokens[resource[:start]..resource[:end]].reject { |r|
162
- formatting_tokens.include? r.type
163
- }
164
-
165
- stripped_tokens = tokens[0..resource[:start]].reject { |r|
166
- formatting_tokens.include? r.type
167
- }
150
+ resource_tokens = tokens[resource[:start]..resource[:end]]
151
+ prev_tokens = tokens[0..resource[:start]]
168
152
 
169
- res_type_idx = stripped_tokens.rindex { |r|
153
+ lbrace_idx = prev_tokens.rindex { |r|
170
154
  r.type == :LBRACE
171
- } - 1
155
+ }
172
156
 
173
- resource_type_token = stripped_tokens[res_type_idx]
157
+ resource_type_token = tokens[lbrace_idx].prev_code_token
174
158
  if resource_type_token.value == "file"
175
- resource_tokens.each_index do |resource_token_idx|
176
- attr_token = resource_tokens[resource_token_idx]
177
- if attr_token.type == :NAME and attr_token.value == 'ensure'
178
- value_token = resource_tokens[resource_token_idx + 2]
179
- if value_token.value.start_with? '/'
180
- notify :warning, {
181
- :message => 'symlink target specified in ensure attr',
182
- :linenumber => value_token.line,
183
- :column => value_token.column,
184
- }
185
- end
159
+ resource_tokens.select { |resource_token|
160
+ resource_token.type == :NAME and resource_token.value == 'ensure'
161
+ }.each do |ensure_token|
162
+ value_token = ensure_token.next_code_token.next_code_token
163
+ if value_token.value.start_with? '/'
164
+ notify :warning, {
165
+ :message => 'symlink target specified in ensure attr',
166
+ :linenumber => value_token.line,
167
+ :column => value_token.column,
168
+ }
186
169
  end
187
170
  end
188
171
  end
@@ -1,3 +1,3 @@
1
1
  class PuppetLint
2
- VERSION = '0.2.0'
2
+ VERSION = '0.2.1'
3
3
  end
@@ -4,7 +4,8 @@ describe PuppetLint::Configuration do
4
4
  subject { PuppetLint::Configuration.new }
5
5
 
6
6
  it 'should create check methods on the fly' do
7
- subject.add_check('foo')
7
+ method = Proc.new { true }
8
+ subject.add_check('foo', &method)
8
9
 
9
10
  subject.should respond_to(:foo_enabled?)
10
11
  subject.should_not respond_to(:bar_enabled?)
@@ -21,6 +22,8 @@ describe PuppetLint::Configuration do
21
22
  end
22
23
 
23
24
  it 'should know what checks have been added' do
25
+ method = Proc.new { true }
26
+ subject.add_check('foo', &method)
24
27
  subject.checks.should include('foo')
25
28
  end
26
29
 
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'autoloader_layout' do
4
+ describe 'foo::bar in foo/manifests/bar.pp' do
5
+ let(:code) { "class foo::bar { }" }
6
+ let(:fullpath) { '/etc/puppet/modules/foo/manifests/bar.pp' }
7
+
8
+ its(:problems) { should be_empty }
9
+ end
10
+
11
+ describe 'foo::bar::baz in foo/manifests/bar/baz.pp' do
12
+ let(:code) { 'define foo::bar::baz() { }' }
13
+ let(:fullpath) { '/etc/puppet/modules/foo/manifests/bar/baz.pp' }
14
+
15
+ its(:problems) { should be_empty }
16
+ end
17
+
18
+ describe 'foo in foo/manifests/init.pp' do
19
+ let(:code) { 'class foo { }' }
20
+ let(:fullpath) { '/etc/puppet/modules/foo/manifests/init.pp' }
21
+
22
+ its(:problems) { should be_empty }
23
+ end
24
+
25
+ describe 'foo::bar in foo/manifests/init.pp' do
26
+ let(:code) { 'class foo::bar { }' }
27
+ let(:fullpath) { '/etc/puppet/modules/foo/manifests/init.pp' }
28
+
29
+ its(:problems) {
30
+ should only_have_problem({
31
+ :kind => :error,
32
+ :message => "foo::bar not in autoload module layout",
33
+ :linenumber => 1,
34
+ :column => 7,
35
+ })
36
+ }
37
+ end
38
+
39
+ describe 'foo included in bar/manifests/init.pp' do
40
+ let(:code) { "
41
+ class bar {
42
+ class {'foo':
43
+ someparam => 'somevalue',
44
+ }
45
+ }
46
+ "
47
+ }
48
+ let(:fullpath) { '/etc/puppet/modules/bar/manifests/init.pp' }
49
+ its(:problems) { should be_empty }
50
+ end
51
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'inherits_across_namespaces' do
4
+ describe 'class inheriting from its namespace' do
5
+ let(:code) { "class foo::bar inherits foo { }" }
6
+
7
+ its(:problems) { should be_empty }
8
+ end
9
+
10
+ describe 'class inheriting from another namespace' do
11
+ let(:code) { "class foo::bar inherits baz { }" }
12
+
13
+ its(:problems) {
14
+ should have_problem({
15
+ :kind => :warning,
16
+ :message => "class inherits across namespaces",
17
+ :linenumber => 1,
18
+ :column => 25,
19
+ })
20
+ should_not have_problem :kind => :error
21
+ }
22
+ end
23
+ end