puppet-lint 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
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/