puppet-lint 0.1.13 → 0.2.0.pre1
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/.gitignore +5 -0
- data/README.md +19 -5
- data/bin/puppet-lint +2 -0
- data/lib/puppet-lint.rb +2 -11
- data/lib/puppet-lint/configuration.rb +4 -0
- data/lib/puppet-lint/lexer.rb +244 -0
- data/lib/puppet-lint/plugin.rb +125 -54
- data/lib/puppet-lint/plugins/check_classes.rb +135 -49
- data/lib/puppet-lint/plugins/check_conditionals.rb +34 -23
- data/lib/puppet-lint/plugins/check_resources.rb +114 -28
- data/lib/puppet-lint/plugins/check_strings.rb +67 -79
- data/lib/puppet-lint/plugins/check_variables.rb +13 -18
- data/lib/puppet-lint/plugins/check_whitespace.rb +70 -40
- data/lib/puppet-lint/tasks/puppet-lint.rb +11 -3
- data/lib/puppet-lint/version.rb +3 -0
- data/puppet-lint.gemspec +8 -29
- data/spec/puppet-lint/check_classes_spec.rb +72 -23
- data/spec/puppet-lint/check_conditionals_spec.rb +19 -3
- data/spec/puppet-lint/check_resources_spec.rb +9 -16
- data/spec/puppet-lint/check_strings_spec.rb +94 -7
- data/spec/puppet-lint/check_variables_spec.rb +20 -10
- data/spec/puppet-lint/check_whitespace_spec.rb +13 -0
- data/spec/spec_helper.rb +15 -10
- metadata +30 -17
@@ -1,49 +1,80 @@
|
|
1
1
|
class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
# Public: Test the manifest tokens for any right-to-left (<-) chaining
|
3
|
+
# operators and record a warning for each instance found.
|
4
|
+
#
|
5
|
+
# Returns nothing.
|
6
|
+
check 'right_to_left_relationship' do
|
7
|
+
tokens.select { |r| r.type == :OUT_EDGE }.each do |token|
|
8
|
+
notify :warning, {
|
9
|
+
:message => 'right-to-left (<-) relationship',
|
10
|
+
:linenumber => token.line,
|
11
|
+
:column => token.column,
|
12
|
+
}
|
7
13
|
end
|
8
14
|
end
|
9
15
|
|
16
|
+
# Public: Test the manifest tokens for any classes or defined types that are
|
17
|
+
# not in an appropriately named file for the autoloader to detect and record
|
18
|
+
# an error of each instance found.
|
19
|
+
#
|
20
|
+
# Returns nothing.
|
10
21
|
check 'autoloader_layout' do
|
11
|
-
unless fullpath ==
|
22
|
+
unless fullpath == ''
|
12
23
|
(class_indexes + defined_type_indexes).each do |class_idx|
|
13
|
-
|
14
|
-
|
24
|
+
class_tokens = tokens[class_idx[:start]..class_idx[:end]]
|
25
|
+
title_token = class_tokens[class_tokens.index { |r| r.type == :NAME }]
|
26
|
+
split_title = title_token.value.split('::')
|
27
|
+
mod = split_title.first
|
15
28
|
if split_title.length > 1
|
16
|
-
expected_path = "#{
|
29
|
+
expected_path = "#{mod}/manifests/#{split_title[1..-1].join('/')}.pp"
|
17
30
|
else
|
18
|
-
expected_path = "#{title_token.
|
31
|
+
expected_path = "#{title_token.value}/manifests/init.pp"
|
19
32
|
end
|
20
33
|
|
21
34
|
unless fullpath.end_with? expected_path
|
22
|
-
notify :error,
|
35
|
+
notify :error, {
|
36
|
+
:message => "#{title_token.value} not in autoload module layout",
|
37
|
+
:linenumber => title_token.line,
|
38
|
+
:column => title_token.column,
|
39
|
+
}
|
23
40
|
end
|
24
41
|
end
|
25
42
|
end
|
26
43
|
end
|
27
44
|
|
45
|
+
# Public: Test the manifest tokens for any parameterised classes or defined
|
46
|
+
# types that take parameters and record a warning if there are any optional
|
47
|
+
# parameters listed before required parameters.
|
48
|
+
#
|
49
|
+
# Returns nothing.
|
28
50
|
check 'parameter_order' do
|
29
51
|
(class_indexes + defined_type_indexes).each do |class_idx|
|
30
52
|
token_idx = class_idx[:start]
|
31
|
-
header_end_idx = tokens[token_idx..-1].index { |r| r.
|
32
|
-
|
33
|
-
|
53
|
+
header_end_idx = tokens[token_idx..-1].index { |r| r.type == :LBRACE }
|
54
|
+
header_tokens = tokens[token_idx..header_end_idx].reject { |r|
|
55
|
+
formatting_tokens.include?(r.type)
|
56
|
+
}
|
57
|
+
lparen_idx = header_tokens.index { |r| r.type == :LPAREN }
|
58
|
+
rparen_idx = header_tokens.rindex { |r| r.type == :RPAREN }
|
34
59
|
|
35
60
|
unless lparen_idx.nil? or rparen_idx.nil?
|
36
|
-
param_tokens =
|
61
|
+
param_tokens = header_tokens[lparen_idx..rparen_idx]
|
37
62
|
param_tokens.each_index do |param_tokens_idx|
|
38
63
|
this_token = param_tokens[param_tokens_idx]
|
39
64
|
next_token = param_tokens[param_tokens_idx+1]
|
40
65
|
prev_token = param_tokens[param_tokens_idx-1]
|
41
|
-
if this_token.
|
66
|
+
if this_token.type == :VARIABLE
|
42
67
|
unless next_token.nil?
|
43
|
-
if next_token.
|
44
|
-
|
45
|
-
|
46
|
-
|
68
|
+
if next_token.type == :COMMA or next_token.type == :RPAREN
|
69
|
+
prev_tokens = param_tokens[0..param_tokens_idx]
|
70
|
+
unless prev_tokens.rindex { |r| r.type == :EQUALS }.nil?
|
71
|
+
unless prev_token.nil? or prev_token.type == :EQUALS
|
72
|
+
msg = 'optional parameter listed before required parameter'
|
73
|
+
notify :warning, {
|
74
|
+
:message => msg,
|
75
|
+
:linenumber => this_token.line,
|
76
|
+
:column => this_token.column,
|
77
|
+
}
|
47
78
|
end
|
48
79
|
end
|
49
80
|
end
|
@@ -54,57 +85,107 @@ class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
|
|
54
85
|
end
|
55
86
|
end
|
56
87
|
|
88
|
+
# Public: Test the manifest tokens for any classes that inherit across
|
89
|
+
# namespaces and record a warning for each instance found.
|
90
|
+
#
|
91
|
+
# Returns nothing.
|
57
92
|
check 'inherits_across_namespaces' do
|
58
93
|
class_indexes.each do |class_idx|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
94
|
+
class_tokens = tokens[class_idx[:start]..class_idx[:end]].reject { |r|
|
95
|
+
formatting_tokens.include?(r.type)
|
96
|
+
}
|
97
|
+
|
98
|
+
if class_tokens[2].type == :INHERITS
|
99
|
+
class_name = class_tokens[1].value
|
100
|
+
inherited_class = class_tokens[3].value
|
63
101
|
|
64
102
|
unless class_name =~ /^#{inherited_class}::/
|
65
|
-
notify :warning,
|
103
|
+
notify :warning, {
|
104
|
+
:message => "class inherits across namespaces",
|
105
|
+
:linenumber => class_tokens[3].line,
|
106
|
+
:column => class_tokens[3].column,
|
107
|
+
}
|
66
108
|
end
|
67
109
|
end
|
68
110
|
end
|
69
111
|
end
|
70
112
|
|
113
|
+
# Public: Test the manifest tokens for any classes or defined types that are
|
114
|
+
# defined inside another class.
|
115
|
+
#
|
116
|
+
# Returns nothing.
|
71
117
|
check 'nested_classes_or_defines' do
|
72
118
|
class_indexes.each do |class_idx|
|
73
|
-
|
74
|
-
class_tokens[1
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
119
|
+
# Skip the first token so that we don't pick up the first :CLASS
|
120
|
+
class_tokens = tokens[class_idx[:start]+1..class_idx[:end]].reject { |r|
|
121
|
+
formatting_tokens.include?(r.type)
|
122
|
+
}
|
123
|
+
|
124
|
+
class_tokens.each_index do |token_idx|
|
125
|
+
token = class_tokens[token_idx]
|
126
|
+
next_token = class_tokens[token_idx + 1]
|
127
|
+
|
128
|
+
if token.type == :CLASS
|
129
|
+
if next_token.type != :LBRACE
|
130
|
+
notify :warning, {
|
131
|
+
:message => "class defined inside a class",
|
132
|
+
:linenumber => token.line,
|
133
|
+
:column => token.column,
|
134
|
+
}
|
81
135
|
end
|
82
136
|
end
|
83
137
|
|
84
|
-
if token.
|
85
|
-
notify :warning,
|
138
|
+
if token.type == :DEFINE
|
139
|
+
notify :warning, {
|
140
|
+
:message => "define defined inside a class",
|
141
|
+
:linenumber => token.line,
|
142
|
+
:column => token.column,
|
143
|
+
}
|
86
144
|
end
|
87
145
|
end
|
88
146
|
end
|
89
147
|
end
|
90
148
|
|
149
|
+
# Public: Test the manifest tokens for any variables that are referenced in
|
150
|
+
# the manifest. If the variables are not fully qualified or one of the
|
151
|
+
# variables automatically created in the scope, check that they have been
|
152
|
+
# defined in the local scope and record a warning for each variable that has
|
153
|
+
# not.
|
154
|
+
#
|
155
|
+
# Returns nothing.
|
91
156
|
check 'variable_scope' do
|
157
|
+
variables_in_scope = [
|
158
|
+
'name',
|
159
|
+
'title',
|
160
|
+
'module_name',
|
161
|
+
'environment',
|
162
|
+
'clientcert',
|
163
|
+
'clientversion',
|
164
|
+
'servername',
|
165
|
+
'serverip',
|
166
|
+
'serverversion',
|
167
|
+
'caller_module_name',
|
168
|
+
]
|
92
169
|
(class_indexes + defined_type_indexes).each do |idx|
|
93
170
|
object_tokens = tokens[idx[:start]..idx[:end]]
|
94
|
-
|
171
|
+
object_tokens.reject! { |r| formatting_tokens.include?(r.type) }
|
95
172
|
referenced_variables = []
|
96
|
-
header_end_idx = object_tokens.index { |r| r.
|
97
|
-
lparen_idx = object_tokens[0..header_end_idx].index { |r|
|
98
|
-
|
173
|
+
header_end_idx = object_tokens.index { |r| r.type == :LBRACE }
|
174
|
+
lparen_idx = object_tokens[0..header_end_idx].index { |r|
|
175
|
+
r.type == :LPAREN
|
176
|
+
}
|
177
|
+
rparen_idx = object_tokens[0..header_end_idx].rindex { |r|
|
178
|
+
r.type == :RPAREN
|
179
|
+
}
|
99
180
|
|
100
181
|
unless lparen_idx.nil? or rparen_idx.nil?
|
101
182
|
param_tokens = object_tokens[lparen_idx..rparen_idx]
|
102
183
|
param_tokens.each_index do |param_tokens_idx|
|
103
184
|
this_token = param_tokens[param_tokens_idx]
|
104
185
|
next_token = param_tokens[param_tokens_idx+1]
|
105
|
-
if this_token.
|
106
|
-
if [:COMMA, :EQUALS, :RPAREN].include? next_token.
|
107
|
-
variables_in_scope << this_token.
|
186
|
+
if this_token.type == :VARIABLE
|
187
|
+
if [:COMMA, :EQUALS, :RPAREN].include? next_token.type
|
188
|
+
variables_in_scope << this_token.value
|
108
189
|
end
|
109
190
|
end
|
110
191
|
end
|
@@ -114,20 +195,25 @@ class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
|
|
114
195
|
this_token = object_tokens[object_token_idx]
|
115
196
|
next_token = object_tokens[object_token_idx + 1]
|
116
197
|
|
117
|
-
if this_token.
|
118
|
-
if next_token.
|
119
|
-
variables_in_scope << this_token.
|
198
|
+
if this_token.type == :VARIABLE
|
199
|
+
if next_token.type == :EQUALS
|
200
|
+
variables_in_scope << this_token.value
|
120
201
|
else
|
121
202
|
referenced_variables << this_token
|
122
203
|
end
|
123
204
|
end
|
124
205
|
end
|
125
206
|
|
207
|
+
msg = "top-scope variable being used without an explicit namespace"
|
126
208
|
referenced_variables.each do |token|
|
127
|
-
unless token.
|
128
|
-
unless variables_in_scope.include? token.
|
129
|
-
unless token.
|
130
|
-
notify :warning,
|
209
|
+
unless token.value.include? '::'
|
210
|
+
unless variables_in_scope.include? token.value
|
211
|
+
unless token.value =~ /\d+/
|
212
|
+
notify :warning, {
|
213
|
+
:message => msg,
|
214
|
+
:linenumber => token.line,
|
215
|
+
:column => token.column,
|
216
|
+
}
|
131
217
|
end
|
132
218
|
end
|
133
219
|
end
|
@@ -1,14 +1,24 @@
|
|
1
1
|
class PuppetLint::Plugins::CheckConditionals < PuppetLint::CheckPlugin
|
2
|
+
# Public: Test the manifest tokens for any selectors embedded within resource
|
3
|
+
# declarations and record a warning for each instance found.
|
4
|
+
#
|
5
|
+
# Returns nothing.
|
2
6
|
check 'selector_inside_resource' do
|
3
7
|
resource_indexes.each do |resource|
|
4
|
-
resource_tokens = tokens[resource[:start]..resource[:end]]
|
8
|
+
resource_tokens = tokens[resource[:start]..resource[:end]].reject { |r|
|
9
|
+
formatting_tokens.include? r.type
|
10
|
+
}
|
5
11
|
|
6
12
|
resource_tokens.each_index do |resource_token_idx|
|
7
|
-
if resource_tokens[resource_token_idx].
|
8
|
-
if resource_tokens[resource_token_idx + 1].
|
13
|
+
if resource_tokens[resource_token_idx].type == :FARROW
|
14
|
+
if resource_tokens[resource_token_idx + 1].type == :VARIABLE
|
9
15
|
unless resource_tokens[resource_token_idx + 2].nil?
|
10
|
-
if resource_tokens[resource_token_idx + 2].
|
11
|
-
notify :warning,
|
16
|
+
if resource_tokens[resource_token_idx + 2].type == :QMARK
|
17
|
+
notify :warning, {
|
18
|
+
:message => 'selector inside resource block',
|
19
|
+
:linenumber => resource_tokens[resource_token_idx].line,
|
20
|
+
:column => resource_tokens[resource_token_idx].column,
|
21
|
+
}
|
12
22
|
end
|
13
23
|
end
|
14
24
|
end
|
@@ -17,26 +27,23 @@ class PuppetLint::Plugins::CheckConditionals < PuppetLint::CheckPlugin
|
|
17
27
|
end
|
18
28
|
end
|
19
29
|
|
30
|
+
# Public: Test the manifest tokens for any case statements that do not
|
31
|
+
# contain a "default" case and record a warning for each instance found.
|
32
|
+
#
|
33
|
+
# Returns nothing.
|
20
34
|
check 'case_without_default' do
|
21
35
|
case_indexes = []
|
22
36
|
|
23
37
|
tokens.each_index do |token_idx|
|
24
|
-
if tokens[token_idx].
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
tokens[token_idx+1..-1].each_index do |case_token_idx|
|
34
|
-
idx = case_token_idx + token_idx
|
35
|
-
if tokens[idx].first == :LBRACE
|
36
|
-
lbrace_count += 1
|
37
|
-
elsif tokens[idx].first == :RBRACE
|
38
|
-
lbrace_count -= 1
|
39
|
-
if lbrace_count == 0
|
38
|
+
if tokens[token_idx].type == :CASE
|
39
|
+
depth = 0
|
40
|
+
tokens[(token_idx + 1)..-1].each_index do |case_token_idx|
|
41
|
+
idx = case_token_idx + token_idx + 1
|
42
|
+
if tokens[idx].type == :LBRACE
|
43
|
+
depth += 1
|
44
|
+
elsif tokens[idx].type == :RBRACE
|
45
|
+
depth -= 1
|
46
|
+
if depth == 0
|
40
47
|
case_indexes << {:start => token_idx, :end => idx}
|
41
48
|
break
|
42
49
|
end
|
@@ -48,8 +55,12 @@ class PuppetLint::Plugins::CheckConditionals < PuppetLint::CheckPlugin
|
|
48
55
|
case_indexes.each do |kase|
|
49
56
|
case_tokens = tokens[kase[:start]..kase[:end]]
|
50
57
|
|
51
|
-
unless case_tokens.index { |r| r.
|
52
|
-
notify :warning,
|
58
|
+
unless case_tokens.index { |r| r.type == :DEFAULT }
|
59
|
+
notify :warning, {
|
60
|
+
:message => 'case statement without a default case',
|
61
|
+
:linenumber => case_tokens.first.line,
|
62
|
+
:column => case_tokens.first.column,
|
63
|
+
}
|
53
64
|
end
|
54
65
|
end
|
55
66
|
end
|
@@ -1,39 +1,79 @@
|
|
1
|
-
# Resources
|
2
|
-
# http://docs.puppetlabs.com/guides/style_guide.html#resources
|
3
|
-
|
4
1
|
class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
|
2
|
+
# Public: Check the manifest tokens for any resource titles / namevars that
|
3
|
+
# are not quoted and record a warning for each instance found.
|
4
|
+
#
|
5
|
+
# Return nothing.
|
5
6
|
check 'unquoted_resource_title' do
|
6
7
|
title_tokens.each do |token|
|
7
|
-
if token.
|
8
|
-
notify :warning,
|
8
|
+
if token.type == :NAME
|
9
|
+
notify :warning, {
|
10
|
+
:message => 'unquoted resource title',
|
11
|
+
:linenumber => token.line,
|
12
|
+
:column => token.column,
|
13
|
+
}
|
9
14
|
end
|
10
15
|
end
|
11
16
|
end
|
12
17
|
|
18
|
+
# Public: Check the tokens of each resource instance for an ensure parameter
|
19
|
+
# and if found, check that it is the first parameter listed. If it is not
|
20
|
+
# the first parameter, record a warning.
|
21
|
+
#
|
22
|
+
# Returns nothing.
|
13
23
|
check 'ensure_first_param' do
|
14
24
|
resource_indexes.each do |resource|
|
15
|
-
resource_tokens = tokens[resource[:start]..resource[:end]]
|
16
|
-
|
25
|
+
resource_tokens = tokens[resource[:start]..resource[:end]].reject { |r|
|
26
|
+
formatting_tokens.include? r.type
|
27
|
+
}
|
28
|
+
|
29
|
+
ensure_attr_index = resource_tokens.index { |token|
|
30
|
+
token.type == :NAME and token.value == 'ensure'
|
31
|
+
}
|
32
|
+
|
17
33
|
unless ensure_attr_index.nil?
|
18
34
|
if ensure_attr_index > 1
|
19
|
-
|
20
|
-
notify :warning,
|
35
|
+
ensure_token = resource_tokens[ensure_attr_index]
|
36
|
+
notify :warning, {
|
37
|
+
:message => "ensure found on line but it's not the first attribute",
|
38
|
+
:linenumber => ensure_token.line,
|
39
|
+
:column => ensure_token.column,
|
40
|
+
}
|
21
41
|
end
|
22
42
|
end
|
23
43
|
end
|
24
44
|
end
|
25
45
|
|
46
|
+
# Public: Check the tokens of each File resource instance for a mode
|
47
|
+
# parameter and if found, record a warning if the value of that parameter is
|
48
|
+
# not a quoted string.
|
49
|
+
#
|
50
|
+
# Returns nothing.
|
26
51
|
check 'unquoted_file_mode' do
|
27
52
|
resource_indexes.each do |resource|
|
28
|
-
resource_tokens = tokens[resource[:start]..resource[:end]]
|
29
|
-
|
30
|
-
|
53
|
+
resource_tokens = tokens[resource[:start]..resource[:end]].reject { |r|
|
54
|
+
formatting_tokens.include? r.type
|
55
|
+
}
|
56
|
+
|
57
|
+
stripped_tokens = tokens[0..resource[:start]].reject { |r|
|
58
|
+
formatting_tokens.include? r.type
|
59
|
+
}
|
60
|
+
|
61
|
+
res_type_idx = stripped_tokens.rindex { |r|
|
62
|
+
r.type == :LBRACE
|
63
|
+
} - 1
|
64
|
+
|
65
|
+
resource_type_token = stripped_tokens[res_type_idx]
|
66
|
+
if resource_type_token.value == "file"
|
31
67
|
resource_tokens.each_index do |resource_token_idx|
|
32
68
|
attr_token = resource_tokens[resource_token_idx]
|
33
|
-
if attr_token.
|
69
|
+
if attr_token.type == :NAME and attr_token.value == 'mode'
|
34
70
|
value_token = resource_tokens[resource_token_idx + 2]
|
35
|
-
if value_token.
|
36
|
-
notify :warning,
|
71
|
+
if value_token.type == :NAME
|
72
|
+
notify :warning, {
|
73
|
+
:message => 'unquoted file mode',
|
74
|
+
:linenumber => value_token.line,
|
75
|
+
:column => value_token.column,
|
76
|
+
}
|
37
77
|
end
|
38
78
|
end
|
39
79
|
end
|
@@ -41,35 +81,81 @@ class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
|
|
41
81
|
end
|
42
82
|
end
|
43
83
|
|
84
|
+
# Public: Check the tokens of each File resource instance for a mode
|
85
|
+
# parameter and if found, record a warning if the value of that parameter is
|
86
|
+
# not a 4 digit octal value (0755) or a symbolic mode ('o=rwx,g+r').
|
87
|
+
#
|
88
|
+
# Returns nothing.
|
44
89
|
check 'file_mode' do
|
90
|
+
msg = 'mode should be represented as a 4 digit octal value or symbolic mode'
|
91
|
+
sym_mode = /\A([ugoa]*[-=+][-=+rstwxXugo]*)(,[ugoa]*[-=+][-=+rstwxXugo]*)*\Z/
|
92
|
+
|
45
93
|
resource_indexes.each do |resource|
|
46
|
-
resource_tokens = tokens[resource[:start]..resource[:end]]
|
47
|
-
|
48
|
-
|
94
|
+
resource_tokens = tokens[resource[:start]..resource[:end]].reject { |r|
|
95
|
+
formatting_tokens.include? r.type
|
96
|
+
}
|
97
|
+
|
98
|
+
stripped_tokens = tokens[0..resource[:start]].reject { |r|
|
99
|
+
formatting_tokens.include? r.type
|
100
|
+
}
|
101
|
+
|
102
|
+
res_type_idx = stripped_tokens.rindex { |r|
|
103
|
+
r.type == :LBRACE
|
104
|
+
} - 1
|
105
|
+
|
106
|
+
resource_type_token = stripped_tokens[res_type_idx]
|
107
|
+
if resource_type_token.value == "file"
|
49
108
|
resource_tokens.each_index do |resource_token_idx|
|
50
109
|
attr_token = resource_tokens[resource_token_idx]
|
51
|
-
if attr_token.
|
110
|
+
if attr_token.type == :NAME and attr_token.value == 'mode'
|
52
111
|
value_token = resource_tokens[resource_token_idx + 2]
|
53
|
-
|
54
|
-
|
55
|
-
|
112
|
+
|
113
|
+
break if value_token.value =~ /\d{4}/
|
114
|
+
break if value_token.type == :VARIABLE
|
115
|
+
break if value_token.value =~ sym_mode
|
116
|
+
|
117
|
+
notify :warning, {
|
118
|
+
:message => msg,
|
119
|
+
:linenumber => value_token.line,
|
120
|
+
:column => value_token.column,
|
121
|
+
}
|
56
122
|
end
|
57
123
|
end
|
58
124
|
end
|
59
125
|
end
|
60
126
|
end
|
61
127
|
|
128
|
+
# Public: Check the tokens of each File resource instance for an ensure
|
129
|
+
# parameter and record a warning if the value of that parameter looks like
|
130
|
+
# a symlink target (starts with a '/').
|
131
|
+
#
|
132
|
+
# Returns nothing.
|
62
133
|
check 'ensure_not_symlink_target' do
|
63
134
|
resource_indexes.each do |resource|
|
64
|
-
resource_tokens = tokens[resource[:start]..resource[:end]]
|
65
|
-
|
66
|
-
|
135
|
+
resource_tokens = tokens[resource[:start]..resource[:end]].reject { |r|
|
136
|
+
formatting_tokens.include? r.type
|
137
|
+
}
|
138
|
+
|
139
|
+
stripped_tokens = tokens[0..resource[:start]].reject { |r|
|
140
|
+
formatting_tokens.include? r.type
|
141
|
+
}
|
142
|
+
|
143
|
+
res_type_idx = stripped_tokens.rindex { |r|
|
144
|
+
r.type == :LBRACE
|
145
|
+
} - 1
|
146
|
+
|
147
|
+
resource_type_token = stripped_tokens[res_type_idx]
|
148
|
+
if resource_type_token.value == "file"
|
67
149
|
resource_tokens.each_index do |resource_token_idx|
|
68
150
|
attr_token = resource_tokens[resource_token_idx]
|
69
|
-
if attr_token.
|
151
|
+
if attr_token.type == :NAME and attr_token.value == 'ensure'
|
70
152
|
value_token = resource_tokens[resource_token_idx + 2]
|
71
|
-
if value_token.
|
72
|
-
notify :warning,
|
153
|
+
if value_token.value.start_with? '/'
|
154
|
+
notify :warning, {
|
155
|
+
:message => 'symlink target specified in ensure attr',
|
156
|
+
:linenumber => value_token.line,
|
157
|
+
:column => value_token.column,
|
158
|
+
}
|
73
159
|
end
|
74
160
|
end
|
75
161
|
end
|