puppet-lint 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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