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