puppet-lint 0.0.7 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +22 -1
- data/lib/puppet-lint/plugins/check_classes.rb +119 -0
- data/lib/puppet-lint/plugins/check_conditionals.rb +59 -0
- data/lib/puppet-lint/plugins/check_resources.rb +8 -1
- data/lib/puppet-lint/plugins/check_strings.rb +4 -0
- data/lib/puppet-lint/plugins/check_whitespace.rb +7 -1
- data/lib/puppet-lint/plugins.rb +2 -0
- data/lib/puppet-lint.rb +1 -1
- data/puppet-lint.gemspec +5 -1
- data/spec/puppet-lint/check_classes_spec.rb +163 -0
- data/spec/puppet-lint/check_conditionals_spec.rb +58 -0
- data/spec/puppet-lint/check_resources_spec.rb +23 -0
- data/spec/puppet-lint/check_strings_spec.rb +7 -0
- data/spec/puppet-lint/check_whitespace_spec.rb +15 -0
- metadata +8 -4
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
The goal of this project is to implement as many of the recommended Puppet
|
4
4
|
style guidelines from the [Puppetlabs style
|
5
|
-
guide](http://docs.puppetlabs.com/guides/style_guide.html).
|
5
|
+
guide](http://docs.puppetlabs.com/guides/style_guide.html) as practical.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -40,15 +40,36 @@ At the moment, the following tests have been implemented:
|
|
40
40
|
quotes.
|
41
41
|
* All strings that contain variables must be enclosed in double quotes.
|
42
42
|
* All variables should be enclosed in braces when interpolated in a string.
|
43
|
+
* Variables standing by themselves should not be quoted.
|
43
44
|
|
44
45
|
### Resources
|
45
46
|
|
46
47
|
* All resource titles should be quoted.
|
47
48
|
* If a resource declaration includes an `ensure` attribute, it should be the
|
48
49
|
first attribute specified.
|
50
|
+
* Symbolic links should be declared by using an ensure value of `link` and
|
51
|
+
explicitly specifying a value for the `target` attribute.
|
49
52
|
* File modes should be represented as a 4 digit string enclosed in single
|
50
53
|
quotes.
|
51
54
|
|
55
|
+
### Conditionals
|
56
|
+
|
57
|
+
* You should not intermingle conditionals inside resource declarations (i.e.
|
58
|
+
selectors inside resources).
|
59
|
+
* Case statements should have a default case.
|
60
|
+
|
61
|
+
### Classes
|
62
|
+
|
63
|
+
* Relationship declarations with the chaining syntax should only be used in
|
64
|
+
the 'left to right' direction.
|
65
|
+
* Classes should not be defined inside a class.
|
66
|
+
* Defines should not be defined inside a class.
|
67
|
+
* Classes should not inherit between namespaces.
|
68
|
+
* Required parameters in class & defined type definitions should be listed
|
69
|
+
before optional parameters.
|
70
|
+
# When using top-scope variables, including facts, Puppet modules should
|
71
|
+
explicitly specify the empty namespace.
|
72
|
+
|
52
73
|
## Reporting bugs or incorrect results
|
53
74
|
|
54
75
|
If you find a bug in puppet-lint or its results, please create an issue in the
|
@@ -0,0 +1,119 @@
|
|
1
|
+
class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
|
2
|
+
def test(data)
|
3
|
+
lexer = Puppet::Parser::Lexer.new
|
4
|
+
lexer.string = data
|
5
|
+
tokens = lexer.fullscan
|
6
|
+
|
7
|
+
tokens.select { |r| r.first == :OUT_EDGE }.each do |token|
|
8
|
+
warn "right-to-left (<-) relationship on line #{token.last[:line]}"
|
9
|
+
end
|
10
|
+
|
11
|
+
class_indexes = []
|
12
|
+
defined_type_indexes = []
|
13
|
+
tokens.each_index do |token_idx|
|
14
|
+
if [:DEFINE, :CLASS].include? tokens[token_idx].first
|
15
|
+
header_end_idx = tokens[token_idx..-1].index { |r| r.first == :LBRACE }
|
16
|
+
lparen_idx = tokens[token_idx..(header_end_idx + token_idx)].index { |r| r.first == :LPAREN }
|
17
|
+
rparen_idx = tokens[token_idx..(header_end_idx + token_idx)].rindex { |r| r.first == :RPAREN }
|
18
|
+
|
19
|
+
unless lparen_idx.nil? or rparen_idx.nil?
|
20
|
+
param_tokens = tokens[lparen_idx..rparen_idx]
|
21
|
+
param_tokens.each_index do |param_tokens_idx|
|
22
|
+
this_token = param_tokens[param_tokens_idx]
|
23
|
+
next_token = param_tokens[param_tokens_idx+1]
|
24
|
+
if this_token.first == :VARIABLE
|
25
|
+
unless next_token.nil?
|
26
|
+
if next_token.first == :COMMA or next_token.first == :RPAREN
|
27
|
+
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]}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if [:CLASS, :DEFINE].include? tokens[token_idx].first
|
38
|
+
if tokens[token_idx].first == :CLASS
|
39
|
+
if tokens[token_idx+2].first == :INHERITS
|
40
|
+
class_name = tokens[token_idx+1].last[:value]
|
41
|
+
inherited_class = tokens[token_idx+3].last[:value]
|
42
|
+
|
43
|
+
unless class_name =~ /^#{inherited_class}::/
|
44
|
+
warn "class inherits across namespaces on line #{tokens[token_idx].last[:line]}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
lbrace_count = 0
|
50
|
+
tokens[token_idx+1..-1].each_index do |class_token_idx|
|
51
|
+
idx = class_token_idx + token_idx
|
52
|
+
if tokens[idx].first == :LBRACE
|
53
|
+
lbrace_count += 1
|
54
|
+
elsif tokens[idx].first == :RBRACE
|
55
|
+
lbrace_count -= 1
|
56
|
+
if lbrace_count == 0
|
57
|
+
class_indexes << {:start => token_idx, :end => idx} if tokens[token_idx].first == :CLASS
|
58
|
+
defined_type_indexes << {:start => token_idx, :end => idx} if tokens[token_idx].first == :DEFINE
|
59
|
+
break
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class_indexes.each do |class_idx|
|
67
|
+
class_tokens = tokens[class_idx[:start]..class_idx[:end]]
|
68
|
+
class_tokens[1..-1].select { |r| r.first == :CLASS }.each do |token|
|
69
|
+
warn "class defined inside a class on line #{token.last[:line]}"
|
70
|
+
end
|
71
|
+
class_tokens[1..-1].select { |r| r.first == :DEFINE }.each do |token|
|
72
|
+
warn "define defined inside a class on line #{token.last[:line]}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
(class_indexes + defined_type_indexes).each do |idx|
|
77
|
+
object_tokens = tokens[idx[:start]..idx[:end]]
|
78
|
+
variables_in_scope = []
|
79
|
+
referenced_variables = []
|
80
|
+
header_end_idx = object_tokens.index { |r| r.first == :LBRACE }
|
81
|
+
lparen_idx = object_tokens[0..header_end_idx].index { |r| r.first == :LPAREN }
|
82
|
+
rparen_idx = object_tokens[0..header_end_idx].rindex { |r| r.first == :RPAREN }
|
83
|
+
|
84
|
+
unless lparen_idx.nil? or rparen_idx.nil?
|
85
|
+
param_tokens = object_tokens[lparen_idx..rparen_idx]
|
86
|
+
param_tokens.each_index do |param_tokens_idx|
|
87
|
+
this_token = param_tokens[param_tokens_idx]
|
88
|
+
next_token = param_tokens[param_tokens_idx+1]
|
89
|
+
if this_token.first == :VARIABLE
|
90
|
+
if [:COMMA, :EQUALS, :RPAREN].include? next_token.first
|
91
|
+
variables_in_scope << this_token.last[:value]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
object_tokens.each_index do |object_token_idx|
|
98
|
+
this_token = object_tokens[object_token_idx]
|
99
|
+
next_token = object_tokens[object_token_idx + 1]
|
100
|
+
|
101
|
+
if this_token.first == :VARIABLE
|
102
|
+
if next_token.first == :EQUALS
|
103
|
+
variables_in_scope << this_token.last[:value]
|
104
|
+
else
|
105
|
+
referenced_variables << this_token
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
referenced_variables.each do |token|
|
111
|
+
unless token.last[:value].include? '::'
|
112
|
+
unless variables_in_scope.include? token.last[:value]
|
113
|
+
warn "top-scope variable being used without an explicit namespace on line #{token.last[:line]}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class PuppetLint::Plugins::CheckConditionals < PuppetLint::CheckPlugin
|
2
|
+
def test(data)
|
3
|
+
lexer = Puppet::Parser::Lexer.new
|
4
|
+
lexer.string = data
|
5
|
+
tokens = lexer.fullscan
|
6
|
+
|
7
|
+
resource_indexes = []
|
8
|
+
case_indexes = []
|
9
|
+
|
10
|
+
tokens.each_index do |token_idx|
|
11
|
+
if tokens[token_idx].first == :COLON
|
12
|
+
# gather a list of start and end indexes for resource attribute blocks
|
13
|
+
if tokens[token_idx+1].first != :LBRACE
|
14
|
+
resource_indexes << {:start => token_idx+1, :end => tokens[token_idx+1..-1].index { |r| [:SEMIC, :RBRACE].include? r.first }+token_idx}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
if tokens[token_idx].first == :CASE
|
19
|
+
lbrace_count = 0
|
20
|
+
tokens[token_idx+1..-1].each_index do |case_token_idx|
|
21
|
+
idx = case_token_idx + token_idx
|
22
|
+
if tokens[idx].first == :LBRACE
|
23
|
+
lbrace_count += 1
|
24
|
+
elsif tokens[idx].first == :RBRACE
|
25
|
+
lbrace_count -= 1
|
26
|
+
if lbrace_count == 0
|
27
|
+
case_indexes << {:start => token_idx, :end => idx}
|
28
|
+
break
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
resource_indexes.each do |resource|
|
36
|
+
resource_tokens = tokens[resource[:start]..resource[:end]]
|
37
|
+
|
38
|
+
resource_tokens.each_index do |resource_token_idx|
|
39
|
+
if resource_tokens[resource_token_idx].first == :FARROW
|
40
|
+
if resource_tokens[resource_token_idx + 1].first == :VARIABLE
|
41
|
+
unless resource_tokens[resource_token_idx + 2].nil?
|
42
|
+
if resource_tokens[resource_token_idx + 2].first == :QMARK
|
43
|
+
warn "selector inside resource block on line #{resource_tokens[resource_token_idx].last[:line]}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
case_indexes.each do |kase|
|
52
|
+
case_tokens = tokens[kase[:start]..kase[:end]]
|
53
|
+
|
54
|
+
unless case_tokens.index { |r| r.first == :DEFAULT }
|
55
|
+
warn "case statement without a default case on line #{case_tokens.first.last[:line]}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -16,7 +16,9 @@ class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
|
|
16
16
|
title_array_tokens = tokens[tokens.rindex { |r| r.first == :LBRACK }+1..token_idx-2]
|
17
17
|
title_tokens += title_array_tokens.select { |token| [:STRING, :NAME].include? token.first }
|
18
18
|
else
|
19
|
-
|
19
|
+
if tokens[token_idx + 1].first != :LBRACE
|
20
|
+
title_tokens << tokens[token_idx-1]
|
21
|
+
end
|
20
22
|
end
|
21
23
|
|
22
24
|
# gather a list of start and end indexes for resource attribute blocks
|
@@ -54,6 +56,11 @@ class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
|
|
54
56
|
if value_token.last[:value] !~ /\d{4}/
|
55
57
|
warn "mode should be represented as a 4 digit octal value on line #{value_token.last[:line]}"
|
56
58
|
end
|
59
|
+
elsif attr_token.first == :NAME and attr_token.last[:value] == 'ensure'
|
60
|
+
value_token = resource_tokens[resource_token_idx + 2]
|
61
|
+
if value_token.last[:value].start_with? '/'
|
62
|
+
warn "symlink target specified in ensure attr on line #{value_token.last[:line]}"
|
63
|
+
end
|
57
64
|
end
|
58
65
|
end
|
59
66
|
end
|
@@ -18,6 +18,10 @@ class PuppetLint::Plugins::CheckStrings < PuppetLint::CheckPlugin
|
|
18
18
|
unless variable_found
|
19
19
|
warn "double quoted string containing no variables on line #{line_no}"
|
20
20
|
end
|
21
|
+
if s =~ /^"\$\{[\w\:]+\}"$/
|
22
|
+
warn "string containing only a variable on line #{line_no}"
|
23
|
+
end
|
24
|
+
|
21
25
|
line = line[line.index('"', line.index('"')+1)..-1]
|
22
26
|
end
|
23
27
|
end
|
@@ -34,6 +34,10 @@ class PuppetLint::Plugins::CheckWhitespace < PuppetLint::CheckPlugin
|
|
34
34
|
line_indent = $1
|
35
35
|
if in_resource
|
36
36
|
if in_selector
|
37
|
+
if selector_indent_length == 0
|
38
|
+
selector_indent_length = line_indent.length
|
39
|
+
end
|
40
|
+
|
37
41
|
unless line_indent.length == selector_indent_length
|
38
42
|
warn "=> on line #{line_no} isn't aligned with the previous line"
|
39
43
|
end
|
@@ -45,7 +49,6 @@ class PuppetLint::Plugins::CheckWhitespace < PuppetLint::CheckPlugin
|
|
45
49
|
else
|
46
50
|
if line.strip.end_with? "{"
|
47
51
|
in_selector = true
|
48
|
-
selector_indent_length = resource_indent_length + 2
|
49
52
|
end
|
50
53
|
unless line_indent.length == resource_indent_length
|
51
54
|
warn "=> on line #{line_no} isn't aligned with the previous line"
|
@@ -54,6 +57,9 @@ class PuppetLint::Plugins::CheckWhitespace < PuppetLint::CheckPlugin
|
|
54
57
|
else
|
55
58
|
resource_indent_length = line_indent.length
|
56
59
|
in_resource = true
|
60
|
+
if line.strip.end_with? "{"
|
61
|
+
in_selector = true
|
62
|
+
end
|
57
63
|
end
|
58
64
|
else
|
59
65
|
in_resource = false
|
data/lib/puppet-lint/plugins.rb
CHANGED
@@ -3,6 +3,8 @@ class PuppetLint
|
|
3
3
|
end
|
4
4
|
end
|
5
5
|
|
6
|
+
require 'puppet-lint/plugins/check_classes'
|
7
|
+
require 'puppet-lint/plugins/check_conditionals'
|
6
8
|
require 'puppet-lint/plugins/check_strings'
|
7
9
|
require 'puppet-lint/plugins/check_whitespace'
|
8
10
|
require 'puppet-lint/plugins/check_resources'
|
data/lib/puppet-lint.rb
CHANGED
data/puppet-lint.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'puppet-lint'
|
3
|
-
s.version = '0.0
|
3
|
+
s.version = '0.1.0'
|
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
|
@@ -10,6 +10,8 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.files = [
|
11
11
|
'bin/puppet-lint',
|
12
12
|
'lib/puppet-lint/plugin.rb',
|
13
|
+
'lib/puppet-lint/plugins/check_classes.rb',
|
14
|
+
'lib/puppet-lint/plugins/check_conditionals.rb',
|
13
15
|
'lib/puppet-lint/plugins/check_resources.rb',
|
14
16
|
'lib/puppet-lint/plugins/check_strings.rb',
|
15
17
|
'lib/puppet-lint/plugins/check_whitespace.rb',
|
@@ -20,6 +22,8 @@ Gem::Specification.new do |s|
|
|
20
22
|
'puppet-lint.gemspec',
|
21
23
|
'Rakefile',
|
22
24
|
'README.md',
|
25
|
+
'spec/puppet-lint/check_classes_spec.rb',
|
26
|
+
'spec/puppet-lint/check_conditionals_spec.rb',
|
23
27
|
'spec/puppet-lint/check_resources_spec.rb',
|
24
28
|
'spec/puppet-lint/check_strings_spec.rb',
|
25
29
|
'spec/puppet-lint/check_whitespace_spec.rb',
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PuppetLint::Plugins::CheckClasses do
|
4
|
+
subject do
|
5
|
+
klass = described_class.new
|
6
|
+
klass.test(code)
|
7
|
+
klass
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'chain 2 resources left to right' do
|
11
|
+
let(:code) { "Class[foo] -> Class[bar]" }
|
12
|
+
|
13
|
+
its(:warnings) { should be_empty }
|
14
|
+
its(:errors) { should be_empty }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'chain 2 resources right to left' do
|
18
|
+
let(:code) { "Class[foo] <- Class[bar]" }
|
19
|
+
|
20
|
+
its(:warnings) { should include "right-to-left (<-) relationship on line 1" }
|
21
|
+
its(:errors) { should be_empty }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'class on its own' do
|
25
|
+
let(:code) { "class foo { }" }
|
26
|
+
|
27
|
+
its(:warnings) { should be_empty }
|
28
|
+
its(:errors) { should be_empty }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'class inside a class' do
|
32
|
+
let(:code) { "
|
33
|
+
class foo {
|
34
|
+
class bar {
|
35
|
+
}
|
36
|
+
}"
|
37
|
+
}
|
38
|
+
|
39
|
+
its(:warnings) { should include "class defined inside a class on line 3" }
|
40
|
+
its(:errors) { should be_empty }
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'define inside a class' do
|
44
|
+
let(:code) { "
|
45
|
+
class foo {
|
46
|
+
define bar() {
|
47
|
+
}
|
48
|
+
}"
|
49
|
+
}
|
50
|
+
|
51
|
+
its(:warnings) { should include "define defined inside a class on line 3" }
|
52
|
+
its(:errors) { should be_empty }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'class inheriting from its namespace' do
|
56
|
+
let(:code) { "class foo::bar inherits foo { }" }
|
57
|
+
|
58
|
+
its(:warnings) { should be_empty }
|
59
|
+
its(:errors) { should be_empty }
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'class inheriting from another namespace' do
|
63
|
+
let(:code) { "class foo::bar inherits baz { }" }
|
64
|
+
|
65
|
+
its(:warnings) { should include "class inherits across namespaces on line 1" }
|
66
|
+
its(:errors) { should be_empty }
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'class with attrs in order' do
|
70
|
+
let(:code) { "class foo($bar, $baz='gronk') { }" }
|
71
|
+
|
72
|
+
its(:warnings) { should be_empty }
|
73
|
+
its(:errors) { should be_empty }
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'class with attrs out of order' do
|
77
|
+
let(:code) { "class foo($bar='baz', $gronk) { }" }
|
78
|
+
|
79
|
+
its(:warnings) { should include "optional parameter listed before required parameter on line 1" }
|
80
|
+
its(:errors) { should be_empty }
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'define with attrs in order' do
|
84
|
+
let(:code) { "define foo($bar, $baz='gronk') { }" }
|
85
|
+
|
86
|
+
its(:warnings) { should be_empty }
|
87
|
+
its(:errors) { should be_empty }
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'define with attrs out of order' do
|
91
|
+
let(:code) { "define foo($bar='baz', $gronk) { }" }
|
92
|
+
|
93
|
+
its(:warnings) { should include "optional parameter listed before required parameter on line 1" }
|
94
|
+
its(:errors) { should be_empty }
|
95
|
+
end
|
96
|
+
|
97
|
+
describe 'class with no variables declared accessing top scope' do
|
98
|
+
let(:code) { "
|
99
|
+
class foo {
|
100
|
+
$bar = $baz
|
101
|
+
}"
|
102
|
+
}
|
103
|
+
|
104
|
+
its(:warnings) { should include "top-scope variable being used without an explicit namespace on line 3" }
|
105
|
+
its(:errors) { should be_empty}
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'class with no variables declared accessing top scope explicitly' do
|
109
|
+
let(:code) { "
|
110
|
+
class foo {
|
111
|
+
$bar = $::baz
|
112
|
+
}"
|
113
|
+
}
|
114
|
+
|
115
|
+
its(:warnings) { should be_empty }
|
116
|
+
its(:errors) { should be_empty }
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'class with variables declared accessing local scope' do
|
120
|
+
let(:code) { "
|
121
|
+
class foo {
|
122
|
+
$bar = 1
|
123
|
+
$baz = $bar
|
124
|
+
}"
|
125
|
+
}
|
126
|
+
|
127
|
+
its(:warnings) { should be_empty }
|
128
|
+
its(:errors) { should be_empty }
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'class with parameters accessing local scope' do
|
132
|
+
let(:code) { "
|
133
|
+
class foo($bar) {
|
134
|
+
$baz = $bar
|
135
|
+
}"
|
136
|
+
}
|
137
|
+
|
138
|
+
its(:warnings) { should be_empty }
|
139
|
+
its(:errors) { should be_empty }
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'defined type with no variables declared accessing top scope' do
|
143
|
+
let(:code) { "
|
144
|
+
define foo() {
|
145
|
+
$bar = $fqdn
|
146
|
+
}"
|
147
|
+
}
|
148
|
+
|
149
|
+
its(:warnings) { should include "top-scope variable being used without an explicit namespace on line 3" }
|
150
|
+
its(:errors) { should be_empty }
|
151
|
+
end
|
152
|
+
|
153
|
+
describe 'defined type with no variables declared accessing top scope explicitly' do
|
154
|
+
let(:code) { "
|
155
|
+
define foo() {
|
156
|
+
$bar = $::fqdn
|
157
|
+
}"
|
158
|
+
}
|
159
|
+
|
160
|
+
its(:warnings) { should be_empty }
|
161
|
+
its(:errors) { should be_empty }
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PuppetLint::Plugins::CheckConditionals do
|
4
|
+
subject do
|
5
|
+
klass = described_class.new
|
6
|
+
klass.test(code)
|
7
|
+
klass
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'resource with a selector' do
|
11
|
+
let(:code) { "
|
12
|
+
file { 'foo':
|
13
|
+
ensure => $bar ? {
|
14
|
+
true => present,
|
15
|
+
default => absent,
|
16
|
+
},
|
17
|
+
}"
|
18
|
+
}
|
19
|
+
|
20
|
+
its(:warnings) { should include "selector inside resource block on line 3" }
|
21
|
+
its(:errors) { should be_empty }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'resource with a variable as a attr value' do
|
25
|
+
let(:code) { "
|
26
|
+
file { 'foo',
|
27
|
+
ensure => $bar,
|
28
|
+
}"
|
29
|
+
}
|
30
|
+
|
31
|
+
its(:warnings) { should be_empty }
|
32
|
+
its(:errors) { should be_empty }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'case statement with a default case' do
|
36
|
+
let(:code) { "
|
37
|
+
case $foo {
|
38
|
+
bar: { }
|
39
|
+
default: { }
|
40
|
+
}"
|
41
|
+
}
|
42
|
+
|
43
|
+
its(:warnings) { should be_empty }
|
44
|
+
its(:errors) { should be_empty }
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'case statement without a default case' do
|
48
|
+
let(:code) { "
|
49
|
+
case $foo {
|
50
|
+
bar: { }
|
51
|
+
baz: { }
|
52
|
+
}"
|
53
|
+
}
|
54
|
+
|
55
|
+
its(:warnings) { should include "case statement without a default case on line 2" }
|
56
|
+
its(:errors) { should be_empty }
|
57
|
+
end
|
58
|
+
end
|
@@ -142,4 +142,27 @@ describe PuppetLint::Plugins::CheckResources do
|
|
142
142
|
its(:warnings) { should be_empty }
|
143
143
|
its(:errors) { should be_empty }
|
144
144
|
end
|
145
|
+
|
146
|
+
describe 'file resource creating a symlink with seperate target attr' do
|
147
|
+
let(:code) { "
|
148
|
+
file { 'foo':
|
149
|
+
ensure => link,
|
150
|
+
target => '/foo/bar',
|
151
|
+
}"
|
152
|
+
}
|
153
|
+
|
154
|
+
its(:warnings) { should be_empty }
|
155
|
+
its(:errors) { should be_empty }
|
156
|
+
end
|
157
|
+
|
158
|
+
describe 'file resource creating a symlink with target specified in ensure' do
|
159
|
+
let(:code) { "
|
160
|
+
file { 'foo':
|
161
|
+
ensure => '/foo/bar',
|
162
|
+
}"
|
163
|
+
}
|
164
|
+
|
165
|
+
its(:warnings) { should include "symlink target specified in ensure attr on line 3" }
|
166
|
+
its(:errors) { should be_empty }
|
167
|
+
end
|
145
168
|
end
|
@@ -20,4 +20,11 @@ describe PuppetLint::Plugins::CheckStrings do
|
|
20
20
|
its(:warnings) { should include "double quoted string containing no variables on line 1" }
|
21
21
|
its(:errors) { should include "single quoted string containing a variable found on line 1" }
|
22
22
|
end
|
23
|
+
|
24
|
+
describe 'string containing only a variable' do
|
25
|
+
let(:code) { '"${foo}"' }
|
26
|
+
|
27
|
+
its(:warnings) { should include "string containing only a variable on line 1" }
|
28
|
+
its(:errors) { should be_empty }
|
29
|
+
end
|
23
30
|
end
|
@@ -22,6 +22,21 @@ describe PuppetLint::Plugins::CheckWhitespace do
|
|
22
22
|
its(:errors) { should be_empty }
|
23
23
|
end
|
24
24
|
|
25
|
+
describe 'selectors in the middle of a resource' do
|
26
|
+
let(:code) { "
|
27
|
+
file { 'foo':
|
28
|
+
ensure => $ensure ? {
|
29
|
+
present => directory,
|
30
|
+
absent => undef,
|
31
|
+
},
|
32
|
+
owner => 'tomcat6',
|
33
|
+
}"
|
34
|
+
}
|
35
|
+
|
36
|
+
its(:warnings) { should be_empty }
|
37
|
+
its(:errors) { should be_empty }
|
38
|
+
end
|
39
|
+
|
25
40
|
describe 'file resource with a source line > 80c' do
|
26
41
|
let(:code) { "
|
27
42
|
file {
|
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:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.7
|
10
|
+
version: 0.1.0
|
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-08-
|
18
|
+
date: 2011-08-23 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rspec
|
@@ -44,6 +44,8 @@ extra_rdoc_files: []
|
|
44
44
|
files:
|
45
45
|
- bin/puppet-lint
|
46
46
|
- lib/puppet-lint/plugin.rb
|
47
|
+
- lib/puppet-lint/plugins/check_classes.rb
|
48
|
+
- lib/puppet-lint/plugins/check_conditionals.rb
|
47
49
|
- lib/puppet-lint/plugins/check_resources.rb
|
48
50
|
- lib/puppet-lint/plugins/check_strings.rb
|
49
51
|
- lib/puppet-lint/plugins/check_whitespace.rb
|
@@ -54,6 +56,8 @@ files:
|
|
54
56
|
- puppet-lint.gemspec
|
55
57
|
- Rakefile
|
56
58
|
- README.md
|
59
|
+
- spec/puppet-lint/check_classes_spec.rb
|
60
|
+
- spec/puppet-lint/check_conditionals_spec.rb
|
57
61
|
- spec/puppet-lint/check_resources_spec.rb
|
58
62
|
- spec/puppet-lint/check_strings_spec.rb
|
59
63
|
- spec/puppet-lint/check_whitespace_spec.rb
|