puppet-lint 0.1.7 → 0.1.8

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.
data/README.md CHANGED
@@ -76,3 +76,5 @@ At the moment, the following tests have been implemented:
76
76
  If you find a bug in puppet-lint or its results, please create an issue in the
77
77
  [repo issues tracker](https://github.com/rodjek/puppet-lint/issues/). Bonus
78
78
  points will be awarded if you also include a patch that fixes the issue.
79
+
80
+ ## Build status
@@ -17,7 +17,9 @@ require 'optparse'
17
17
  require 'rubygems'
18
18
  require 'puppet-lint'
19
19
 
20
- options = {}
20
+ options = {
21
+ :error_level => :all,
22
+ }
21
23
  opts = OptionParser.new do |opts|
22
24
  opts.banner = help
23
25
 
@@ -26,6 +28,14 @@ opts = OptionParser.new do |opts|
26
28
  exit 0
27
29
  end
28
30
 
31
+ opts.on("--with-filename", "Display the filename before the warning") do
32
+ options[:with_filename] = true
33
+ end
34
+
35
+ opts.on("--error-level LEVEL", [:all, :warning, :error], "The level of error to return (warning, error, all).") do |el|
36
+ options[:error_level] = el
37
+ end
38
+
29
39
  opts.on("--fail-on-warnings", "Return a non-zero exit status for warnings.") do
30
40
  options[:fail_on_warnings] = true
31
41
  end
@@ -47,8 +57,9 @@ if ARGV[0].nil?
47
57
  end
48
58
 
49
59
  begin
50
- l = PuppetLint.new
60
+ l = PuppetLint.new(options)
51
61
  l.file = ARGV[0]
62
+ l.show_filename = options.has_key?(:with_filename) ? options[:with_filename] : false
52
63
  l.run
53
64
 
54
65
  if l.errors? or (l.warnings? and options[:fail_on_warnings])
@@ -10,21 +10,33 @@ end
10
10
  require 'puppet-lint/plugin'
11
11
  require 'puppet-lint/plugins'
12
12
 
13
+ unless String.respond_to?('prepend')
14
+ class String
15
+ def prepend(lead)
16
+ self.replace "#{lead}#{self}"
17
+ end
18
+ end
19
+ end
20
+
13
21
  class PuppetLint::NoCodeError < StandardError; end
14
22
 
15
23
  class PuppetLint
16
- VERSION = '0.1.7'
24
+ VERSION = '0.1.8'
17
25
 
18
- attr_reader :code, :file
26
+ attr_reader :code, :file, :show_filename
19
27
 
20
- def initialize
28
+ def initialize(options)
21
29
  @data = nil
22
30
  @errors = 0
23
31
  @warnings = 0
32
+ @show_filename = 0
33
+ @path = ''
34
+ @error_level = options[:error_level]
24
35
  end
25
36
 
26
37
  def file=(path)
27
38
  if File.exist? path
39
+ @path = path
28
40
  @data = File.read(path)
29
41
  end
30
42
  end
@@ -33,14 +45,23 @@ class PuppetLint
33
45
  @data = value
34
46
  end
35
47
 
48
+ def show_filename=(value)
49
+ @show_filename = value
50
+ end
51
+
36
52
  def report(kind, message)
53
+ #msg = message
37
54
  if kind == :warnings
38
55
  @warnings += 1
39
- puts "WARNING: #{message}"
56
+ message.prepend('WARNING: ')
40
57
  else
41
58
  @errors += 1
42
- puts "ERROR: #{message}"
59
+ message.prepend('ERROR: ')
60
+ end
61
+ if @show_filename
62
+ message.prepend("#{@path} - ")
43
63
  end
64
+ puts message
44
65
  end
45
66
 
46
67
  def errors?
@@ -57,9 +78,16 @@ class PuppetLint
57
78
  end
58
79
 
59
80
  PuppetLint::CheckPlugin.repository.each do |plugin|
60
- problems = plugin.new.run(@data)
61
- problems[:errors].each { |error| report :errors, error }
62
- problems[:warnings].each { |warning| report :warnings, warning }
81
+ problems = plugin.new.run(@path, @data)
82
+ case @error_level
83
+ when :warning
84
+ problems[:warnings].each { |warning| report :warnings, warning }
85
+ when :error
86
+ problems[:errors].each { |error| report :errors, error }
87
+ else
88
+ problems[:warnings].each { |warning| report :warnings, warning }
89
+ problems[:errors].each { |error| report :errors, error }
90
+ end
63
91
  end
64
92
  end
65
93
  end
@@ -33,8 +33,8 @@ class PuppetLint::CheckPlugin
33
33
  @errors << message
34
34
  end
35
35
 
36
- def run(data)
37
- test(data)
36
+ def run(path, data)
37
+ test(path, data)
38
38
 
39
39
  {:warnings => @warnings, :errors => @errors}
40
40
  end
@@ -6,5 +6,6 @@ end
6
6
  require 'puppet-lint/plugins/check_classes'
7
7
  require 'puppet-lint/plugins/check_conditionals'
8
8
  require 'puppet-lint/plugins/check_strings'
9
+ require 'puppet-lint/plugins/check_variables'
9
10
  require 'puppet-lint/plugins/check_whitespace'
10
11
  require 'puppet-lint/plugins/check_resources'
@@ -1,5 +1,5 @@
1
1
  class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
2
- def test(data)
2
+ def test(path, data)
3
3
  lexer = Puppet::Parser::Lexer.new
4
4
  lexer.string = data
5
5
  tokens = lexer.fullscan
@@ -16,16 +16,35 @@ class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
16
16
  lparen_idx = tokens[token_idx..(header_end_idx + token_idx)].index { |r| r.first == :LPAREN }
17
17
  rparen_idx = tokens[token_idx..(header_end_idx + token_idx)].rindex { |r| r.first == :RPAREN }
18
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
28
+
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
33
+ end
34
+
19
35
  unless lparen_idx.nil? or rparen_idx.nil?
20
36
  param_tokens = tokens[lparen_idx..rparen_idx]
21
37
  param_tokens.each_index do |param_tokens_idx|
22
38
  this_token = param_tokens[param_tokens_idx]
23
39
  next_token = param_tokens[param_tokens_idx+1]
40
+ prev_token = param_tokens[param_tokens_idx-1]
24
41
  if this_token.first == :VARIABLE
25
42
  unless next_token.nil?
26
43
  if next_token.first == :COMMA or next_token.first == :RPAREN
27
44
  unless param_tokens[0..param_tokens_idx].rindex { |r| r.first == :EQUALS }.nil?
28
- warn "optional parameter listed before required parameter on line #{this_token.last[:line]}"
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
29
48
  end
30
49
  end
31
50
  end
@@ -1,5 +1,5 @@
1
1
  class PuppetLint::Plugins::CheckConditionals < PuppetLint::CheckPlugin
2
- def test(data)
2
+ def test(path, data)
3
3
  lexer = Puppet::Parser::Lexer.new
4
4
  lexer.string = data
5
5
  tokens = lexer.fullscan
@@ -2,7 +2,7 @@
2
2
  # http://docs.puppetlabs.com/guides/style_guide.html#resources
3
3
 
4
4
  class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
5
- def test(data)
5
+ def test(path, data)
6
6
  lexer = Puppet::Parser::Lexer.new
7
7
  lexer.string = data
8
8
  tokens = lexer.fullscan
@@ -14,7 +14,7 @@ class PuppetLint::Plugins::CheckStrings < PuppetLint::CheckPlugin
14
14
  end
15
15
  end
16
16
 
17
- def test(data)
17
+ def test(path, data)
18
18
  l = Puppet::Parser::Lexer.new
19
19
  l.string = data
20
20
  tokens = l.fullscan
@@ -48,6 +48,15 @@ class PuppetLint::Plugins::CheckStrings < PuppetLint::CheckPlugin
48
48
  end
49
49
  end
50
50
 
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
59
+
51
60
  if token.first == :SSTRING
52
61
  contents = token.last[:value]
53
62
  line_no = token.last[:line]
@@ -55,6 +64,10 @@ class PuppetLint::Plugins::CheckStrings < PuppetLint::CheckPlugin
55
64
  if contents.include? '${'
56
65
  error "single quoted string containing a variable found on line #{token.last[:line]}"
57
66
  end
67
+
68
+ if ['true', 'false'].include? contents
69
+ warn "quoted boolean value found on line #{token.last[:line]}"
70
+ end
58
71
  end
59
72
  end
60
73
  end
@@ -0,0 +1,19 @@
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
+
7
+ tokens.each_index do |token_idx|
8
+ token = tokens[token_idx]
9
+
10
+ if token.first == :VARIABLE
11
+ variable = token.last[:value]
12
+ line_no = token.last[:line]
13
+ if variable.match(/-/)
14
+ warn "Variable contains a dash on line #{line_no}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,13 +1,12 @@
1
1
  # Spacing, Identation & Whitespace
2
- # http://http://docs.puppetlabs.com/guides/style_guide.html#spacing-indentation--whitespace
2
+ # http://docs.puppetlabs.com/guides/style_guide.html#spacing-indentation--whitespace
3
3
 
4
4
  class PuppetLint::Plugins::CheckWhitespace < PuppetLint::CheckPlugin
5
- def test(data)
5
+ def test(path, data)
6
6
  line_no = 0
7
7
  in_resource = false
8
- in_selector = false
8
+ selectors = []
9
9
  resource_indent_length = 0
10
- selector_indent_length = 0
11
10
  data.split("\n").each do |line|
12
11
  line_no += 1
13
12
 
@@ -30,44 +29,43 @@ class PuppetLint::Plugins::CheckWhitespace < PuppetLint::CheckPlugin
30
29
  end
31
30
 
32
31
  # SHOULD align fat comma arrows (=>) within blocks of attributes
33
- if in_selector
34
- if line.strip =~ /\}[,;]?$/
35
- in_selector = false
36
- selector_indent_length = 0
37
- end
38
- end
39
-
40
- if line =~ /^( +\w+ +)=>/
32
+ if line =~ /^( +.+? +)=>/
41
33
  line_indent = $1
42
34
  if in_resource
43
- if in_selector
44
- if selector_indent_length == 0
45
- selector_indent_length = line_indent.length
35
+ if selectors.count > 0
36
+ if selectors.last == 0
37
+ selectors[-1] = line_indent.length
46
38
  end
47
39
 
48
- unless line_indent.length == selector_indent_length
49
- warn "=> on line #{line_no} isn't aligned with the previous line"
40
+ # check for length first
41
+ unless line_indent.length == selectors.last
42
+ warn "=> on line #{line_no} isn't properly aligned for selector"
50
43
  end
51
44
 
52
- if line.strip =~ /\}[,;]?$/
53
- in_selector = false
54
- selector_indent_length = 0
55
- end
56
- else
45
+ # then for a new selector or selector finish
57
46
  if line.strip.end_with? "{"
58
- in_selector = true
47
+ selectors.push(0)
48
+ elsif line.strip =~ /\}[,;]?$/
49
+ selectors.pop
59
50
  end
51
+ else
60
52
  unless line_indent.length == resource_indent_length
61
- warn "=> on line #{line_no} isn't aligned with the previous line"
53
+ warn "=> on line #{line_no} isn't properly aligned for resource"
54
+ end
55
+
56
+ if line.strip.end_with? "{"
57
+ selectors.push(0)
62
58
  end
63
59
  end
64
60
  else
65
61
  resource_indent_length = line_indent.length
66
62
  in_resource = true
67
63
  if line.strip.end_with? "{"
68
- in_selector = true
64
+ selectors.push(0)
69
65
  end
70
66
  end
67
+ elsif line.strip =~ /\}[,;]?$/ and selectors.count > 0
68
+ selectors.pop
71
69
  else
72
70
  in_resource = false
73
71
  resource_indent_length = 0
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'puppet-lint'
3
- s.version = '0.1.7'
3
+ s.version = '0.1.8'
4
4
  s.homepage = 'https://github.com/rodjek/puppet-lint/'
5
5
  s.summary = 'Ensure your Puppet manifests conform with the Puppetlabs style guide'
6
6
  s.description = 'Checks your Puppet manifests against the Puppetlabs
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
14
14
  'lib/puppet-lint/plugins/check_conditionals.rb',
15
15
  'lib/puppet-lint/plugins/check_resources.rb',
16
16
  'lib/puppet-lint/plugins/check_strings.rb',
17
+ 'lib/puppet-lint/plugins/check_variables.rb',
17
18
  'lib/puppet-lint/plugins/check_whitespace.rb',
18
19
  'lib/puppet-lint/plugins.rb',
19
20
  'lib/puppet-lint/tasks/puppet-lint.rb',
@@ -26,6 +27,7 @@ Gem::Specification.new do |s|
26
27
  'spec/puppet-lint/check_conditionals_spec.rb',
27
28
  'spec/puppet-lint/check_resources_spec.rb',
28
29
  'spec/puppet-lint/check_strings_spec.rb',
30
+ 'spec/puppet-lint/check_variables_spec.rb',
29
31
  'spec/puppet-lint/check_whitespace_spec.rb',
30
32
  'spec/spec_helper.rb',
31
33
  ]
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe PuppetLint::Plugins::CheckClasses do
4
4
  subject do
5
5
  klass = described_class.new
6
- klass.test(code)
6
+ klass.test(defined?(path).nil? ? '' : path, code)
7
7
  klass
8
8
  end
9
9
 
@@ -197,4 +197,56 @@ describe PuppetLint::Plugins::CheckClasses do
197
197
  its(:warnings) { should be_empty }
198
198
  its(:errors) { should be_empty }
199
199
  end
200
+
201
+ describe 'class/define parameter set to another variable' do
202
+ let(:code) { "
203
+ define foo($bar, $baz = $name, $gronk=$::fqdn) {
204
+ }"
205
+ }
206
+
207
+ its(:warnings) { should be_empty }
208
+ its(:errors) { should be_empty }
209
+ end
210
+
211
+ describe 'class/define parameter set to another variable with incorrect order' do
212
+ let(:code) { "
213
+ define foo($baz = $name, $bar, $gronk=$::fqdn) {
214
+ }"
215
+ }
216
+
217
+ its(:warnings) { should include "optional parameter listed before required parameter on line 2" }
218
+ its(:errors) { should be_empty }
219
+ end
220
+
221
+ describe 'foo::bar in foo/manifests/bar.pp' do
222
+ let(:code) { "class foo::bar { }" }
223
+ let(:path) { '/etc/puppet/modules/foo/manifests/bar.pp' }
224
+
225
+ its(:warnings) { should be_empty }
226
+ its(:errors) { should be_empty }
227
+ end
228
+
229
+ describe 'foo::bar::baz in foo/manifests/bar/baz.pp' do
230
+ let(:code) { 'define foo::bar::baz() { }' }
231
+ let(:path) { '/etc/puppet/modules/foo/manifests/bar/baz.pp' }
232
+
233
+ its(:warnings) { should be_empty }
234
+ its(:errors) { should be_empty }
235
+ end
236
+
237
+ describe 'foo in foo/manifests/init.pp' do
238
+ let(:code) { 'class foo { }' }
239
+ let(:path) { '/etc/puppet/modules/foo/manifests/init.pp' }
240
+
241
+ its(:warnings) { should be_empty }
242
+ its(:errors) { should be_empty }
243
+ end
244
+
245
+ describe 'foo::bar in foo/manifests/init.pp' do
246
+ let(:code) { 'class foo::bar { }' }
247
+ let(:path) { '/etc/puppet/modules/foo/manifests/init.pp' }
248
+
249
+ its(:warnings) { should be_empty }
250
+ its(:errors) { should include "foo::bar not in autoload module layout on line 1" }
251
+ end
200
252
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe PuppetLint::Plugins::CheckConditionals do
4
4
  subject do
5
5
  klass = described_class.new
6
- klass.test(code)
6
+ klass.test(defined?(path).nil? ? '' : path, code)
7
7
  klass
8
8
  end
9
9
 
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe PuppetLint::Plugins::CheckResources do
4
4
  subject do
5
5
  klass = described_class.new
6
- klass.test(code)
6
+ klass.test(defined?(path).nil? ? '' : path, code)
7
7
  klass
8
8
  end
9
9
 
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe PuppetLint::Plugins::CheckStrings do
4
4
  subject do
5
5
  klass = described_class.new
6
- klass.test(code)
6
+ klass.test(defined?(path).nil? ? '' : path, code)
7
7
  klass
8
8
  end
9
9
 
@@ -35,6 +35,15 @@ describe PuppetLint::Plugins::CheckStrings do
35
35
  its(:errors) { should be_empty }
36
36
  end
37
37
 
38
+ if Puppet.version.start_with? "2.7"
39
+ describe 'variable containing a dash' do
40
+ let(:code) { '" $foo-bar"' }
41
+
42
+ its(:warnings) { should include "variable contains a dash on line 1" }
43
+ its(:errors) { should be_empty }
44
+ end
45
+ end
46
+
38
47
  describe 'double quoted string nested in a single quoted string' do
39
48
  let(:code) { "'grep \"status=sent\" /var/log/mail.log'" }
40
49
 
@@ -55,4 +64,18 @@ describe PuppetLint::Plugins::CheckStrings do
55
64
  its(:warnings) { should be_empty }
56
65
  its(:errors) { should be_empty }
57
66
  end
67
+
68
+ describe 'quoted false' do
69
+ let(:code) { "class { 'foo': boolFlag => 'false' }" }
70
+
71
+ its(:warnings) { should include "quoted boolean value found on line 1" }
72
+ its(:errors) { should be_empty }
73
+ end
74
+
75
+ describe 'quoted true' do
76
+ let(:code) { "class { 'foo': boolFlag => 'true' }" }
77
+
78
+ its(:warnings) { should include "quoted boolean value found on line 1" }
79
+ its(:errors) { should be_empty }
80
+ end
58
81
  end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe PuppetLint::Plugins::CheckVariables do
4
+ subject do
5
+ klass = described_class.new
6
+ klass.test(defined?(path).nil? ? '' : path, code)
7
+ klass
8
+ end
9
+
10
+ if Puppet.version.start_with? "2.7"
11
+ describe 'a variable containing a dash' do
12
+ let(:code) { "$foo-bar" }
13
+
14
+ its(:warnings) { should include "Variable contains a dash on line 1" }
15
+ its(:errors) { should be_empty }
16
+ end
17
+ end
18
+ end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe PuppetLint::Plugins::CheckWhitespace do
4
4
  subject do
5
5
  klass = described_class.new
6
- klass.test(code)
6
+ klass.test(defined?(path).nil? ? '' : path, code)
7
7
  klass
8
8
  end
9
9
 
@@ -61,4 +61,53 @@ describe PuppetLint::Plugins::CheckWhitespace do
61
61
  its(:warnings) { should be_empty }
62
62
  its(:errors) { should be_empty }
63
63
  end
64
+
65
+ describe 'selector inside a hash inside a resource' do
66
+ let(:code) { "
67
+ server => {
68
+ ensure => ensure => $ensure ? {
69
+ present => directory,
70
+ absent => undef,
71
+ },
72
+ ip => '192.168.1.1'
73
+ },
74
+ owner => 'foo4',
75
+ group => 'foo4',
76
+ mode => '0755'," }
77
+
78
+ its(:warnings) { should be_empty }
79
+ its(:errors) { should be_empty }
80
+ end
81
+
82
+ describe 'issue #37' do
83
+ let(:code) { "
84
+ class { 'lvs::base':
85
+ virtualeservers => {
86
+ '192.168.2.13' => {
87
+ vport => '11025',
88
+ service => 'smtp',
89
+ scheduler => 'wlc',
90
+ protocol => 'tcp',
91
+ checktype => 'external',
92
+ checkcommand => '/path/to/checkscript',
93
+ real_servers => {
94
+ 'server01' => {
95
+ real_server => '192.168.2.14',
96
+ real_port => '25',
97
+ forwarding => 'masq',
98
+ },
99
+ 'server02' => {
100
+ real_server => '192.168.2.15',
101
+ real_port => '25',
102
+ forwarding => 'masq',
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }"
108
+ }
109
+
110
+ its(:warnings) { should be_empty }
111
+ its(:errors) { should be_empty }
112
+ end
64
113
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet-lint
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 7
10
- version: 0.1.7
9
+ - 8
10
+ version: 0.1.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tim Sharpe
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-10-18 00:00:00 Z
18
+ date: 2011-12-27 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rspec
@@ -48,6 +48,7 @@ files:
48
48
  - lib/puppet-lint/plugins/check_conditionals.rb
49
49
  - lib/puppet-lint/plugins/check_resources.rb
50
50
  - lib/puppet-lint/plugins/check_strings.rb
51
+ - lib/puppet-lint/plugins/check_variables.rb
51
52
  - lib/puppet-lint/plugins/check_whitespace.rb
52
53
  - lib/puppet-lint/plugins.rb
53
54
  - lib/puppet-lint/tasks/puppet-lint.rb
@@ -60,6 +61,7 @@ files:
60
61
  - spec/puppet-lint/check_conditionals_spec.rb
61
62
  - spec/puppet-lint/check_resources_spec.rb
62
63
  - spec/puppet-lint/check_strings_spec.rb
64
+ - spec/puppet-lint/check_variables_spec.rb
63
65
  - spec/puppet-lint/check_whitespace_spec.rb
64
66
  - spec/spec_helper.rb
65
67
  homepage: https://github.com/rodjek/puppet-lint/