puppet-lint-nine-check 0.3.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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +45 -0
- data/lib/puppet-lint/plugins/concatenated_template_files.rb +59 -0
- data/lib/puppet-lint/plugins/explicit_hiera_class_param_lookup.rb +47 -0
- data/lib/puppet-lint/plugins/nine_legacy_facts.rb +85 -0
- data/lib/puppet-lint/plugins/trailing_newline.rb +41 -0
- data/lib/puppet-lint/plugins/world_writable_files.rb +49 -0
- data/spec/puppet-lint/plugins/concatenated_template_files_spec.rb +75 -0
- data/spec/puppet-lint/plugins/explicit_hiera_class_param_lookup_spec.rb +58 -0
- data/spec/puppet-lint/plugins/nine_legacy_facts_spec.rb +122 -0
- data/spec/puppet-lint/plugins/trailing_newline_spec.rb +65 -0
- data/spec/puppet-lint/plugins/world_writable_files_spec.rb +75 -0
- data/spec/spec_helper.rb +9 -0
- metadata +157 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7bd04cd6c797fc8dfcfa90947cf9fa8464765f17da05128333b5d60ef24d7bd5
|
4
|
+
data.tar.gz: ebbb400e531834f99523e76881e0b874c0d0b341323714ed20d6555bcca2c981
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a195b46f95951a594d854b5301e5093734d044f1d24fc1d4c3fd1f1c72bfa2c482e6feefd625df9cd331255c10724135aa8da5f43a610d2d06e270b263b13f9a
|
7
|
+
data.tar.gz: 632e08c48a1a0a1549c14c4b7738a7a77390c4d09d80e55a95d0b517b8c68186fe030587d1244faf613eb61cf5cf50cc319180586f9ba7c7fb97a57516d06e98
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 Nine Internet Solutions AG
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
## Overview
|
2
|
+
|
3
|
+
This linter will convert from legacy facts like `$::nine_location` or legacy hashed facts like `$facts['nine_location']` to the new structured facts like
|
4
|
+
`$facts['nine_metadata']['location']`.
|
5
|
+
|
6
|
+
## Installing
|
7
|
+
|
8
|
+
### From the command line
|
9
|
+
|
10
|
+
```shell
|
11
|
+
$ gem install puppet-lint-nine-check
|
12
|
+
```
|
13
|
+
|
14
|
+
### In a Gemfile
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'puppet-lint-nine-check', :require => false
|
18
|
+
```
|
19
|
+
|
20
|
+
#### Disabling the check
|
21
|
+
|
22
|
+
To disable this check, you can add `--no-nine` to your puppet-lint
|
23
|
+
command line.
|
24
|
+
|
25
|
+
```shell
|
26
|
+
$ puppet-lint --no-nine path/to/file.pp
|
27
|
+
```
|
28
|
+
|
29
|
+
Alternatively, if you’re calling puppet-lint via the Rake task, you should
|
30
|
+
insert the following line to your `Rakefile`.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
PuppetLint.configuration.send('disable_nine')
|
34
|
+
```
|
35
|
+
|
36
|
+
Alternatively, you can disable it directly in your puppet manifest.
|
37
|
+
|
38
|
+
```puppet
|
39
|
+
# lint:ignore:nine
|
40
|
+
$package_name = $facts['operatingsystem'] {
|
41
|
+
'CentOS' => 'httpd',
|
42
|
+
'Debian' => 'apache2',
|
43
|
+
}
|
44
|
+
# lint:endignore
|
45
|
+
```
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# https://github.com/deanwilson/puppet-lint-concatenated_template_files-check/blob/4591aca68f0c30ffb52012db7e31a94b42830f0e/lib/puppet-lint/plugins/concatenated_template_files.rb
|
2
|
+
#
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (c) 2016 Dean Wilson
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#
|
25
|
+
PuppetLint.new_check(:concatenated_template_files) do
|
26
|
+
def check
|
27
|
+
resource_indexes.each do |resource|
|
28
|
+
next unless resource[:type].value == "file"
|
29
|
+
|
30
|
+
content_tokens = resource[:param_tokens].select { |pt| pt.value == "content" }
|
31
|
+
|
32
|
+
content_tokens.each do |content_token|
|
33
|
+
value_token = content_token.next_code_token.next_code_token
|
34
|
+
|
35
|
+
next unless value_token.value == "template"
|
36
|
+
|
37
|
+
file_names = []
|
38
|
+
|
39
|
+
current_token = value_token.next_token
|
40
|
+
until current_token.type == :RPAREN
|
41
|
+
current_token = current_token.next_code_token
|
42
|
+
file_names << current_token.value if current_token.type == :SSTRING
|
43
|
+
end
|
44
|
+
|
45
|
+
next unless file_names.length > 1
|
46
|
+
|
47
|
+
warning = 'calling "template" with multiple files concatenates them into a single string'
|
48
|
+
|
49
|
+
notify :warning, {
|
50
|
+
message: warning,
|
51
|
+
line: value_token.line,
|
52
|
+
column: value_token.column,
|
53
|
+
param_token: content_token,
|
54
|
+
value_token: value_token
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# https://github.com/deanwilson/puppet-lint-explicit_hiera_class_param_lookup-check/blob/c2c23f4635017172dee1896c8e81c4d150586759/lib/puppet-lint/plugins/explicit_hiera_class_param_lookup.rb
|
2
|
+
#
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (c) 2016 Dean Wilson
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#
|
25
|
+
PuppetLint.new_check(:explicit_hiera_class_param_lookup) do
|
26
|
+
def check
|
27
|
+
class_indexes.each do |class_idx|
|
28
|
+
next unless class_idx[:param_tokens].is_a? Array
|
29
|
+
|
30
|
+
tokens = class_idx[:param_tokens].select do |t|
|
31
|
+
(t.type == :NAME or t.type == :FUNCTION_NAME) and t.value == "hiera"
|
32
|
+
end
|
33
|
+
|
34
|
+
tokens.each do |token|
|
35
|
+
next unless token.next_code_token.type == :LPAREN
|
36
|
+
|
37
|
+
hiera_key = token.next_code_token.next_code_token
|
38
|
+
|
39
|
+
notify :error, {
|
40
|
+
message: "explicit hiera() lookup of #{hiera_key.value}",
|
41
|
+
line: hiera_key.line,
|
42
|
+
column: hiera_key.column
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
PuppetLint.new_check(:nine_legacy_facts) do
|
4
|
+
def legacy_fact_tokens
|
5
|
+
tokens.select { |x| [:VARIABLE, :UNENC_VARIABLE].include?(x.type) }
|
6
|
+
end
|
7
|
+
|
8
|
+
# These facts have a one to one correlation between a legacy fact and a new
|
9
|
+
# structured fact.
|
10
|
+
def fixable_facts
|
11
|
+
{
|
12
|
+
"nine_customer" => "facts['nine_metadata']['customer']",
|
13
|
+
"nine_location" => "facts['nine_metadata']['location']"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
# A list of valid hash key token types
|
18
|
+
def hash_key_type?(type)
|
19
|
+
[
|
20
|
+
:STRING, # Double quoted string
|
21
|
+
:SSTRING, # Single quoted string
|
22
|
+
:NAME # Unquoted single word
|
23
|
+
].include?(type)
|
24
|
+
end
|
25
|
+
|
26
|
+
def check
|
27
|
+
legacy_fact_tokens.each do |token|
|
28
|
+
fact_name = ""
|
29
|
+
|
30
|
+
# Get rid of the top scope before we do our work. We don't need to
|
31
|
+
# preserve it because it won't work with the new structured facts.
|
32
|
+
if token.value.start_with?("::")
|
33
|
+
fact_name = token.value.sub(/^::/, "")
|
34
|
+
|
35
|
+
# This matches using legacy facts in a the new structured fact. For
|
36
|
+
# example this would match 'uuid' in $facts['uuid'] so it can be converted
|
37
|
+
# to facts['dmi']['product']['uuid']"
|
38
|
+
elsif token.value == "facts"
|
39
|
+
fact_name = hash_key_for(token)
|
40
|
+
|
41
|
+
elsif token.value.start_with?("facts['")
|
42
|
+
fact_name = token.value.match(/facts\['(.*)'\]/)[1]
|
43
|
+
end
|
44
|
+
|
45
|
+
unless fixable_facts.include?(fact_name)
|
46
|
+
next
|
47
|
+
end
|
48
|
+
|
49
|
+
notify :warning,
|
50
|
+
message: "legacy fact",
|
51
|
+
line: token.line,
|
52
|
+
column: token.column,
|
53
|
+
token: token,
|
54
|
+
fact_name: fact_name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# If the variable is using the $facts hash represented internally by multiple
|
59
|
+
# tokens, this helper simplifies accessing the hash key.
|
60
|
+
def hash_key_for(token)
|
61
|
+
lbrack_token = token.next_code_token
|
62
|
+
return "" unless lbrack_token && lbrack_token.type == :LBRACK
|
63
|
+
|
64
|
+
key_token = lbrack_token.next_code_token
|
65
|
+
return "" unless key_token && hash_key_type?(key_token.type)
|
66
|
+
|
67
|
+
key_token.value
|
68
|
+
end
|
69
|
+
|
70
|
+
def fix(problem)
|
71
|
+
fact_name = problem[:fact_name]
|
72
|
+
|
73
|
+
# Check if the variable is using the $facts hash represented internally by
|
74
|
+
# multiple tokens and remove the tokens for the old legacy key if so.
|
75
|
+
if problem[:token].value == "facts"
|
76
|
+
loop do
|
77
|
+
t = problem[:token].next_token
|
78
|
+
remove_token(t)
|
79
|
+
break if t.type == :RBRACK
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
problem[:token].value = fixable_facts[fact_name] if fixable_facts.include?(fact_name)
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# https://github.com/rodjek/puppet-lint-trailing_newline-check/blob/6bfdd76e53a509190f95273914a754ca21e3f2f0/spec/puppet-lint/plugins/check_trailing_newline_spec.rb
|
2
|
+
#
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (c) 2014 Tim Sharpe
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#
|
25
|
+
PuppetLint.new_check(:trailing_newline) do
|
26
|
+
def check
|
27
|
+
last_token = tokens.last
|
28
|
+
|
29
|
+
unless last_token.type == :NEWLINE
|
30
|
+
notify :warning, {
|
31
|
+
message: "expected newline at the end of the file",
|
32
|
+
line: last_token.line,
|
33
|
+
column: manifest_lines.last.length
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def fix(problem)
|
39
|
+
tokens << PuppetLint::Lexer::Token.new(:NEWLINE, "\n", 0, 0)
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# https://github.com/deanwilson/puppet-lint-world_writable_files-check/blob/a0956e31062d792740caa1dac30483110a39e375/lib/puppet-lint/plugins/world_writable_files.rb
|
2
|
+
#
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (c) 2016 Dean Wilson
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
#
|
25
|
+
PuppetLint.new_check(:world_writable_files) do
|
26
|
+
def check
|
27
|
+
resource_indexes.each do |resource|
|
28
|
+
next unless resource[:type].value == "file"
|
29
|
+
|
30
|
+
param_tokens = resource[:param_tokens].select { |pt| pt.value == "mode" }
|
31
|
+
|
32
|
+
param_tokens.each do |param_token|
|
33
|
+
# get the file modes value
|
34
|
+
value_token = param_token.next_code_token.next_code_token
|
35
|
+
|
36
|
+
# we only work with octal for now - also stops file { mode => undef }
|
37
|
+
break if !/^\d+$/.match?(value_token.value)
|
38
|
+
break if /\d+[^2367]$/.match?(value_token.value)
|
39
|
+
|
40
|
+
notify :warning, {
|
41
|
+
message: "files should not be created with world writable permissions",
|
42
|
+
line: value_token.line,
|
43
|
+
column: value_token.column,
|
44
|
+
token: value_token
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "concatenated_template_files" do
|
4
|
+
let(:msg) { 'calling "template" with multiple files concatenates them into a single string' }
|
5
|
+
|
6
|
+
context "when the manifest has no file resources" do
|
7
|
+
let(:code) do
|
8
|
+
<<-TEST_CLASS
|
9
|
+
class no_file_resource {
|
10
|
+
host { 'syslog':
|
11
|
+
ip => '10.10.10.10',
|
12
|
+
}
|
13
|
+
}
|
14
|
+
TEST_CLASS
|
15
|
+
end
|
16
|
+
|
17
|
+
it "does not detect any problems" do
|
18
|
+
expect(problems.size).to eq(0)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with file resource but no template call" do
|
23
|
+
context "when the template has a relative module path" do
|
24
|
+
let(:code) do
|
25
|
+
<<-TEST_CLASS
|
26
|
+
class template_tester {
|
27
|
+
file { '/tmp/template':
|
28
|
+
content => 'A static string',
|
29
|
+
}
|
30
|
+
}
|
31
|
+
TEST_CLASS
|
32
|
+
end
|
33
|
+
|
34
|
+
it "detects no problems" do
|
35
|
+
expect(problems.size).to eq(0)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when template function is passed one filename" do
|
41
|
+
let(:code) do
|
42
|
+
<<-TEST_CLASS
|
43
|
+
class single_templated_file {
|
44
|
+
file { '/tmp/templated':
|
45
|
+
content => template('mymodule/single_file.erb'),
|
46
|
+
}
|
47
|
+
}
|
48
|
+
TEST_CLASS
|
49
|
+
end
|
50
|
+
|
51
|
+
it "does not detect any problems" do
|
52
|
+
expect(problems.size).to eq(0)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when template function is passed multiple filenames" do
|
57
|
+
let(:code) do
|
58
|
+
<<-TEST_CLASS
|
59
|
+
class multi_templated_file {
|
60
|
+
file { '/tmp/templated':
|
61
|
+
content => template('mymodule/first_file.erb', 'mymodule/second_file.erb'),
|
62
|
+
}
|
63
|
+
}
|
64
|
+
TEST_CLASS
|
65
|
+
end
|
66
|
+
|
67
|
+
it "detects a single problem" do
|
68
|
+
expect(problems.size).to eq(1)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "creates a warning" do
|
72
|
+
expect(problems).to contain_warning(msg).on_line(3).in_column(24)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "explicit_hiera_class_param_lookup" do
|
4
|
+
context "when class has no explicit hiera() lookups" do
|
5
|
+
let(:code) do
|
6
|
+
<<-TEST_CLASS
|
7
|
+
class no_explicit_lookups(
|
8
|
+
$my_content = undef
|
9
|
+
) {
|
10
|
+
file { '/tmp/foo':
|
11
|
+
content => 'bar',
|
12
|
+
}
|
13
|
+
}
|
14
|
+
TEST_CLASS
|
15
|
+
end
|
16
|
+
|
17
|
+
it "does not detect any problems" do
|
18
|
+
expect(problems.size).to eq(0)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when class has an explicit hiera() lookup" do
|
23
|
+
let(:msg) { "explicit hiera() lookup of my::nested::key" }
|
24
|
+
|
25
|
+
let(:code) do
|
26
|
+
<<-TEST_CLASS
|
27
|
+
class no_explicit_lookups(
|
28
|
+
$my_content = hiera('my::nested::key', 'baz')
|
29
|
+
) {
|
30
|
+
file { '/tmp/foo':
|
31
|
+
content => $my_content,
|
32
|
+
}
|
33
|
+
}
|
34
|
+
TEST_CLASS
|
35
|
+
end
|
36
|
+
|
37
|
+
it "detects a single problem" do
|
38
|
+
expect(problems.size).to eq(1)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "creates an error" do
|
42
|
+
expect(problems).to contain_error(msg).on_line(2).in_column(31)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
### Reported issues
|
47
|
+
context "with an empty class with inherit and no explicit hiera() lookups" do
|
48
|
+
let(:code) do
|
49
|
+
<<-TEST_CLASS
|
50
|
+
class ig::base::freebsd inherits ig::base { }
|
51
|
+
TEST_CLASS
|
52
|
+
end
|
53
|
+
|
54
|
+
it "does not detect any problems" do
|
55
|
+
expect(problems.size).to eq(0)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe "nine_legacy_facts" do
|
6
|
+
let(:msg) { "legacy fact" }
|
7
|
+
context "with fix disabled" do
|
8
|
+
context "fact variable using modern $facts['nine_metadata']['location'] hash" do
|
9
|
+
let(:code) { "$facts['nine_metadata']['location']" }
|
10
|
+
|
11
|
+
it "should not detect any problems" do
|
12
|
+
expect(problems.size).to eq(0)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "fact variable using legacy $nine_location" do
|
17
|
+
let(:code) { "$nine_location" }
|
18
|
+
|
19
|
+
it "should not detect any problems" do
|
20
|
+
expect(problems.size).to eq(0)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "fact variable using legacy $facts['nine_location']" do
|
25
|
+
let(:code) { "$facts['nine_location']" }
|
26
|
+
|
27
|
+
it "should only detect a single problem" do
|
28
|
+
expect(problems.size).to eq(1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "fact variable using legacy $::nine_location" do
|
33
|
+
let(:code) { "$::nine_location" }
|
34
|
+
|
35
|
+
it "should only detect a single problem" do
|
36
|
+
expect(problems.size).to eq(1)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "fact variable using legacy $::nine_location" do
|
41
|
+
let(:code) { "$::nine_location" }
|
42
|
+
|
43
|
+
it "should only detect a single problem" do
|
44
|
+
expect(problems.size).to eq(1)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "fact variable using legacy $facts['nine_location']" do
|
49
|
+
let(:code) { "$facts['nine_location']" }
|
50
|
+
|
51
|
+
it "should only detect a single problem" do
|
52
|
+
expect(problems.size).to eq(1)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "fact variable using legacy facts hash variable in interpolation" do
|
57
|
+
let(:code) { %("${facts['nine_location']}") }
|
58
|
+
|
59
|
+
it "detects a single problem" do
|
60
|
+
expect(problems.size).to eq(1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with fix enabled" do
|
66
|
+
before do
|
67
|
+
PuppetLint.configuration.fix = true
|
68
|
+
end
|
69
|
+
|
70
|
+
after do
|
71
|
+
PuppetLint.configuration.fix = false
|
72
|
+
end
|
73
|
+
|
74
|
+
context "fact variable using modern $facts['nine_metadata']['location'] hash" do
|
75
|
+
let(:code) { "$facts['nine_metadata']['location']" }
|
76
|
+
|
77
|
+
it "should not detect any problems" do
|
78
|
+
expect(problems.size).to eq(0)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "fact variable using legacy $nine_location" do
|
83
|
+
let(:code) { "$nine_location" }
|
84
|
+
|
85
|
+
it "should not detect any problems" do
|
86
|
+
expect(problems.size).to eq(0)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "fact variable using legacy $facts['nine_location']" do
|
91
|
+
let(:code) { "$facts['nine_location']" }
|
92
|
+
|
93
|
+
it "should only detect a single problem" do
|
94
|
+
expect(problems.size).to eq(1)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should fix the problem" do
|
98
|
+
expect(problems).to contain_fixed(msg).on_line(1).in_column(1)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should use the facts hash" do
|
102
|
+
expect(manifest).to eq("$facts['nine_metadata']['location']")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "fact variable using legacy $::nine_location" do
|
107
|
+
let(:code) { "$::nine_location" }
|
108
|
+
|
109
|
+
it "should only detect a single problem" do
|
110
|
+
expect(problems.size).to eq(1)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should fix the problem" do
|
114
|
+
expect(problems).to contain_fixed(msg).on_line(1).in_column(1)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should use the facts hash" do
|
118
|
+
expect(manifest).to eq("$facts['nine_metadata']['location']")
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "trailing_newline" do
|
4
|
+
let(:msg) { "expected newline at the end of the file" }
|
5
|
+
|
6
|
+
context "with fix disabled" do
|
7
|
+
context "code not ending with a newline" do
|
8
|
+
let(:code) { "'test'" }
|
9
|
+
|
10
|
+
it "should detect a single problem" do
|
11
|
+
expect(problems.size).to eq(1)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should create a warning" do
|
15
|
+
expect(problems).to contain_warning(msg).on_line(1).in_column(6)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "code ending with a newline" do
|
20
|
+
let(:code) { "'test'\n" }
|
21
|
+
|
22
|
+
it "should not detect any problems" do
|
23
|
+
expect(problems.size).to eq(0)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with fix enabled" do
|
29
|
+
before do
|
30
|
+
PuppetLint.configuration.fix = true
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
PuppetLint.configuration.fix = false
|
35
|
+
end
|
36
|
+
|
37
|
+
context "code not ending in a newline" do
|
38
|
+
let(:code) { "'test'" }
|
39
|
+
|
40
|
+
it "should only detect a single problem" do
|
41
|
+
expect(problems.size).to eq(1)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should fix the problem" do
|
45
|
+
expect(problems).to contain_fixed(msg).on_line(1).in_column(6)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should add a newline to the end of the manifest" do
|
49
|
+
expect(manifest).to eq("'test'\n")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "code ending in a newline" do
|
54
|
+
let(:code) { "'test'\n" }
|
55
|
+
|
56
|
+
it "should not detect any problems" do
|
57
|
+
expect(problems.size).to eq(0)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should not modify the manifest" do
|
61
|
+
expect(manifest).to eq(code)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "world_writable_files" do
|
4
|
+
context "when the manifest has no file resources" do
|
5
|
+
let(:code) do
|
6
|
+
<<-TEST_CLASS
|
7
|
+
class no_file_resource {
|
8
|
+
host { 'syslog':
|
9
|
+
ip => '10.10.10.10',
|
10
|
+
}
|
11
|
+
}
|
12
|
+
TEST_CLASS
|
13
|
+
end
|
14
|
+
|
15
|
+
it "does not detect any problems" do
|
16
|
+
expect(problems.size).to eq(0)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when file resource has a mode of 640" do
|
21
|
+
let(:code) do
|
22
|
+
<<-TEST_CLASS
|
23
|
+
class locked_down_file {
|
24
|
+
file { '/tmp/locked_down':
|
25
|
+
ensure => 'file',
|
26
|
+
mode => '0640',
|
27
|
+
}
|
28
|
+
}
|
29
|
+
TEST_CLASS
|
30
|
+
end
|
31
|
+
|
32
|
+
it "does not detect any problems" do
|
33
|
+
expect(problems.size).to eq(0)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when file has a mode of undef" do
|
38
|
+
let(:code) do
|
39
|
+
<<-TEST_CLASS
|
40
|
+
class undef_file_mode {
|
41
|
+
file { '/tmp/undef_file_mode':
|
42
|
+
ensure => 'file',
|
43
|
+
mode => undef,
|
44
|
+
}
|
45
|
+
}
|
46
|
+
TEST_CLASS
|
47
|
+
end
|
48
|
+
|
49
|
+
it "does not detect any problems" do
|
50
|
+
expect(problems.size).to eq(0)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when file has a world writable octal mode of 666" do
|
55
|
+
let(:msg) { "files should not be created with world writable permissions" }
|
56
|
+
let(:code) do
|
57
|
+
<<-TEST_CLASS
|
58
|
+
class locked_down_file {
|
59
|
+
file { '/tmp/open_octal':
|
60
|
+
ensure => 'file',
|
61
|
+
mode => '0666',
|
62
|
+
}
|
63
|
+
}
|
64
|
+
TEST_CLASS
|
65
|
+
end
|
66
|
+
|
67
|
+
it "detects a problem" do
|
68
|
+
expect(problems.size).to eq(1)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "creates a warning" do
|
72
|
+
expect(problems).to contain_warning(msg).on_line(4).in_column(23)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: puppet-lint-nine-check
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nine Internet Solutions AG
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-10-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: puppet-lint
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-its
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-json_expectations
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-collection_matchers
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: |2
|
112
|
+
A pupet-lint to check you are not using Nine legacy facts like `$::nine_location`
|
113
|
+
or `$facts['nine_location']`. You should use the new structured facts like
|
114
|
+
`$facts['nine_metadata']['location']` instead.
|
115
|
+
email:
|
116
|
+
- support@nine.ch
|
117
|
+
executables: []
|
118
|
+
extensions: []
|
119
|
+
extra_rdoc_files: []
|
120
|
+
files:
|
121
|
+
- LICENSE
|
122
|
+
- README.md
|
123
|
+
- lib/puppet-lint/plugins/concatenated_template_files.rb
|
124
|
+
- lib/puppet-lint/plugins/explicit_hiera_class_param_lookup.rb
|
125
|
+
- lib/puppet-lint/plugins/nine_legacy_facts.rb
|
126
|
+
- lib/puppet-lint/plugins/trailing_newline.rb
|
127
|
+
- lib/puppet-lint/plugins/world_writable_files.rb
|
128
|
+
- spec/puppet-lint/plugins/concatenated_template_files_spec.rb
|
129
|
+
- spec/puppet-lint/plugins/explicit_hiera_class_param_lookup_spec.rb
|
130
|
+
- spec/puppet-lint/plugins/nine_legacy_facts_spec.rb
|
131
|
+
- spec/puppet-lint/plugins/trailing_newline_spec.rb
|
132
|
+
- spec/puppet-lint/plugins/world_writable_files_spec.rb
|
133
|
+
- spec/spec_helper.rb
|
134
|
+
homepage: https://gitlab.nine.ch/managed-services/puppet/tools/puppet-lint-nine-check
|
135
|
+
licenses:
|
136
|
+
- MIT
|
137
|
+
metadata: {}
|
138
|
+
post_install_message:
|
139
|
+
rdoc_options: []
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 2.7.0
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
requirements: []
|
153
|
+
rubygems_version: 3.4.10
|
154
|
+
signing_key:
|
155
|
+
specification_version: 4
|
156
|
+
summary: A puppet-lint plugin for different checks used at Nine.
|
157
|
+
test_files: []
|