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,79 @@
1
+ require 'puppet-lint/optparser'
2
+
3
+ # Internal: The logic of the puppet-lint bin script, contained in a class for
4
+ # ease of testing.
5
+ class PuppetLint::Bin
6
+ # Public: Initialise a new PuppetLint::Bin.
7
+ #
8
+ # args - An Array of command line argument Strings to be passed to the option
9
+ # parser.
10
+ #
11
+ # Examples
12
+ #
13
+ # PuppetLint::Bin.new(ARGV).run
14
+ def initialize(args)
15
+ @args = args
16
+ end
17
+
18
+ # Public: Run puppet-lint as a command line tool.
19
+ #
20
+ # Returns an Integer exit code to be passed back to the shell.
21
+ def run
22
+ opts = PuppetLint::OptParser.build
23
+
24
+ begin
25
+ opts.parse!(@args)
26
+ rescue OptionParser::InvalidOption
27
+ puts "puppet-lint: #{$!.message}"
28
+ puts "puppet-lint: try 'puppet-lint --help' for more information"
29
+ return 1
30
+ end
31
+
32
+ if PuppetLint.configuration.display_version
33
+ puts "puppet-lint #{PuppetLint::VERSION}"
34
+ return 0
35
+ end
36
+
37
+ if @args[0].nil?
38
+ puts "puppet-lint: no file specified"
39
+ puts "puppet-lint: try 'puppet-lint --help' for more information"
40
+ return 1
41
+ end
42
+
43
+ begin
44
+ path = @args[0]
45
+ if File.directory?(path)
46
+ path = Dir.glob("#{path}/**/*.pp")
47
+ else
48
+ path = @args
49
+ end
50
+
51
+ if path.length > 1
52
+ PuppetLint.configuration.with_filename = true
53
+ end
54
+
55
+ return_val = 0
56
+ path.each do |f|
57
+ l = PuppetLint.new
58
+ l.file = f
59
+ l.run
60
+ l.print_problems
61
+ if l.errors? or (l.warnings? and PuppetLint.configuration.fail_on_warnings)
62
+ return_val = 1
63
+ end
64
+
65
+ if PuppetLint.configuration.fix && !l.problems.any? { |e| e[:check] == :syntax }
66
+ File.open(f, 'w') do |fd|
67
+ fd.write l.manifest
68
+ end
69
+ end
70
+ end
71
+ return return_val
72
+
73
+ rescue PuppetLint::NoCodeError
74
+ puts "puppet-lint: no file specified or specified file does not exist"
75
+ puts "puppet-lint: try 'puppet-lint --help' for more information"
76
+ return 1
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,176 @@
1
+ # Public: A class that contains and provides information for the puppet-lint
2
+ # checks.
3
+ #
4
+ # This class should not be used directly, but instead should be inherited.
5
+ #
6
+ # Examples
7
+ #
8
+ # class PuppetLint::Plugin::CheckFoo < PuppetLint::CheckPlugin
9
+ # end
10
+ class PuppetLint::CheckPlugin
11
+ # Internal: Initialise a new PuppetLint::CheckPlugin.
12
+ def initialize
13
+ @problems = []
14
+ end
15
+
16
+ # Internal: Check the manifest for problems and filter out any problems that
17
+ # should be ignored.
18
+ #
19
+ # Returns an Array of problem Hashes.
20
+ def run
21
+ check
22
+
23
+ @problems.each do |problem|
24
+ if PuppetLint::Data.ignore_overrides[problem[:check]].has_key?(problem[:line])
25
+ problem[:kind] = :ignored
26
+ problem[:reason] = PuppetLint::Data.ignore_overrides[problem[:check]][problem[:line]]
27
+ next
28
+ end
29
+ end
30
+
31
+ @problems
32
+ end
33
+
34
+ # Internal: Fix any problems the check plugin has detected.
35
+ #
36
+ # Returns an Array of problem Hashes.
37
+ def fix_problems
38
+ @problems.reject { |problem| problem[:kind] == :ignored }.each do |problem|
39
+ if self.respond_to?(:fix)
40
+ begin
41
+ fix(problem)
42
+ rescue PuppetLint::NoFix
43
+ # noop
44
+ else
45
+ problem[:kind] = :fixed
46
+ end
47
+ end
48
+ end
49
+
50
+ @problems
51
+ end
52
+
53
+ private
54
+
55
+ # Public: Provides the tokenised manifest to the check plugins.
56
+ #
57
+ # Returns an Array of PuppetLint::Lexer::Token objects.
58
+ def tokens
59
+ PuppetLint::Data.tokens
60
+ end
61
+
62
+ # Public: Provides the resource titles to the check plugins.
63
+ #
64
+ # Returns an Array of PuppetLint::Lexer::Token objects.
65
+ def title_tokens
66
+ PuppetLint::Data.title_tokens
67
+ end
68
+
69
+ # Public: Provides positional information for any resource declarations in
70
+ # the tokens array to the check plugins.
71
+ #
72
+ # Returns an Array of Hashes containing the position information.
73
+ def resource_indexes
74
+ PuppetLint::Data.resource_indexes
75
+ end
76
+
77
+ # Public: Provides positional information for any class definitions in the
78
+ # tokens array to the check plugins.
79
+ #
80
+ # Returns an Array of Hashes containing the position information.
81
+ def class_indexes
82
+ PuppetLint::Data.class_indexes
83
+ end
84
+
85
+ # Public: Provides positional information for any defined type definitions in
86
+ # the tokens array to the check plugins.
87
+ #
88
+ # Returns an Array of Hashes containing the position information.
89
+ def defined_type_indexes
90
+ PuppetLint::Data.defined_type_indexes
91
+ end
92
+
93
+ # Public: Provides positional information for any node definitions in the
94
+ # tokens array to the check plugins.
95
+ #
96
+ # Returns an Array of Hashes containing the position information.
97
+ def node_indexes
98
+ PuppetLint::Data.node_indexes
99
+ end
100
+
101
+ # Public: Provides the expanded path of the file being analysed to check
102
+ # plugins.
103
+ #
104
+ # Returns the String path.
105
+ def fullpath
106
+ PuppetLint::Data.fullpath
107
+ end
108
+
109
+ # Public: Provides the path of the file being analysed as it was provided to
110
+ # puppet-lint to the check plugins.
111
+ #
112
+ # Returns the String path.
113
+ def path
114
+ PuppetLint::Data.path
115
+ end
116
+
117
+ # Public: Provides the name of the file being analysed to the check plugins.
118
+ #
119
+ # Returns the String file name.
120
+ def filename
121
+ PuppetLint::Data.filename
122
+ end
123
+
124
+ # Public: Provides a list of formatting tokens to the check plugins.
125
+ #
126
+ # Returns an Array of Symbol token types.
127
+ def formatting_tokens
128
+ PuppetLint::Data.formatting_tokens
129
+ end
130
+
131
+ # Public: Provides a list of manifest lines to the check plugins.
132
+ #
133
+ # Returns an Array of manifest lines.
134
+ def manifest_lines
135
+ PuppetLint::Data.manifest_lines
136
+ end
137
+
138
+ # Internal: Prepare default problem report information.
139
+ #
140
+ # Returns a Hash of default problem information.
141
+ def default_info
142
+ @default_info ||= {
143
+ :check => self.class.const_get('NAME'),
144
+ :fullpath => fullpath,
145
+ :path => path,
146
+ :filename => filename,
147
+ }
148
+ end
149
+
150
+ # Public: Report a problem with the manifest being checked.
151
+ #
152
+ # kind - The Symbol problem type (:warning or :error).
153
+ # problem - A Hash containing the attributes of the problem
154
+ # :message - The String message describing the problem.
155
+ # :line - The Integer line number of the location of the problem.
156
+ # :column - The Integer column number of the location of the problem.
157
+ # :check - The Symbol name of the check that detected the problem.
158
+ #
159
+ # Returns nothing.
160
+ def notify(kind, problem)
161
+ problem[:kind] = kind
162
+ problem.merge!(default_info) { |key, v1, v2| v1 }
163
+
164
+ unless [:warning, :error, :fixed].include? kind
165
+ raise ArgumentError, "unknown value passed for kind"
166
+ end
167
+
168
+ [:message, :line, :column, :check].each do |attr|
169
+ unless problem.has_key? attr
170
+ raise ArgumentError, "problem hash must contain #{attr.inspect}"
171
+ end
172
+ end
173
+
174
+ @problems << problem
175
+ end
176
+ end
@@ -0,0 +1,91 @@
1
+ require 'puppet-lint/checkplugin'
2
+
3
+ # Internal: Various methods that orchestrate the actions of the puppet-lint
4
+ # check plugins.
5
+ class PuppetLint::Checks
6
+ # Public: Get an Array of problem Hashes.
7
+ attr_accessor :problems
8
+
9
+ # Public: Initialise a new PuppetLint::Checks object.
10
+ def initialize
11
+ @problems = []
12
+ end
13
+
14
+ # Internal: Tokenise the manifest code and prepare it for checking.
15
+ #
16
+ # path - The path to the file as passed to puppet-lint as a String.
17
+ # content - The String manifest code to be checked.
18
+ #
19
+ # Returns nothing.
20
+ def load_data(path, content)
21
+ lexer = PuppetLint::Lexer.new
22
+ PuppetLint::Data.path = path
23
+ PuppetLint::Data.manifest_lines = content.split("\n", -1)
24
+ begin
25
+ PuppetLint::Data.tokens = lexer.tokenise(content)
26
+ PuppetLint::Data.parse_control_comments
27
+ rescue PuppetLint::LexerError => e
28
+ problems << {
29
+ :kind => :error,
30
+ :check => :syntax,
31
+ :message => 'Syntax error (try running `puppet parser validate <file>`)',
32
+ :line => e.line_no,
33
+ :column => e.column,
34
+ :fullpath => PuppetLint::Data.fullpath,
35
+ :path => PuppetLint::Data.path,
36
+ :filename => PuppetLint::Data.filename,
37
+ }
38
+ PuppetLint::Data.tokens = []
39
+ end
40
+ end
41
+
42
+ # Internal: Run the lint checks over the manifest code.
43
+ #
44
+ # fileinfo - A Hash containing the following:
45
+ # :fullpath - The expanded path to the file as a String.
46
+ # :filename - The name of the file as a String.
47
+ # :path - The original path to the file as passed to puppet-lint as
48
+ # a String.
49
+ # data - The String manifest code to be checked.
50
+ #
51
+ # Returns an Array of problem Hashes.
52
+ def run(fileinfo, data)
53
+ load_data(fileinfo, data)
54
+
55
+ checks_run = []
56
+ enabled_checks.each do |check|
57
+ klass = PuppetLint.configuration.check_object[check].new
58
+ problems = klass.run
59
+
60
+ if PuppetLint.configuration.fix
61
+ checks_run << klass
62
+ else
63
+ @problems.concat(problems)
64
+ end
65
+ end
66
+
67
+ checks_run.each do |check|
68
+ @problems.concat(check.fix_problems)
69
+ end
70
+
71
+ @problems
72
+ end
73
+
74
+ # Internal: Get a list of checks that have not been disabled.
75
+ #
76
+ # Returns an Array of String check names.
77
+ def enabled_checks
78
+ @enabled_checks ||= Proc.new do
79
+ PuppetLint.configuration.checks.select { |check|
80
+ PuppetLint.configuration.send("#{check}_enabled?")
81
+ }
82
+ end.call
83
+ end
84
+
85
+ # Internal: Render the fixed manifest.
86
+ #
87
+ # Returns the manifest as a String.
88
+ def manifest
89
+ PuppetLint::Data.tokens.map { |t| t.to_manifest }.join('')
90
+ end
91
+ end
@@ -0,0 +1,153 @@
1
+ class PuppetLint
2
+ # Public: A singleton class to store the running configuration of
3
+ # puppet-lint.
4
+ class Configuration
5
+ # Internal: Add helper methods for a new check to the
6
+ # PuppetLint::Configuration object.
7
+ #
8
+ # check - The String name of the check.
9
+ #
10
+ # Returns nothing.
11
+ #
12
+ # Signature
13
+ #
14
+ # <check>_enabled?
15
+ # disable_<check>
16
+ # enable_<check>
17
+ def self.add_check(check)
18
+ # Public: Determine if the named check is enabled.
19
+ #
20
+ # Returns true if the check is enabled, otherwise return false.
21
+ define_method("#{check}_enabled?") do
22
+ settings["#{check}_disabled"] == true ? false : true
23
+ end
24
+
25
+ # Public: Disable the named check.
26
+ #
27
+ # Returns nothing.
28
+ define_method("disable_#{check}") do
29
+ settings["#{check}_disabled"] = true
30
+ end
31
+
32
+ # Public: Enable the named check.
33
+ #
34
+ # Returns nothing.
35
+ define_method("enable_#{check}") do
36
+ settings["#{check}_disabled"] = false
37
+ end
38
+ end
39
+
40
+ # Public: Catch situations where options are being set for the first time
41
+ # and create the necessary methods to get & set the option in the future.
42
+ #
43
+ # args - An Array of values to set the option to.
44
+ # method - The String name of the option.
45
+ # block - Unused.
46
+ #
47
+ # Returns nothing.
48
+ #
49
+ # Signature
50
+ #
51
+ # <option>=(value)
52
+ def method_missing(method, *args, &block)
53
+ if method.to_s =~ /^(\w+)=$/
54
+ option = $1
55
+ add_option(option.to_s) if settings[option].nil?
56
+ settings[option] = args[0]
57
+ else
58
+ nil
59
+ end
60
+ end
61
+
62
+ # Internal: Add options to the PuppetLint::Configuration object from inside
63
+ # the class.
64
+ #
65
+ # option - The String name of the option.
66
+ #
67
+ # Returns nothing.
68
+ #
69
+ # Signature
70
+ #
71
+ # <option>
72
+ # <option>=(value)
73
+ def add_option(option)
74
+ self.class.add_option(option)
75
+ end
76
+
77
+ # Public: Add an option to the PuppetLint::Configuration object from
78
+ # outside the class.
79
+ #
80
+ # option - The String name of the option.
81
+ #
82
+ # Returns nothing.
83
+ #
84
+ # Signature
85
+ #
86
+ # <option>
87
+ # <option>=(value)
88
+ def self.add_option(option)
89
+ # Public: Set the value of the named option.
90
+ #
91
+ # value - The value to set the option to.
92
+ #
93
+ # Returns nothing.
94
+ define_method("#{option}=") do |value|
95
+ settings[option] = value
96
+ end
97
+
98
+ # Public: Get the value of the named option.
99
+ #
100
+ # Returns the value of the option.
101
+ define_method(option) do
102
+ settings[option]
103
+ end
104
+ end
105
+
106
+ # Internal: Register a new check.
107
+ #
108
+ # check - The String name of the check
109
+ # klass - The Class containing the check logic.
110
+ #
111
+ # Returns nothing.
112
+ def add_check(check, klass)
113
+ self.class.add_check(check)
114
+ check_object[check] = klass
115
+ end
116
+
117
+ # Internal: Access the internal storage for settings.
118
+ #
119
+ # Returns a Hash containing all the settings.
120
+ def settings
121
+ @settings ||= {}
122
+ end
123
+
124
+ # Internal: Access the internal storage for check method blocks.
125
+ #
126
+ # Returns a Hash containing all the check blocks.
127
+ def check_object
128
+ @check_object ||= {}
129
+ end
130
+
131
+ # Public: Get a list of all the defined checks.
132
+ #
133
+ # Returns an Array of String check names.
134
+ def checks
135
+ check_object.keys
136
+ end
137
+
138
+ # Public: Clear the PuppetLint::Configuration storage and set some sane
139
+ # default values.
140
+ #
141
+ # Returns nothing.
142
+ def defaults
143
+ settings.clear
144
+ self.with_filename = false
145
+ self.fail_on_warnings = false
146
+ self.error_level = :all
147
+ self.log_format = ''
148
+ self.with_context = false
149
+ self.fix = false
150
+ self.show_ignored = false
151
+ end
152
+ end
153
+ end