puppet-lint 0.1.9 → 0.1.10

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.
@@ -1,50 +1,47 @@
1
1
  class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
2
- def test(path, data)
3
- lexer = Puppet::Parser::Lexer.new
4
- lexer.string = data
5
- tokens = lexer.fullscan
6
-
2
+ check 'right_to_left_relationship' do
7
3
  tokens.select { |r| r.first == :OUT_EDGE }.each do |token|
8
- warn "right-to-left (<-) relationship on line #{token.last[:line]}"
4
+ notify :warning, :message => "right-to-left (<-) relationship", :linenumber => token.last[:line]
9
5
  end
6
+ end
10
7
 
11
- class_indexes = []
12
- defined_type_indexes = []
13
- tokens.each_index do |token_idx|
14
- if [:DEFINE, :CLASS].include? tokens[token_idx].first
15
- header_end_idx = tokens[token_idx..-1].index { |r| r.first == :LBRACE }
16
- lparen_idx = tokens[token_idx..(header_end_idx + token_idx)].index { |r| r.first == :LPAREN }
17
- rparen_idx = tokens[token_idx..(header_end_idx + token_idx)].rindex { |r| r.first == :RPAREN }
18
-
19
- unless path == ""
20
- title_token = tokens[token_idx+1]
21
- if [:CLASSNAME, :NAME].include? title_token.first
22
- split_title = title_token.last[:value].split('::')
23
- if split_title.length > 1
24
- expected_path = "#{split_title.first}/manifests/#{split_title[1..-1].join('/')}.pp"
25
- else
26
- expected_path = "#{title_token.last[:value]}/manifests/init.pp"
27
- end
8
+ check 'autoloader_layout' do
9
+ unless path == ""
10
+ (class_indexes + defined_type_indexes).each do |class_idx|
11
+ title_token = tokens[class_idx[:start]+1]
12
+ split_title = title_token.last[:value].split('::')
13
+ if split_title.length > 1
14
+ expected_path = "#{split_title.first}/manifests/#{split_title[1..-1].join('/')}.pp"
15
+ else
16
+ expected_path = "#{title_token.last[:value]}/manifests/init.pp"
17
+ end
28
18
 
29
- unless path.end_with? expected_path
30
- error "#{title_token.last[:value]} not in autoload module layout on line #{title_token.last[:line]}"
31
- end
32
- end
19
+ unless path.end_with? expected_path
20
+ notify :error, :message => "#{title_token.last[:value]} not in autoload module layout", :linenumber => title_token.last[:line]
33
21
  end
22
+ end
23
+ end
24
+ end
25
+
26
+ check 'parameter_order' do
27
+ (class_indexes + defined_type_indexes).each do |class_idx|
28
+ token_idx = class_idx[:start]
29
+ header_end_idx = tokens[token_idx..-1].index { |r| r.first == :LBRACE }
30
+ lparen_idx = tokens[token_idx..(header_end_idx + token_idx)].index { |r| r.first == :LPAREN }
31
+ rparen_idx = tokens[token_idx..(header_end_idx + token_idx)].rindex { |r| r.first == :RPAREN }
34
32
 
35
- unless lparen_idx.nil? or rparen_idx.nil?
36
- param_tokens = tokens[lparen_idx..rparen_idx]
37
- param_tokens.each_index do |param_tokens_idx|
38
- this_token = param_tokens[param_tokens_idx]
39
- next_token = param_tokens[param_tokens_idx+1]
40
- prev_token = param_tokens[param_tokens_idx-1]
41
- if this_token.first == :VARIABLE
42
- unless next_token.nil?
43
- if next_token.first == :COMMA or next_token.first == :RPAREN
44
- unless param_tokens[0..param_tokens_idx].rindex { |r| r.first == :EQUALS }.nil?
45
- unless prev_token.nil? or prev_token.first == :EQUALS
46
- warn "optional parameter listed before required parameter on line #{this_token.last[:line]}"
47
- end
33
+ unless lparen_idx.nil? or rparen_idx.nil?
34
+ param_tokens = tokens[lparen_idx..rparen_idx]
35
+ param_tokens.each_index do |param_tokens_idx|
36
+ this_token = param_tokens[param_tokens_idx]
37
+ next_token = param_tokens[param_tokens_idx+1]
38
+ prev_token = param_tokens[param_tokens_idx-1]
39
+ if this_token.first == :VARIABLE
40
+ unless next_token.nil?
41
+ if next_token.first == :COMMA or next_token.first == :RPAREN
42
+ unless param_tokens[0..param_tokens_idx].rindex { |r| r.first == :EQUALS }.nil?
43
+ unless prev_token.nil? or prev_token.first == :EQUALS
44
+ notify :warning, :message => "optional parameter listed before required parameter", :linenumber => this_token.last[:line]
48
45
  end
49
46
  end
50
47
  end
@@ -52,36 +49,24 @@ class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
52
49
  end
53
50
  end
54
51
  end
52
+ end
53
+ end
55
54
 
56
- if [:CLASS, :DEFINE].include? tokens[token_idx].first
57
- if tokens[token_idx].first == :CLASS
58
- if tokens[token_idx+2].first == :INHERITS
59
- class_name = tokens[token_idx+1].last[:value]
60
- inherited_class = tokens[token_idx+3].last[:value]
61
-
62
- unless class_name =~ /^#{inherited_class}::/
63
- warn "class inherits across namespaces on line #{tokens[token_idx].last[:line]}"
64
- end
65
- end
66
- end
55
+ check 'inherits_across_namespaces' do
56
+ class_indexes.each do |class_idx|
57
+ token_idx = class_idx[:start]
58
+ if tokens[token_idx+2].first == :INHERITS
59
+ class_name = tokens[token_idx+1].last[:value]
60
+ inherited_class = tokens[token_idx+3].last[:value]
67
61
 
68
- lbrace_count = 0
69
- tokens[token_idx+1..-1].each_index do |class_token_idx|
70
- idx = class_token_idx + token_idx
71
- if tokens[idx].first == :LBRACE
72
- lbrace_count += 1
73
- elsif tokens[idx].first == :RBRACE
74
- lbrace_count -= 1
75
- if lbrace_count == 0
76
- class_indexes << {:start => token_idx, :end => idx} if tokens[token_idx].first == :CLASS
77
- defined_type_indexes << {:start => token_idx, :end => idx} if tokens[token_idx].first == :DEFINE
78
- break
79
- end
80
- end
62
+ unless class_name =~ /^#{inherited_class}::/
63
+ notify :warning, :message => "class inherits across namespaces", :linenumber => tokens[token_idx].last[:line]
81
64
  end
82
65
  end
83
66
  end
67
+ end
84
68
 
69
+ check 'nested_classes_or_defines' do
85
70
  class_indexes.each do |class_idx|
86
71
  class_tokens = tokens[class_idx[:start]..class_idx[:end]]
87
72
  class_tokens[1..-1].each_index do |token_idx|
@@ -90,19 +75,21 @@ class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
90
75
 
91
76
  if token.first == :CLASS
92
77
  if next_token.first != :LBRACE
93
- warn "class defined inside a class on line #{token.last[:line]}"
78
+ notify :warning, :message => "class defined inside a class", :linenumber => token.last[:line]
94
79
  end
95
80
  end
96
81
 
97
82
  if token.first == :DEFINE
98
- warn "define defined inside a class on line #{token.last[:line]}"
83
+ notify :warning, :message => "define defined inside a class", :linenumber => token.last[:line]
99
84
  end
100
85
  end
101
86
  end
87
+ end
102
88
 
89
+ check 'variable_scope' do
103
90
  (class_indexes + defined_type_indexes).each do |idx|
104
91
  object_tokens = tokens[idx[:start]..idx[:end]]
105
- variables_in_scope = ['name']
92
+ variables_in_scope = ['name', 'title', 'module_name']
106
93
  referenced_variables = []
107
94
  header_end_idx = object_tokens.index { |r| r.first == :LBRACE }
108
95
  lparen_idx = object_tokens[0..header_end_idx].index { |r| r.first == :LPAREN }
@@ -137,7 +124,9 @@ class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
137
124
  referenced_variables.each do |token|
138
125
  unless token.last[:value].include? '::'
139
126
  unless variables_in_scope.include? token.last[:value]
140
- warn "top-scope variable being used without an explicit namespace on line #{token.last[:line]}"
127
+ unless token.last[:value] =~ /\d+/
128
+ notify :warning, :message => "top-scope variable being used without an explicit namespace", :linenumber => token.last[:line]
129
+ end
141
130
  end
142
131
  end
143
132
  end
@@ -1,10 +1,23 @@
1
1
  class PuppetLint::Plugins::CheckConditionals < PuppetLint::CheckPlugin
2
- def test(path, data)
3
- lexer = Puppet::Parser::Lexer.new
4
- lexer.string = data
5
- tokens = lexer.fullscan
2
+ check 'selector_inside_resource' do
3
+ resource_indexes.each do |resource|
4
+ resource_tokens = tokens[resource[:start]..resource[:end]]
5
+
6
+ resource_tokens.each_index do |resource_token_idx|
7
+ if resource_tokens[resource_token_idx].first == :FARROW
8
+ if resource_tokens[resource_token_idx + 1].first == :VARIABLE
9
+ unless resource_tokens[resource_token_idx + 2].nil?
10
+ if resource_tokens[resource_token_idx + 2].first == :QMARK
11
+ notify :warning, :message => "selector inside resource block", :linenumber => resource_tokens[resource_token_idx].last[:line]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
6
19
 
7
- resource_indexes = []
20
+ check 'case_without_default' do
8
21
  case_indexes = []
9
22
 
10
23
  tokens.each_index do |token_idx|
@@ -32,27 +45,11 @@ class PuppetLint::Plugins::CheckConditionals < PuppetLint::CheckPlugin
32
45
  end
33
46
  end
34
47
 
35
- resource_indexes.each do |resource|
36
- resource_tokens = tokens[resource[:start]..resource[:end]]
37
-
38
- resource_tokens.each_index do |resource_token_idx|
39
- if resource_tokens[resource_token_idx].first == :FARROW
40
- if resource_tokens[resource_token_idx + 1].first == :VARIABLE
41
- unless resource_tokens[resource_token_idx + 2].nil?
42
- if resource_tokens[resource_token_idx + 2].first == :QMARK
43
- warn "selector inside resource block on line #{resource_tokens[resource_token_idx].last[:line]}"
44
- end
45
- end
46
- end
47
- end
48
- end
49
- end
50
-
51
48
  case_indexes.each do |kase|
52
49
  case_tokens = tokens[kase[:start]..kase[:end]]
53
50
 
54
51
  unless case_tokens.index { |r| r.first == :DEFAULT }
55
- warn "case statement without a default case on line #{case_tokens.first.last[:line]}"
52
+ notify :warning, :message => "case statement without a default case", :linenumber => case_tokens.first.last[:line]
56
53
  end
57
54
  end
58
55
  end
@@ -2,48 +2,30 @@
2
2
  # http://docs.puppetlabs.com/guides/style_guide.html#resources
3
3
 
4
4
  class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
5
- def test(path, data)
6
- lexer = Puppet::Parser::Lexer.new
7
- lexer.string = data
8
- tokens = lexer.fullscan
9
-
10
- title_tokens = []
11
- resource_indexes = []
12
- tokens.each_index do |token_idx|
13
- if tokens[token_idx].first == :COLON
14
- # gather a list of tokens that are resource titles
15
- if tokens[token_idx-1].first == :RBRACK
16
- title_array_tokens = tokens[tokens.rindex { |r| r.first == :LBRACK }+1..token_idx-2]
17
- title_tokens += title_array_tokens.select { |token| [:STRING, :NAME].include? token.first }
18
- else
19
- if tokens[token_idx + 1].first != :LBRACE
20
- title_tokens << tokens[token_idx-1]
21
- end
22
- end
23
-
24
- # gather a list of start and end indexes for resource attribute blocks
25
- if tokens[token_idx+1].first != :LBRACE
26
- resource_indexes << {:start => token_idx+1, :end => tokens[token_idx+1..-1].index { |r| [:SEMIC, :RBRACE].include? r.first }+token_idx}
27
- end
28
- end
29
- end
30
-
5
+ check 'unquoted_resource_title' do
31
6
  title_tokens.each do |token|
32
7
  if token.first == :NAME
33
- warn "unquoted resource title on line #{token.last[:line]}"
8
+ notify :warning, :message => "unquoted resource title", :linenumber => token.last[:line]
34
9
  end
35
10
  end
11
+ end
36
12
 
13
+ check 'ensure_first_param' do
37
14
  resource_indexes.each do |resource|
38
15
  resource_tokens = tokens[resource[:start]..resource[:end]]
39
16
  ensure_attr_index = resource_tokens.index { |token| token.first == :NAME and token.last[:value] == 'ensure' }
40
17
  unless ensure_attr_index.nil?
41
18
  if ensure_attr_index > 1
42
19
  ensure_attr_line_no = resource_tokens[ensure_attr_index].last[:line]
43
- warn "ensure found on line #{ensure_attr_line_no} but it's not the first attribute"
20
+ notify :warning, :message => "ensure found on line but it's not the first attribute", :linenumber => ensure_attr_line_no
44
21
  end
45
22
  end
23
+ end
24
+ end
46
25
 
26
+ check 'unquoted_file_mode' do
27
+ resource_indexes.each do |resource|
28
+ resource_tokens = tokens[resource[:start]..resource[:end]]
47
29
  resource_type_token = tokens[tokens[0..resource[:start]].rindex { |r| r.first == :LBRACE } - 1]
48
30
  if resource_type_token.last[:value] == "file"
49
31
  resource_tokens.each_index do |resource_token_idx|
@@ -51,15 +33,43 @@ class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
51
33
  if attr_token.first == :NAME and attr_token.last[:value] == 'mode'
52
34
  value_token = resource_tokens[resource_token_idx + 2]
53
35
  if value_token.first == :NAME
54
- warn "unquoted file mode on line #{value_token.last[:line]}"
36
+ notify :warning, :message => "unquoted file mode", :linenumber => value_token.last[:line]
55
37
  end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ check '4digit_file_mode' do
45
+ resource_indexes.each do |resource|
46
+ resource_tokens = tokens[resource[:start]..resource[:end]]
47
+ resource_type_token = tokens[tokens[0..resource[:start]].rindex { |r| r.first == :LBRACE } - 1]
48
+ if resource_type_token.last[:value] == "file"
49
+ resource_tokens.each_index do |resource_token_idx|
50
+ attr_token = resource_tokens[resource_token_idx]
51
+ if attr_token.first == :NAME and attr_token.last[:value] == 'mode'
52
+ value_token = resource_tokens[resource_token_idx + 2]
56
53
  if value_token.last[:value] !~ /\d{4}/ and value_token.first != :VARIABLE
57
- warn "mode should be represented as a 4 digit octal value on line #{value_token.last[:line]}"
54
+ notify :warning, :message => "mode should be represented as a 4 digit octal value", :linenumber => value_token.last[:line]
58
55
  end
59
- elsif attr_token.first == :NAME and attr_token.last[:value] == 'ensure'
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ check 'ensure_not_symlink_target' do
63
+ resource_indexes.each do |resource|
64
+ resource_tokens = tokens[resource[:start]..resource[:end]]
65
+ resource_type_token = tokens[tokens[0..resource[:start]].rindex { |r| r.first == :LBRACE } - 1]
66
+ if resource_type_token.last[:value] == "file"
67
+ resource_tokens.each_index do |resource_token_idx|
68
+ attr_token = resource_tokens[resource_token_idx]
69
+ if attr_token.first == :NAME and attr_token.last[:value] == 'ensure'
60
70
  value_token = resource_tokens[resource_token_idx + 2]
61
71
  if value_token.last[:value].start_with? '/'
62
- warn "symlink target specified in ensure attr on line #{value_token.last[:line]}"
72
+ notify :warning, :message => "symlink target specified in ensure attr", :linenumber => value_token.last[:line]
63
73
  end
64
74
  end
65
75
  end
@@ -14,27 +14,35 @@ class PuppetLint::Plugins::CheckStrings < PuppetLint::CheckPlugin
14
14
  end
15
15
  end
16
16
 
17
- def test(path, data)
18
- l = Puppet::Parser::Lexer.new
19
- l.string = data
20
- tokens = l.fullscan
21
-
17
+ check 'double_quoted_strings' do
22
18
  tokens.each_index do |token_idx|
23
19
  token = tokens[token_idx]
24
20
 
25
21
  if token.first == :STRING
26
22
  unless token.last[:value].include? "\t" or token.last[:value].include? "\n"
27
- warn "double quoted string containing no variables on line #{token.last[:line]}"
23
+ notify :warning, :message => "double quoted string containing no variables", :linenumber => token.last[:line]
28
24
  end
29
25
  end
26
+ end
27
+ end
28
+
29
+ check 'only_variable_string' do
30
+ tokens.each_index do |token_idx|
31
+ token = tokens[token_idx]
30
32
 
31
33
  if token.first == :DQPRE and token.last[:value] == ""
32
34
  if tokens[token_idx + 1].first == :VARIABLE
33
35
  if tokens[token_idx + 2].first == :DQPOST and tokens[token_idx + 2].last[:value] == ""
34
- warn "string containing only a variable on line #{tokens[token_idx + 1].last[:line]}"
36
+ notify :warning, :message => "string containing only a variable", :linenumber => tokens[token_idx + 1].last[:line]
35
37
  end
36
38
  end
37
39
  end
40
+ end
41
+ end
42
+
43
+ check 'variables_not_enclosed' do
44
+ tokens.each_index do |token_idx|
45
+ token = tokens[token_idx]
38
46
 
39
47
  if token.first == :DQPRE
40
48
  end_of_string_idx = tokens[token_idx..-1].index { |r| r.first == :DQPOST }
@@ -42,31 +50,39 @@ class PuppetLint::Plugins::CheckStrings < PuppetLint::CheckPlugin
42
50
  if t.first == :VARIABLE
43
51
  line = data.split("\n")[t.last[:line] - 1]
44
52
  if line.is_a? String and line.include? "$#{t.last[:value]}"
45
- warn "variable not enclosed in {} on line #{t.last[:line]}"
53
+ notify :warning, :message => "variable not enclosed in {}", :linenumber => t.last[:line]
46
54
  end
47
55
  end
48
56
  end
49
57
  end
58
+ end
59
+ end
50
60
 
51
- if token.first == :DQPRE
52
- end_of_string_idx = tokens[token_idx..-1].index { |r| r.first == :DQPOST }
53
- tokens[token_idx..end_of_string_idx].each do |t|
54
- if t.first == :VARIABLE and t.last[:value].match(/-/)
55
- warn "variable contains a dash on line #{t.last[:line]}"
56
- end
57
- end
58
- end
61
+ check 'single_quote_string_with_variables' do
62
+ tokens.each_index do |token_idx|
63
+ token = tokens[token_idx]
59
64
 
60
65
  if token.first == :SSTRING
61
66
  contents = token.last[:value]
62
67
  line_no = token.last[:line]
63
68
 
64
69
  if contents.include? '${'
65
- error "single quoted string containing a variable found on line #{token.last[:line]}"
70
+ notify :error, :message => "single quoted string containing a variable found", :linenumber => token.last[:line]
66
71
  end
72
+ end
73
+ end
74
+ end
75
+
76
+ check 'quoted_booleans' do
77
+ tokens.each_index do |token_idx|
78
+ token = tokens[token_idx]
79
+
80
+ if token.first == :SSTRING
81
+ contents = token.last[:value]
82
+ line_no = token.last[:line]
67
83
 
68
84
  if ['true', 'false'].include? contents
69
- warn "quoted boolean value found on line #{token.last[:line]}"
85
+ notify :warning, :message => "quoted boolean value found", :linenumber => token.last[:line]
70
86
  end
71
87
  end
72
88
  end
@@ -1,9 +1,5 @@
1
1
  class PuppetLint::Plugins::CheckVariables < PuppetLint::CheckPlugin
2
- def test(path, data)
3
- lexer = Puppet::Parser::Lexer.new
4
- lexer.string = data
5
- tokens = lexer.fullscan
6
-
2
+ check 'variable_contains_dash' do
7
3
  tokens.each_index do |token_idx|
8
4
  token = tokens[token_idx]
9
5
 
@@ -11,7 +7,16 @@ class PuppetLint::Plugins::CheckVariables < PuppetLint::CheckPlugin
11
7
  variable = token.last[:value]
12
8
  line_no = token.last[:line]
13
9
  if variable.match(/-/)
14
- warn "Variable contains a dash on line #{line_no}"
10
+ notify :warning, :message => "variable contains a dash", :linenumber => line_no
11
+ end
12
+ end
13
+
14
+ if token.first == :DQPRE
15
+ end_of_string_idx = tokens[token_idx..-1].index { |r| r.first == :DQPOST }
16
+ tokens[token_idx..end_of_string_idx].each do |t|
17
+ if t.first == :VARIABLE and t.last[:value].match(/-/)
18
+ notify :warning, :message => "variable contains a dash", :linenumber => t.last[:line]
19
+ end
15
20
  end
16
21
  end
17
22
  end