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.
- data/lib/puppet-lint.rb +1 -3
- data/lib/puppet-lint/configuration.rb +7 -6
- data/lib/puppet-lint/plugin.rb +14 -24
- data/lib/puppet-lint/plugins/check_classes.rb +14 -10
- data/lib/puppet-lint/plugins/check_documentation.rb +10 -14
- data/lib/puppet-lint/plugins/check_resources.rb +56 -73
- data/lib/puppet-lint/version.rb +1 -1
- data/spec/puppet-lint/configuration_spec.rb +4 -1
- data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +51 -0
- data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +23 -0
- data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +45 -0
- data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +71 -0
- data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +67 -0
- data/spec/puppet-lint/plugins/check_classes/parameterised_classes_spec.rb +43 -0
- data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +23 -0
- data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +93 -0
- data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +16 -0
- data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +19 -0
- data/spec/puppet-lint/plugins/{check_conditionals_spec.rb → check_conditionals/case_without_default_spec.rb} +1 -39
- data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +33 -0
- data/spec/puppet-lint/plugins/{check_documentation_spec.rb → check_documentation/documentation_spec.rb} +1 -9
- data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +23 -0
- data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +43 -0
- data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +26 -0
- data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +43 -0
- data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +11 -0
- data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +110 -0
- data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +83 -0
- data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +16 -0
- data/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb +55 -0
- data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +16 -0
- data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +29 -0
- data/spec/puppet-lint/plugins/{check_variables_spec.rb → check_variables/variable_contains_dash_spec.rb} +1 -9
- data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +20 -0
- data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +38 -0
- data/spec/puppet-lint/plugins/{check_whitespace_spec.rb → check_whitespace/arrow_alignment_spec.rb} +1 -86
- data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +16 -0
- data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +16 -0
- data/spec/spec_helper.rb +17 -0
- metadata +122 -92
- data/spec/puppet-lint/plugins/check_classes_spec.rb +0 -390
- data/spec/puppet-lint/plugins/check_comments_spec.rb +0 -40
- data/spec/puppet-lint/plugins/check_resources_spec.rb +0 -249
- data/spec/puppet-lint/plugins/check_strings_spec.rb +0 -175
data/lib/puppet-lint.rb
CHANGED
@@ -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
|
-
|
51
|
-
method =~ /^.+_enabled\?$/
|
52
|
-
}.map { |method|
|
53
|
-
method[0..-10]
|
54
|
-
}
|
55
|
+
check_method.keys
|
55
56
|
end
|
56
57
|
|
57
58
|
def defaults
|
data/lib/puppet-lint/plugin.rb
CHANGED
@@ -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
|
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
|
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[
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
3
|
-
|
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
|
-
|
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?
|
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?
|
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]]
|
26
|
-
formatting_tokens.include? r.type
|
27
|
-
}
|
25
|
+
resource_tokens = tokens[resource[:start]..resource[:end]]
|
28
26
|
|
29
|
-
|
30
|
-
|
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 >
|
35
|
-
ensure_token =
|
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]]
|
79
|
-
|
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
|
-
|
82
|
+
lbrace_idx = prev_tokens.rindex { |r|
|
87
83
|
r.type == :LBRACE
|
88
|
-
}
|
84
|
+
}
|
89
85
|
|
90
|
-
resource_type_token =
|
86
|
+
resource_type_token = tokens[lbrace_idx].prev_code_token
|
91
87
|
if resource_type_token.value == "file"
|
92
|
-
resource_tokens.
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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]]
|
120
|
-
|
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
|
-
|
117
|
+
lbrace_idx = prev_tokens.rindex { |r|
|
128
118
|
r.type == :LBRACE
|
129
|
-
}
|
119
|
+
}
|
130
120
|
|
131
|
-
resource_type_token =
|
121
|
+
resource_type_token = tokens[lbrace_idx].prev_code_token
|
132
122
|
if resource_type_token.value == "file"
|
133
|
-
resource_tokens.
|
134
|
-
|
135
|
-
|
136
|
-
|
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
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
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
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
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]]
|
162
|
-
|
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
|
-
|
153
|
+
lbrace_idx = prev_tokens.rindex { |r|
|
170
154
|
r.type == :LBRACE
|
171
|
-
}
|
155
|
+
}
|
172
156
|
|
173
|
-
resource_type_token =
|
157
|
+
resource_type_token = tokens[lbrace_idx].prev_code_token
|
174
158
|
if resource_type_token.value == "file"
|
175
|
-
resource_tokens.
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
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
|
data/lib/puppet-lint/version.rb
CHANGED
@@ -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
|
-
|
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
|