puppet-lint 2.2.1 → 2.3.0

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