puppet-lint 0.0.7 → 0.1.0
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 +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
|