puppet-lint 0.1.13 → 0.2.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|