halyard-puppet-lint 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +10 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +20 -0
  6. data/README.md +210 -0
  7. data/Rakefile +7 -0
  8. data/bin/puppet-lint +7 -0
  9. data/lib/puppet-lint.rb +214 -0
  10. data/lib/puppet-lint/bin.rb +79 -0
  11. data/lib/puppet-lint/checkplugin.rb +176 -0
  12. data/lib/puppet-lint/checks.rb +91 -0
  13. data/lib/puppet-lint/configuration.rb +153 -0
  14. data/lib/puppet-lint/data.rb +521 -0
  15. data/lib/puppet-lint/lexer.rb +373 -0
  16. data/lib/puppet-lint/lexer/token.rb +101 -0
  17. data/lib/puppet-lint/monkeypatches.rb +2 -0
  18. data/lib/puppet-lint/monkeypatches/string_percent.rb +52 -0
  19. data/lib/puppet-lint/monkeypatches/string_prepend.rb +13 -0
  20. data/lib/puppet-lint/optparser.rb +118 -0
  21. data/lib/puppet-lint/plugins.rb +74 -0
  22. data/lib/puppet-lint/plugins/check_classes.rb +285 -0
  23. data/lib/puppet-lint/plugins/check_comments.rb +55 -0
  24. data/lib/puppet-lint/plugins/check_conditionals.rb +65 -0
  25. data/lib/puppet-lint/plugins/check_documentation.rb +31 -0
  26. data/lib/puppet-lint/plugins/check_nodes.rb +29 -0
  27. data/lib/puppet-lint/plugins/check_resources.rb +194 -0
  28. data/lib/puppet-lint/plugins/check_strings.rb +174 -0
  29. data/lib/puppet-lint/plugins/check_variables.rb +19 -0
  30. data/lib/puppet-lint/plugins/check_whitespace.rb +170 -0
  31. data/lib/puppet-lint/tasks/puppet-lint.rb +91 -0
  32. data/lib/puppet-lint/version.rb +3 -0
  33. data/puppet-lint.gemspec +24 -0
  34. data/spec/fixtures/test/manifests/fail.pp +2 -0
  35. data/spec/fixtures/test/manifests/ignore.pp +1 -0
  36. data/spec/fixtures/test/manifests/ignore_multiple_block.pp +6 -0
  37. data/spec/fixtures/test/manifests/ignore_multiple_line.pp +2 -0
  38. data/spec/fixtures/test/manifests/ignore_reason.pp +1 -0
  39. data/spec/fixtures/test/manifests/init.pp +3 -0
  40. data/spec/fixtures/test/manifests/malformed.pp +1 -0
  41. data/spec/fixtures/test/manifests/url_interpolation.pp +12 -0
  42. data/spec/fixtures/test/manifests/warning.pp +2 -0
  43. data/spec/puppet-lint/bin_spec.rb +326 -0
  44. data/spec/puppet-lint/configuration_spec.rb +56 -0
  45. data/spec/puppet-lint/ignore_overrides_spec.rb +109 -0
  46. data/spec/puppet-lint/lexer/token_spec.rb +18 -0
  47. data/spec/puppet-lint/lexer_spec.rb +783 -0
  48. data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +105 -0
  49. data/spec/puppet-lint/plugins/check_classes/class_inherits_from_params_class_spec.rb +35 -0
  50. data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +33 -0
  51. data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +45 -0
  52. data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +76 -0
  53. data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +73 -0
  54. data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +25 -0
  55. data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +196 -0
  56. data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +45 -0
  57. data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +84 -0
  58. data/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +98 -0
  59. data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +36 -0
  60. data/spec/puppet-lint/plugins/check_documentation/documentation_spec.rb +52 -0
  61. data/spec/puppet-lint/plugins/check_nodes/unquoted_node_name_spec.rb +146 -0
  62. data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +100 -0
  63. data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +55 -0
  64. data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +89 -0
  65. data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +113 -0
  66. data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +45 -0
  67. data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +216 -0
  68. data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +199 -0
  69. data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +114 -0
  70. data/spec/puppet-lint/plugins/check_strings/puppet_url_without_modules_spec.rb +62 -0
  71. data/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb +129 -0
  72. data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +17 -0
  73. data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +73 -0
  74. data/spec/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb +37 -0
  75. data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +21 -0
  76. data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +54 -0
  77. data/spec/puppet-lint/plugins/check_whitespace/arrow_alignment_spec.rb +524 -0
  78. data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +45 -0
  79. data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +101 -0
  80. data/spec/puppet-lint_spec.rb +20 -0
  81. data/spec/spec_helper.rb +129 -0
  82. metadata +229 -0
@@ -0,0 +1,55 @@
1
+ # Public: Check the manifest tokens for any comments started with slashes
2
+ # (//) and record a warning for each instance found.
3
+ PuppetLint.new_check(:slash_comments) do
4
+ def check
5
+ tokens.select { |token|
6
+ token.type == :SLASH_COMMENT
7
+ }.each do |token|
8
+ notify :warning, {
9
+ :message => '// comment found',
10
+ :line => token.line,
11
+ :column => token.column,
12
+ :token => token,
13
+ }
14
+ end
15
+ end
16
+
17
+ def fix(problem)
18
+ problem[:token].type = :COMMENT
19
+ end
20
+ end
21
+
22
+ # Public: Check the manifest tokens for any comments encapsulated with
23
+ # slash-asterisks (/* */) and record a warning for each instance found.
24
+ PuppetLint.new_check(:star_comments) do
25
+ def check
26
+ tokens.select { |token|
27
+ token.type == :MLCOMMENT
28
+ }.each do |token|
29
+ notify :warning, {
30
+ :message => '/* */ comment found',
31
+ :line => token.line,
32
+ :column => token.column,
33
+ :token => token,
34
+ }
35
+ end
36
+ end
37
+
38
+ def fix(problem)
39
+ comment_lines = problem[:token].value.strip.split("\n").map(&:strip)
40
+ first_line = comment_lines.shift
41
+ problem[:token].type = :COMMENT
42
+ problem[:token].value = " #{first_line}"
43
+
44
+ index = tokens.index(problem[:token].next_token)
45
+ comment_lines.reverse.each do |line|
46
+ [
47
+ PuppetLint::Lexer::Token.new(:COMMENT, " #{line}", 0, 0),
48
+ PuppetLint::Lexer::Token.new(:INDENT, problem[:token].prev_token.value.dup, 0, 0),
49
+ PuppetLint::Lexer::Token.new(:NEWLINE, "\n", 0, 0),
50
+ ].each do |new_token|
51
+ tokens.insert(index, new_token)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,65 @@
1
+ # Public: Test the manifest tokens for any selectors embedded within resource
2
+ # declarations and record a warning for each instance found.
3
+ PuppetLint.new_check(:selector_inside_resource) do
4
+ def check
5
+ resource_indexes.each do |resource|
6
+ resource[:tokens].each do |token|
7
+ if token.type == :FARROW
8
+ if token.next_code_token.type == :VARIABLE
9
+ unless token.next_code_token.next_code_token.nil?
10
+ if token.next_code_token.next_code_token.type == :QMARK
11
+ notify :warning, {
12
+ :message => 'selector inside resource block',
13
+ :line => token.line,
14
+ :column => token.column,
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ # Public: Test the manifest tokens for any case statements that do not
26
+ # contain a "default" case and record a warning for each instance found.
27
+ PuppetLint.new_check(:case_without_default) do
28
+ def check
29
+ case_indexes = []
30
+
31
+ tokens.each_index do |token_idx|
32
+ if tokens[token_idx].type == :CASE
33
+ depth = 0
34
+ tokens[(token_idx + 1)..-1].each_index do |case_token_idx|
35
+ idx = case_token_idx + token_idx + 1
36
+ if tokens[idx].type == :LBRACE
37
+ depth += 1
38
+ elsif tokens[idx].type == :RBRACE
39
+ depth -= 1
40
+ if depth == 0
41
+ case_indexes << {:start => token_idx, :end => idx}
42
+ break
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ case_indexes.each_with_index do |kase,kase_index|
50
+ case_tokens = tokens[kase[:start]..kase[:end]]
51
+
52
+ case_indexes[(kase_index + 1)..-1].each do |successor_kase|
53
+ case_tokens -= tokens[successor_kase[:start]..successor_kase[:end]]
54
+ end
55
+
56
+ unless case_tokens.index { |r| r.type == :DEFAULT }
57
+ notify :warning, {
58
+ :message => 'case statement without a default case',
59
+ :line => case_tokens.first.line,
60
+ :column => case_tokens.first.column,
61
+ }
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,31 @@
1
+ # Public: Check the manifest tokens for any class or defined type that does not
2
+ # have a comment directly above it (hopefully, explaining the usage of it) and
3
+ # record a warning for each instance found.
4
+ PuppetLint.new_check(:documentation) do
5
+ COMMENT_TOKENS = Set[:COMMENT, :MLCOMMENT, :SLASH_COMMENT]
6
+ WHITESPACE_TOKENS = Set[:WHITESPACE, :NEWLINE, :INDENT]
7
+
8
+ def check
9
+ (class_indexes + defined_type_indexes).each do |item_idx|
10
+ prev_token = item_idx[:tokens].first.prev_token
11
+ while (!prev_token.nil?) && WHITESPACE_TOKENS.include?(prev_token.type)
12
+ prev_token = prev_token.prev_token
13
+ end
14
+
15
+ unless (!prev_token.nil?) && COMMENT_TOKENS.include?(prev_token.type)
16
+ first_token = item_idx[:tokens].first
17
+ if first_token.type == :CLASS
18
+ type = 'class'
19
+ else
20
+ type = 'defined type'
21
+ end
22
+
23
+ notify :warning, {
24
+ :message => "#{type} not documented",
25
+ :line => first_token.line,
26
+ :column => first_token.column,
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,29 @@
1
+ # Public: Check the manifest for unquoted node names and record a warning for
2
+ # each instance found.
3
+ PuppetLint.new_check(:unquoted_node_name) do
4
+ def check
5
+ node_tokens = tokens.select { |token| token.type == :NODE }
6
+ node_tokens.each do |node|
7
+ node_token_idx = tokens.index(node)
8
+ node_lbrace_tok = tokens[node_token_idx..-1].find { |token| token.type == :LBRACE }
9
+ node_lbrace_idx = tokens.index(node_lbrace_tok)
10
+
11
+ tokens[node_token_idx..node_lbrace_idx].select { |token|
12
+ token.type == :NAME
13
+ }.each do |token|
14
+ unless token.value == 'default'
15
+ notify :warning, {
16
+ :message => 'unquoted node name found',
17
+ :line => token.line,
18
+ :column => token.column,
19
+ :token => token,
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def fix(problem)
27
+ problem[:token].type = :SSTRING
28
+ end
29
+ end
@@ -0,0 +1,194 @@
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
+ PuppetLint.new_check(:unquoted_resource_title) do
4
+ def check
5
+ title_tokens.each do |token|
6
+ if token.type == :NAME
7
+ notify :warning, {
8
+ :message => 'unquoted resource title',
9
+ :line => token.line,
10
+ :column => token.column,
11
+ :token => token,
12
+ }
13
+ end
14
+ end
15
+ end
16
+
17
+ def fix(problem)
18
+ problem[:token].type = :SSTRING
19
+ end
20
+ end
21
+
22
+ # Public: Check the tokens of each resource instance for an ensure parameter
23
+ # and if found, check that it is the first parameter listed. If it is not
24
+ # the first parameter, record a warning.
25
+ PuppetLint.new_check(:ensure_first_param) do
26
+ def check
27
+ resource_indexes.each do |resource|
28
+ ensure_attr_index = resource[:param_tokens].index { |param_token|
29
+ param_token.value == 'ensure'
30
+ }
31
+
32
+ unless ensure_attr_index.nil?
33
+ if ensure_attr_index > 0
34
+ ensure_token = resource[:param_tokens][ensure_attr_index]
35
+ notify :warning, {
36
+ :message => "ensure found on line but it's not the first attribute",
37
+ :line => ensure_token.line,
38
+ :column => ensure_token.column,
39
+ }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ # Public: Check the tokens of each resource instance for any duplicate
47
+ # parameters and record a warning for each instance found.
48
+ PuppetLint.new_check(:duplicate_params) do
49
+ def check
50
+ resource_indexes.each do |resource|
51
+ seen_params = {}
52
+ level = 0
53
+
54
+ resource[:tokens].each_with_index do |token, idx|
55
+ case token.type
56
+ when :LBRACE
57
+ level += 1
58
+ next
59
+ when :RBRACE
60
+ seen_params.delete(level)
61
+ level -= 1
62
+ next
63
+ when :FARROW
64
+ prev_token = token.prev_code_token
65
+ next unless prev_token.type == :NAME
66
+
67
+ if (seen_params[level] ||= Set.new).include?(prev_token.value)
68
+ notify :error, {
69
+ :message => 'duplicate parameter found in resource',
70
+ :line => prev_token.line,
71
+ :column => prev_token.column,
72
+ }
73
+ else
74
+ seen_params[level] << prev_token.value
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ # Public: Check the tokens of each File resource instance for a mode
83
+ # parameter and if found, record a warning if the value of that parameter is
84
+ # not a quoted string.
85
+ PuppetLint.new_check(:unquoted_file_mode) do
86
+ TOKEN_TYPES = Set[:NAME, :NUMBER]
87
+
88
+ def check
89
+ resource_indexes.each do |resource|
90
+ if resource[:type].value == "file"
91
+ resource[:param_tokens].select { |param_token|
92
+ param_token.value == 'mode' &&
93
+ TOKEN_TYPES.include?(param_token.next_code_token.next_code_token.type)
94
+ }.each do |param_token|
95
+ value_token = param_token.next_code_token.next_code_token
96
+ notify :warning, {
97
+ :message => 'unquoted file mode',
98
+ :line => value_token.line,
99
+ :column => value_token.column,
100
+ :token => value_token,
101
+ }
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ def fix(problem)
108
+ problem[:token].type = :SSTRING
109
+ end
110
+ end
111
+
112
+ # Public: Check the tokens of each File resource instance for a mode
113
+ # parameter and if found, record a warning if the value of that parameter is
114
+ # not a 4 digit octal value (0755) or a symbolic mode ('o=rwx,g+r').
115
+ PuppetLint.new_check(:file_mode) do
116
+ MSG = 'mode should be represented as a 4 digit octal value or symbolic mode'
117
+ SYM_RE = "([ugoa]*[-=+][-=+rstwxXugo]*)(,[ugoa]*[-=+][-=+rstwxXugo]*)*"
118
+ IGNORE_TYPES = Set[:VARIABLE, :UNDEF]
119
+ MODE_RE = Regexp.new(/\A([0-7]{4}|#{SYM_RE})\Z/)
120
+
121
+ def check
122
+ resource_indexes.each do |resource|
123
+ if resource[:type].value == "file"
124
+ resource[:param_tokens].select { |param_token|
125
+ param_token.value == 'mode'
126
+ }.each do |param_token|
127
+ value_token = param_token.next_code_token.next_code_token
128
+
129
+ break if IGNORE_TYPES.include?(value_token.type)
130
+ break if value_token.value =~ MODE_RE
131
+
132
+ notify :warning, {
133
+ :message => MSG,
134
+ :line => value_token.line,
135
+ :column => value_token.column,
136
+ :token => value_token,
137
+ }
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ def fix(problem)
144
+ if problem[:token].value =~ /\A[0-7]{3}\Z/
145
+ problem[:token].type = :SSTRING
146
+ problem[:token].value = "0#{problem[:token].value.to_s}"
147
+ else
148
+ raise PuppetLint::NoFix
149
+ end
150
+ end
151
+ end
152
+
153
+ # Public: Check the tokens of each File resource instance for an ensure
154
+ # parameter and record a warning if the value of that parameter looks like
155
+ # a symlink target (starts with a '/').
156
+ PuppetLint.new_check(:ensure_not_symlink_target) do
157
+ def check
158
+ resource_indexes.each do |resource|
159
+ if resource[:type].value == "file"
160
+ resource[:param_tokens].select { |param_token|
161
+ param_token.value == 'ensure'
162
+ }.each do |ensure_token|
163
+ value_token = ensure_token.next_code_token.next_code_token
164
+ if value_token.value.start_with? '/'
165
+ notify :warning, {
166
+ :message => 'symlink target specified in ensure attr',
167
+ :line => value_token.line,
168
+ :column => value_token.column,
169
+ :param_token => ensure_token,
170
+ :value_token => value_token,
171
+ }
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ def fix(problem)
179
+ index = tokens.index(problem[:value_token])
180
+
181
+ [
182
+ PuppetLint::Lexer::Token.new(:NAME, 'symlink', 0, 0),
183
+ PuppetLint::Lexer::Token.new(:COMMA, ',', 0, 0),
184
+ PuppetLint::Lexer::Token.new(:NEWLINE, "\n", 0, 0),
185
+ PuppetLint::Lexer::Token.new(:INDENT, problem[:param_token].prev_token.value.dup, 0, 0),
186
+ PuppetLint::Lexer::Token.new(:NAME, 'target', 0, 0),
187
+ PuppetLint::Lexer::Token.new(:WHITESPACE, problem[:param_token].next_token.value.dup, 0, 0),
188
+ PuppetLint::Lexer::Token.new(:FARROW, '=>', 0, 0),
189
+ PuppetLint::Lexer::Token.new(:WHITESPACE, ' ', 0, 0),
190
+ ].reverse.each do |new_token|
191
+ tokens.insert(index, new_token)
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,174 @@
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
+ PuppetLint.new_check(:double_quoted_strings) do
5
+ def check
6
+ tokens.select { |token|
7
+ token.type == :STRING
8
+ }.map { |token|
9
+ [token, token.value.gsub(' '*token.column, "\n")]
10
+ }.select { |token, sane_value|
11
+ sane_value[/(\\\$|\\"|\\'|'|\r|\t|\\t|\n|\\n)/].nil?
12
+ }.each do |token, sane_value|
13
+ notify :warning, {
14
+ :message => 'double quoted string containing no variables',
15
+ :line => token.line,
16
+ :column => token.column,
17
+ :token => token,
18
+ }
19
+ end
20
+ end
21
+
22
+ def fix(problem)
23
+ problem[:token].type = :SSTRING
24
+ end
25
+ end
26
+
27
+ # Public: Check the manifest tokens for double quoted strings that contain
28
+ # a single variable only and record a warning for each instance found.
29
+ PuppetLint.new_check(:only_variable_string) do
30
+ VAR_TYPES = Set[:VARIABLE, :UNENC_VARIABLE]
31
+
32
+ def check
33
+ tokens.each_with_index do |start_token, start_token_idx|
34
+ if start_token.type == :DQPRE and start_token.value == ''
35
+ var_token = start_token.next_token
36
+ if VAR_TYPES.include? var_token.type
37
+ eos_offset = 2
38
+ loop do
39
+ eos_token = tokens[start_token_idx + eos_offset]
40
+ case eos_token.type
41
+ when :LBRACK
42
+ eos_offset += 3
43
+ when :DQPOST
44
+ if eos_token.value == ''
45
+ if eos_token.next_code_token && eos_token.next_code_token.type == :FARROW
46
+ break
47
+ end
48
+ notify :warning, {
49
+ :message => 'string containing only a variable',
50
+ :line => var_token.line,
51
+ :column => var_token.column,
52
+ :start_token => start_token,
53
+ :var_token => var_token,
54
+ :end_token => eos_token,
55
+ }
56
+ end
57
+ break
58
+ else
59
+ break
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ def fix(problem)
68
+ prev_token = problem[:start_token].prev_token
69
+ prev_code_token = problem[:start_token].prev_code_token
70
+ next_token = problem[:end_token].next_token
71
+ next_code_token = problem[:end_token].next_code_token
72
+ var_token = problem[:var_token]
73
+
74
+ tokens.delete(problem[:start_token])
75
+ tokens.delete(problem[:end_token])
76
+
77
+ prev_token.next_token = var_token unless prev_token.nil?
78
+ prev_code_token.next_code_token = var_token unless prev_code_token.nil?
79
+ next_code_token.prev_code_token = var_token unless next_code_token.nil?
80
+ next_token.prev_token = var_token unless next_token.nil?
81
+ var_token.type = :VARIABLE
82
+ var_token.next_token = next_token
83
+ var_token.next_code_token = next_code_token
84
+ var_token.prev_code_token = prev_code_token
85
+ var_token.prev_token = prev_token
86
+ end
87
+ end
88
+
89
+ # Public: Check the manifest tokens for any variables in a string that have
90
+ # not been enclosed by braces ({}) and record a warning for each instance
91
+ # found.
92
+ PuppetLint.new_check(:variables_not_enclosed) do
93
+ def check
94
+ tokens.select { |r|
95
+ r.type == :UNENC_VARIABLE
96
+ }.each do |token|
97
+ notify :warning, {
98
+ :message => 'variable not enclosed in {}',
99
+ :line => token.line,
100
+ :column => token.column,
101
+ :token => token,
102
+ }
103
+ end
104
+ end
105
+
106
+ def fix(problem)
107
+ problem[:token].type = :VARIABLE
108
+ end
109
+ end
110
+
111
+ # Public: Check the manifest tokens for any single quoted strings containing
112
+ # a enclosed variable and record an error for each instance found.
113
+ PuppetLint.new_check(:single_quote_string_with_variables) do
114
+ def check
115
+ tokens.select { |r|
116
+ r.type == :SSTRING && r.value.include?('${')
117
+ }.each do |token|
118
+ notify :error, {
119
+ :message => 'single quoted string containing a variable found',
120
+ :line => token.line,
121
+ :column => token.column,
122
+ }
123
+ end
124
+ end
125
+ end
126
+
127
+ # Public: Check the manifest tokens for any double or single quoted strings
128
+ # containing only a boolean value and record a warning for each instance
129
+ # found.
130
+ PuppetLint.new_check(:quoted_booleans) do
131
+ STRING_TYPES = Set[:STRING, :SSTRING]
132
+ BOOLEANS = Set['true', 'false']
133
+
134
+ def check
135
+ tokens.select { |r|
136
+ STRING_TYPES.include?(r.type) && BOOLEANS.include?(r.value)
137
+ }.each do |token|
138
+ notify :warning, {
139
+ :message => 'quoted boolean value found',
140
+ :line => token.line,
141
+ :column => token.column,
142
+ :token => token,
143
+ }
144
+ end
145
+ end
146
+
147
+ def fix(problem)
148
+ problem[:token].type = problem[:token].value.upcase.to_sym
149
+ end
150
+ end
151
+
152
+ # Public: Check the manifest tokens for any puppet:// URL strings where the
153
+ # path section doesn't start with modules/ and record a warning for each
154
+ # instance found.
155
+ PuppetLint.new_check(:puppet_url_without_modules) do
156
+ def check
157
+ tokens.select { |token|
158
+ (token.type == :SSTRING || token.type == :STRING || token.type == :DQPRE) && token.value.start_with?('puppet://')
159
+ }.reject { |token|
160
+ token.value[/puppet:\/\/.*?\/(.+)/, 1].start_with?('modules/') unless token.value[/puppet:\/\/.*?\/(.+)/, 1].nil?
161
+ }.each do |token|
162
+ notify :warning, {
163
+ :message => 'puppet:// URL without modules/ found',
164
+ :line => token.line,
165
+ :column => token.column,
166
+ :token => token,
167
+ }
168
+ end
169
+ end
170
+
171
+ def fix(problem)
172
+ problem[:token].value.gsub!(/(puppet:\/\/.*?\/)/, '\1modules/')
173
+ end
174
+ end