puppet-lint 2.2.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -19
  3. data/README.md +181 -174
  4. data/Rakefile +1 -1
  5. data/lib/puppet-lint/bin.rb +6 -0
  6. data/lib/puppet-lint/lexer.rb +1 -1
  7. data/lib/puppet-lint/plugins.rb +16 -10
  8. data/lib/puppet-lint/plugins/check_classes/arrow_on_right_operand_line.rb +46 -0
  9. data/lib/puppet-lint/plugins/check_classes/autoloader_layout.rb +33 -0
  10. data/lib/puppet-lint/plugins/check_classes/class_inherits_from_params_class.rb +20 -0
  11. data/lib/puppet-lint/plugins/check_classes/code_on_top_scope.rb +20 -0
  12. data/lib/puppet-lint/plugins/check_classes/inherits_across_namespaces.rb +22 -0
  13. data/lib/puppet-lint/plugins/check_classes/names_containing_dash.rb +23 -0
  14. data/lib/puppet-lint/plugins/check_classes/names_containing_uppercase.rb +28 -0
  15. data/lib/puppet-lint/plugins/check_classes/nested_classes_or_defines.rb +28 -0
  16. data/lib/puppet-lint/plugins/check_classes/parameter_order.rb +44 -0
  17. data/lib/puppet-lint/plugins/check_classes/right_to_left_relationship.rb +15 -0
  18. data/lib/puppet-lint/plugins/check_classes/variable_scope.rb +143 -0
  19. data/lib/puppet-lint/plugins/check_comments/slash_comments.rb +22 -0
  20. data/lib/puppet-lint/plugins/{check_comments.rb → check_comments/star_comments.rb} +1 -24
  21. data/lib/puppet-lint/plugins/{check_conditionals.rb → check_conditionals/case_without_default.rb} +1 -27
  22. data/lib/puppet-lint/plugins/check_conditionals/selector_inside_resource.rb +25 -0
  23. data/lib/puppet-lint/plugins/{check_documentation.rb → check_documentation/documentation.rb} +0 -0
  24. data/lib/puppet-lint/plugins/{check_nodes.rb → check_nodes/unquoted_node_name.rb} +0 -0
  25. data/lib/puppet-lint/plugins/check_resources/duplicate_params.rb +37 -0
  26. data/lib/puppet-lint/plugins/check_resources/ensure_first_param.rb +70 -0
  27. data/lib/puppet-lint/plugins/check_resources/ensure_not_symlink_target.rb +44 -0
  28. data/lib/puppet-lint/plugins/check_resources/file_mode.rb +42 -0
  29. data/lib/puppet-lint/plugins/check_resources/unquoted_file_mode.rb +31 -0
  30. data/lib/puppet-lint/plugins/check_resources/unquoted_resource_title.rb +22 -0
  31. data/lib/puppet-lint/plugins/check_strings/double_quoted_strings.rb +27 -0
  32. data/lib/puppet-lint/plugins/check_strings/only_variable_string.rb +63 -0
  33. data/lib/puppet-lint/plugins/check_strings/puppet_url_without_modules.rb +25 -0
  34. data/lib/puppet-lint/plugins/check_strings/quoted_booleans.rb +26 -0
  35. data/lib/puppet-lint/plugins/check_strings/single_quote_string_with_variables.rb +17 -0
  36. data/lib/puppet-lint/plugins/check_strings/variables_not_enclosed.rb +23 -0
  37. data/lib/puppet-lint/plugins/check_variables/variable_contains_dash.rb +21 -0
  38. data/lib/puppet-lint/plugins/{check_variables.rb → check_variables/variable_is_lowercase.rb} +0 -22
  39. data/lib/puppet-lint/plugins/check_whitespace/140chars.rb +21 -0
  40. data/lib/puppet-lint/plugins/check_whitespace/2sp_soft_tabs.rb +19 -0
  41. data/lib/puppet-lint/plugins/check_whitespace/80chars.rb +21 -0
  42. data/lib/puppet-lint/plugins/{check_whitespace.rb → check_whitespace/arrow_alignment.rb} +0 -118
  43. data/lib/puppet-lint/plugins/check_whitespace/hard_tabs.rb +24 -0
  44. data/lib/puppet-lint/plugins/check_whitespace/trailing_whitespace.rb +28 -0
  45. data/lib/puppet-lint/tasks/puppet-lint.rb +4 -0
  46. data/lib/puppet-lint/version.rb +1 -1
  47. data/spec/puppet-lint/bin_spec.rb +18 -1
  48. data/spec/puppet-lint/lexer_spec.rb +19 -0
  49. metadata +41 -68
  50. data/lib/puppet-lint/plugins/check_classes.rb +0 -433
  51. data/lib/puppet-lint/plugins/check_resources.rb +0 -251
  52. data/lib/puppet-lint/plugins/check_strings.rb +0 -186
@@ -0,0 +1,22 @@
1
+ # Public: Check the manifest tokens for any comments started with slashes
2
+ # (//) and record a warning for each instance found.
3
+ #
4
+ # https://docs.puppet.com/guides/style_guide.html#comments
5
+ PuppetLint.new_check(:slash_comments) do
6
+ def check
7
+ tokens.select { |token|
8
+ token.type == :SLASH_COMMENT
9
+ }.each do |token|
10
+ notify :warning, {
11
+ :message => '// comment found',
12
+ :line => token.line,
13
+ :column => token.column,
14
+ :token => token,
15
+ }
16
+ end
17
+ end
18
+
19
+ def fix(problem)
20
+ problem[:token].type = :COMMENT
21
+ end
22
+ end
@@ -1,26 +1,3 @@
1
- # Public: Check the manifest tokens for any comments started with slashes
2
- # (//) and record a warning for each instance found.
3
- #
4
- # https://docs.puppet.com/guides/style_guide.html#comments
5
- PuppetLint.new_check(:slash_comments) do
6
- def check
7
- tokens.select { |token|
8
- token.type == :SLASH_COMMENT
9
- }.each do |token|
10
- notify :warning, {
11
- :message => '// comment found',
12
- :line => token.line,
13
- :column => token.column,
14
- :token => token,
15
- }
16
- end
17
- end
18
-
19
- def fix(problem)
20
- problem[:token].type = :COMMENT
21
- end
22
- end
23
-
24
1
  # Public: Check the manifest tokens for any comments encapsulated with
25
2
  # slash-asterisks (/* */) and record a warning for each instance found.
26
3
  #
@@ -41,7 +18,7 @@ PuppetLint.new_check(:star_comments) do
41
18
 
42
19
  def fix(problem)
43
20
  comment_lines = problem[:token].value.strip.split("\n").map(&:strip)
44
-
21
+
45
22
  first_line = comment_lines.shift
46
23
  problem[:token].type = :COMMENT
47
24
  problem[:token].value = " #{first_line}"
@@ -1,29 +1,3 @@
1
- # Public: Test the manifest tokens for any selectors embedded within resource
2
- # declarations and record a warning for each instance found.
3
- #
4
- # https://docs.puppet.com/guides/style_guide.html#keep-resource-declarations-simple
5
- PuppetLint.new_check(:selector_inside_resource) do
6
- def check
7
- resource_indexes.each do |resource|
8
- resource[:tokens].each do |token|
9
- if token.type == :FARROW
10
- if token.next_code_token.type == :VARIABLE
11
- unless token.next_code_token.next_code_token.nil?
12
- if token.next_code_token.next_code_token.type == :QMARK
13
- notify :warning, {
14
- :message => 'selector inside resource block',
15
- :line => token.line,
16
- :column => token.column,
17
- }
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
26
-
27
1
  # Public: Test the manifest tokens for any case statements that do not
28
2
  # contain a "default" case and record a warning for each instance found.
29
3
  #
@@ -54,7 +28,7 @@ PuppetLint.new_check(:case_without_default) do
54
28
  case_tokens = tokens[kase[:start]..kase[:end]]
55
29
 
56
30
  case_indexes[(kase_index + 1)..-1].each do |successor_kase|
57
- case_tokens -= tokens[successor_kase[:start]..successor_kase[:end]]
31
+ case_tokens -= tokens[successor_kase[:start]..successor_kase[:end]]
58
32
  end
59
33
 
60
34
  unless case_tokens.index { |r| r.type == :DEFAULT }
@@ -0,0 +1,25 @@
1
+ # Public: Test the manifest tokens for any selectors embedded within resource
2
+ # declarations and record a warning for each instance found.
3
+ #
4
+ # https://docs.puppet.com/guides/style_guide.html#keep-resource-declarations-simple
5
+ PuppetLint.new_check(:selector_inside_resource) do
6
+ def check
7
+ resource_indexes.each do |resource|
8
+ resource[:tokens].each do |token|
9
+ if token.type == :FARROW
10
+ if token.next_code_token.type == :VARIABLE
11
+ unless token.next_code_token.next_code_token.nil?
12
+ if token.next_code_token.next_code_token.type == :QMARK
13
+ notify :warning, {
14
+ :message => 'selector inside resource block',
15
+ :line => token.line,
16
+ :column => token.column,
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,37 @@
1
+ # Public: Check the tokens of each resource instance for any duplicate
2
+ # parameters and record a warning for each instance found.
3
+ #
4
+ # No style guide reference
5
+ PuppetLint.new_check(:duplicate_params) do
6
+ def check
7
+ resource_indexes.each do |resource|
8
+ seen_params = {}
9
+ level = 0
10
+
11
+ resource[:tokens].each_with_index do |token, idx|
12
+ case token.type
13
+ when :LBRACE
14
+ level += 1
15
+ next
16
+ when :RBRACE
17
+ seen_params.delete(level)
18
+ level -= 1
19
+ next
20
+ when :FARROW
21
+ prev_token = token.prev_code_token
22
+ next unless prev_token.type == :NAME
23
+
24
+ if (seen_params[level] ||= Set.new).include?(prev_token.value)
25
+ notify :error, {
26
+ :message => 'duplicate parameter found in resource',
27
+ :line => prev_token.line,
28
+ :column => prev_token.column,
29
+ }
30
+ else
31
+ seen_params[level] << prev_token.value
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,70 @@
1
+ # Public: Check the tokens of each resource instance for an ensure parameter
2
+ # and if found, check that it is the first parameter listed. If it is not
3
+ # the first parameter, record a warning.
4
+ #
5
+ # https://docs.puppet.com/guides/style_guide.html#attribute-ordering
6
+ PuppetLint.new_check(:ensure_first_param) do
7
+ def check
8
+ resource_indexes.each do |resource|
9
+ next if [:CLASS].include? resource[:type].type
10
+ ensure_attr_index = resource[:param_tokens].index { |param_token|
11
+ param_token.value == 'ensure'
12
+ }
13
+
14
+ unless ensure_attr_index.nil?
15
+ if ensure_attr_index > 0
16
+ ensure_token = resource[:param_tokens][ensure_attr_index]
17
+ notify :warning, {
18
+ :message => "ensure found on line but it's not the first attribute",
19
+ :line => ensure_token.line,
20
+ :column => ensure_token.column,
21
+ :resource => resource,
22
+ }
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def fix(problem)
29
+ first_param_name_token = tokens[problem[:resource][:start]].next_token_of(:NAME)
30
+ first_param_comma_token = first_param_name_token.next_token_of(:COMMA)
31
+ ensure_param_name_token = first_param_comma_token.next_token_of(:NAME, :value => 'ensure')
32
+ ensure_param_comma_token = ensure_param_name_token.next_token_of([:COMMA, :SEMIC])
33
+
34
+ if first_param_name_token.nil? or first_param_comma_token.nil? or ensure_param_name_token.nil? or ensure_param_comma_token.nil?
35
+ raise PuppetLint::NoFix
36
+ end
37
+
38
+ first_param_name_idx = tokens.index(first_param_name_token)
39
+ first_param_comma_idx = tokens.index(first_param_comma_token)
40
+ ensure_param_name_idx = tokens.index(ensure_param_name_token)
41
+ ensure_param_comma_idx = tokens.index(ensure_param_comma_token)
42
+
43
+ # Flip params
44
+ prev_token = first_param_name_token.prev_token
45
+ first_param_name_token.prev_token = ensure_param_name_token.prev_token
46
+ ensure_param_name_token.prev_token = prev_token
47
+
48
+ prev_code_token = first_param_name_token.prev_code_token
49
+ first_param_name_token.prev_code_token = ensure_param_name_token.prev_code_token
50
+ ensure_param_name_token.prev_code_token = prev_code_token
51
+
52
+ next_token = first_param_comma_token.next_token
53
+ first_param_comma_token = ensure_param_comma_token.next_token
54
+ ensure_param_comma_token.next_token = next_token
55
+
56
+ next_code_token = first_param_comma_token.next_code_token
57
+ first_param_comma_code_token = ensure_param_comma_token.next_code_token
58
+ ensure_param_comma_token.next_code_token = next_code_token
59
+
60
+ # Update index
61
+ ensure_tmp = tokens.slice!(ensure_param_name_idx..ensure_param_comma_idx-1)
62
+ first_tmp = tokens.slice!(first_param_name_idx..first_param_comma_idx-1)
63
+ ensure_tmp.reverse_each do |item|
64
+ tokens.insert(first_param_name_idx, item)
65
+ end
66
+ first_tmp.reverse_each do |item|
67
+ tokens.insert(ensure_param_name_idx + ensure_tmp.length - first_tmp.length, item)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,44 @@
1
+ # Public: Check the tokens of each File resource instance for an ensure
2
+ # parameter and record a warning if the value of that parameter looks like
3
+ # a symlink target (starts with a '/').
4
+ #
5
+ # https://docs.puppet.com/guides/style_guide.html#symbolic-links
6
+ PuppetLint.new_check(:ensure_not_symlink_target) do
7
+ def check
8
+ resource_indexes.each do |resource|
9
+ if resource[:type].value == "file"
10
+ resource[:param_tokens].select { |param_token|
11
+ param_token.value == 'ensure'
12
+ }.each do |ensure_token|
13
+ value_token = ensure_token.next_code_token.next_code_token
14
+ if value_token.value.start_with? '/'
15
+ notify :warning, {
16
+ :message => 'symlink target specified in ensure attr',
17
+ :line => value_token.line,
18
+ :column => value_token.column,
19
+ :param_token => ensure_token,
20
+ :value_token => value_token,
21
+ }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def fix(problem)
29
+ index = tokens.index(problem[:value_token])
30
+
31
+ [
32
+ PuppetLint::Lexer::Token.new(:NAME, 'symlink', 0, 0),
33
+ PuppetLint::Lexer::Token.new(:COMMA, ',', 0, 0),
34
+ PuppetLint::Lexer::Token.new(:NEWLINE, "\n", 0, 0),
35
+ PuppetLint::Lexer::Token.new(:INDENT, problem[:param_token].prev_token.value.dup, 0, 0),
36
+ PuppetLint::Lexer::Token.new(:NAME, 'target', 0, 0),
37
+ PuppetLint::Lexer::Token.new(:WHITESPACE, ' ', 0, 0),
38
+ PuppetLint::Lexer::Token.new(:FARROW, '=>', 0, 0),
39
+ PuppetLint::Lexer::Token.new(:WHITESPACE, ' ', 0, 0),
40
+ ].reverse.each do |new_token|
41
+ tokens.insert(index, new_token)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,42 @@
1
+ # Public: Check the tokens of each File resource instance for a mode
2
+ # parameter and if found, record a warning if the value of that parameter is
3
+ # not a 4 digit octal value (0755) or a symbolic mode ('o=rwx,g+r').
4
+ #
5
+ # https://docs.puppet.com/guides/style_guide.html#file-modes
6
+ PuppetLint.new_check(:file_mode) do
7
+ MSG = 'mode should be represented as a 4 digit octal value or symbolic mode'
8
+ SYM_RE = "([ugoa]*[-=+][-=+rstwxXugo]*)(,[ugoa]*[-=+][-=+rstwxXugo]*)*"
9
+ IGNORE_TYPES = Set[:VARIABLE, :UNDEF, :FUNCTION_NAME]
10
+ MODE_RE = Regexp.new(/\A([0-7]{4}|#{SYM_RE})\Z/)
11
+
12
+ def check
13
+ resource_indexes.each do |resource|
14
+ if resource[:type].value == "file" or resource[:type].value == "concat"
15
+ resource[:param_tokens].select { |param_token|
16
+ param_token.value == 'mode'
17
+ }.each do |param_token|
18
+ value_token = param_token.next_code_token.next_code_token
19
+
20
+ break if IGNORE_TYPES.include?(value_token.type)
21
+ break if value_token.value =~ MODE_RE
22
+
23
+ notify :warning, {
24
+ :message => MSG,
25
+ :line => value_token.line,
26
+ :column => value_token.column,
27
+ :token => value_token,
28
+ }
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ def fix(problem)
35
+ if problem[:token].value =~ /\A[0-7]{3}\Z/
36
+ problem[:token].type = :SSTRING
37
+ problem[:token].value = "0#{problem[:token].value.to_s}"
38
+ else
39
+ raise PuppetLint::NoFix
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,31 @@
1
+ # Public: Check the tokens of each File resource instance for a mode
2
+ # parameter and if found, record a warning if the value of that parameter is
3
+ # not a quoted string.
4
+ #
5
+ # https://docs.puppet.com/guides/style_guide.html#file-modes
6
+ PuppetLint.new_check(:unquoted_file_mode) do
7
+ TOKEN_TYPES = Set[:NAME, :NUMBER]
8
+
9
+ def check
10
+ resource_indexes.each do |resource|
11
+ if resource[:type].value == "file" or resource[:type].value == "concat"
12
+ resource[:param_tokens].select { |param_token|
13
+ param_token.value == 'mode' &&
14
+ TOKEN_TYPES.include?(param_token.next_code_token.next_code_token.type)
15
+ }.each do |param_token|
16
+ value_token = param_token.next_code_token.next_code_token
17
+ notify :warning, {
18
+ :message => 'unquoted file mode',
19
+ :line => value_token.line,
20
+ :column => value_token.column,
21
+ :token => value_token,
22
+ }
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def fix(problem)
29
+ problem[:token].type = :SSTRING
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ # Public: Check the manifest tokens for any resource titles / namevars that
2
+ # are not quoted and record a warning for each instance found.
3
+ #
4
+ # https://docs.puppet.com/guides/style_guide.html#resource-names
5
+ PuppetLint.new_check(:unquoted_resource_title) do
6
+ def check
7
+ title_tokens.each do |token|
8
+ if token.type == :NAME
9
+ notify :warning, {
10
+ :message => 'unquoted resource title',
11
+ :line => token.line,
12
+ :column => token.column,
13
+ :token => token,
14
+ }
15
+ end
16
+ end
17
+ end
18
+
19
+ def fix(problem)
20
+ problem[:token].type = :SSTRING
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ # Public: Check the manifest tokens for any double quoted strings that don't
2
+ # contain any variables or common escape characters and record a warning for
3
+ # each instance found.
4
+ #
5
+ # https://docs.puppet.com/guides/style_guide.html#quoting
6
+ PuppetLint.new_check(:double_quoted_strings) do
7
+ def check
8
+ tokens.select { |token|
9
+ token.type == :STRING
10
+ }.map { |token|
11
+ [token, token.value.gsub(' '*token.column, "\n")]
12
+ }.select { |token, sane_value|
13
+ sane_value[/(\\\$|\\"|\\'|'|\r|\t|\\t|\n|\\n|\\\\)/].nil?
14
+ }.each do |token, sane_value|
15
+ notify :warning, {
16
+ :message => 'double quoted string containing no variables',
17
+ :line => token.line,
18
+ :column => token.column,
19
+ :token => token,
20
+ }
21
+ end
22
+ end
23
+
24
+ def fix(problem)
25
+ problem[:token].type = :SSTRING
26
+ end
27
+ end
@@ -0,0 +1,63 @@
1
+ # Public: Check the manifest tokens for double quoted strings that contain
2
+ # a single variable only and record a warning for each instance found.
3
+ #
4
+ # https://docs.puppet.com/guides/style_guide.html#quoting
5
+ PuppetLint.new_check(:only_variable_string) do
6
+ VAR_TYPES = Set[:VARIABLE, :UNENC_VARIABLE]
7
+
8
+ def check
9
+ tokens.each_with_index do |start_token, start_token_idx|
10
+ if start_token.type == :DQPRE and start_token.value == ''
11
+ var_token = start_token.next_token
12
+ if VAR_TYPES.include? var_token.type
13
+ eos_offset = 2
14
+ loop do
15
+ eos_token = tokens[start_token_idx + eos_offset]
16
+ case eos_token.type
17
+ when :LBRACK
18
+ eos_offset += 3
19
+ when :DQPOST
20
+ if eos_token.value == ''
21
+ if eos_token.next_code_token && eos_token.next_code_token.type == :FARROW
22
+ break
23
+ end
24
+ notify :warning, {
25
+ :message => 'string containing only a variable',
26
+ :line => var_token.line,
27
+ :column => var_token.column,
28
+ :start_token => start_token,
29
+ :var_token => var_token,
30
+ :end_token => eos_token,
31
+ }
32
+ end
33
+ break
34
+ else
35
+ break
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def fix(problem)
44
+ prev_token = problem[:start_token].prev_token
45
+ prev_code_token = problem[:start_token].prev_code_token
46
+ next_token = problem[:end_token].next_token
47
+ next_code_token = problem[:end_token].next_code_token
48
+ var_token = problem[:var_token]
49
+
50
+ tokens.delete(problem[:start_token])
51
+ tokens.delete(problem[:end_token])
52
+
53
+ prev_token.next_token = var_token unless prev_token.nil?
54
+ prev_code_token.next_code_token = var_token unless prev_code_token.nil?
55
+ next_code_token.prev_code_token = var_token unless next_code_token.nil?
56
+ next_token.prev_token = var_token unless next_token.nil?
57
+ var_token.type = :VARIABLE
58
+ var_token.next_token = next_token
59
+ var_token.next_code_token = next_code_token
60
+ var_token.prev_code_token = prev_code_token
61
+ var_token.prev_token = prev_token
62
+ end
63
+ end