puppet-ghostbuster 0.4.5 → 0.5.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 +4 -4
- data/.travis.yml +3 -0
- data/CHANGELOG.md +7 -0
- data/README.md +26 -66
- data/Rakefile +2 -0
- data/lib/puppet-ghostbuster/puppetdb.rb +28 -0
- data/lib/puppet-ghostbuster/version.rb +1 -1
- data/lib/puppet-lint/plugins/check_ghostbuster_classes.rb +22 -0
- data/lib/puppet-lint/plugins/check_ghostbuster_defines.rb +23 -0
- data/lib/puppet-lint/plugins/check_ghostbuster_files.rb +61 -0
- data/lib/puppet-lint/plugins/check_ghostbuster_templates.rb +41 -0
- data/puppet-ghostbuster.gemspec +4 -1
- data/spec/puppet-lint/plugins/ghostbuster_classes_spec.rb +44 -0
- data/spec/puppet-lint/plugins/ghostbuster_defines_spec.rb +55 -0
- data/spec/puppet-lint/plugins/ghostbuster_files_spec.rb +110 -0
- data/spec/puppet-lint/plugins/ghostbuster_templates_spec.rb +41 -0
- data/spec/spec_helper.rb +3 -0
- metadata +59 -13
- data/bin/puppet-ghostbuster +0 -7
- data/lib/puppet-ghostbuster/bin.rb +0 -31
- data/lib/puppet-ghostbuster/configuration.rb +0 -96
- data/lib/puppet-ghostbuster/optparser.rb +0 -68
- data/lib/puppet-ghostbuster.rb +0 -207
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54bed6f908a3bb9aaae26087248857c8390028b7
|
4
|
+
data.tar.gz: 3904dae59b8117dfd6233afaf73688ed232c2e6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b6a6044ce239fd2aef83b436994b5bff3bb85f5214c3e5537317fa853414c090b517d7e4eea2853df38acab5d5ca1fa6a881366f8817f8f9ff20dd4a9a2b394
|
7
|
+
data.tar.gz: 68abfdd84fd16af1b06a32c06b6173b90b9b50bf4024d26eb4aca4026d27cf5b75b17ed5bb1ca26b588a5896466678f3067a303eb94620f038dce084f68e4887
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [0.5.0](https://rubygems.org/gems/puppet-ghostbuster/versions/0.5.0) (2016-05-10)
|
4
|
+
[Full Changelog](https://github.com/camptocamp/puppet-ghostbuster/compare/0.4.5...0.5.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- Major Reimplementation. Delivered as puppet-lint plugins.
|
9
|
+
|
3
10
|
## [0.4.5](https://rubygems.org/gems/puppet-ghostbuster/versions/0.4.5) (2016-05-04)
|
4
11
|
[Full Changelog](https://github.com/camptocamp/puppet-ghostbuster/compare/0.4.4...0.4.5)
|
5
12
|
|
data/README.md
CHANGED
@@ -17,82 +17,42 @@ This gems only support PuppetDB APi v4 (PuppetDB 3+)
|
|
17
17
|
Usage
|
18
18
|
-----
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
sudo bundle exec puppet-ghostbuster
|
20
|
+
```shell
|
21
|
+
$ find . -type f -exec puppet-lint --only-checks ghostbuster_classes,ghostbuster_defines,ghostbuster_files,ghostbuster_templates {} \+
|
23
22
|
```
|
24
23
|
|
25
|
-
|
24
|
+
Environment variables
|
25
|
+
---------------------
|
26
26
|
|
27
|
-
|
27
|
+
### PUPPETDB_URL
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
$ puppet-ghostbuster -s https://puppetdburl:8081 | jsonpp
|
33
|
-
[
|
34
|
-
{
|
35
|
-
"title": "[GhostBuster] Class Foo::Install seems unused",
|
36
|
-
"body": "./modules/foo/manifests/install.pp"
|
37
|
-
},
|
38
|
-
{
|
39
|
-
"title": "[GhostBuster] Class Foo::Service seems unused",
|
40
|
-
"body": "./modules/foo/manifests/service.pp"
|
41
|
-
},
|
42
|
-
{
|
43
|
-
"title": "[GhostBuster] Class Foo seems unused",
|
44
|
-
"body": "./modules/foo/manifests/init.pp"
|
45
|
-
},
|
46
|
-
{
|
47
|
-
"title": "[GhostBuster] Define Bar:Baz seems unused",
|
48
|
-
"body": "./modules/bar/manifests/baz.pp"
|
49
|
-
},
|
50
|
-
{
|
51
|
-
"title": "[GhostBuster] Template modulename/foo.erb seems unused",
|
52
|
-
"body": "./modules/modulename/templates/foo.erb"
|
53
|
-
},
|
54
|
-
{
|
55
|
-
"title": "[GhostBuster] Template modulename/bar.erb seems unused",
|
56
|
-
"body": "./modules/modulename/templates/bar.erb"
|
57
|
-
},
|
58
|
-
{
|
59
|
-
"title": "[GhostBuster] Template modulename/baz.erb seems unused",
|
60
|
-
"body": "./modules/modulename/templates/baz.erb"
|
61
|
-
},
|
62
|
-
{
|
63
|
-
"title": "[GhostBuster] File foo/bar.txt seems unused",
|
64
|
-
"body": "./modules/foo/files/bar.txt"
|
65
|
-
},
|
66
|
-
{
|
67
|
-
"title": "[GhostBuster] File foo/baz.txt seems unused",
|
68
|
-
"body": "./modules/foo/files/baz.txt"
|
69
|
-
}
|
70
|
-
]
|
71
|
-
```
|
29
|
+
The url or the PuppetDB. Defaults to `http://puppetdb:8080`
|
30
|
+
|
31
|
+
### PUPPETDB_CACERT_FILE
|
72
32
|
|
73
|
-
|
74
|
-
------------
|
75
|
-
To find unused classes:
|
76
|
-
1. It search puppet code recursively starting (by default) from current directory.
|
77
|
-
2. For each .pp file found, it extract the class name
|
78
|
-
3. Query puppetdb (using cache) to find matching class in catalogs
|
79
|
-
4. Display the number of class, followed by the class name.
|
33
|
+
Your site’s CA certificate
|
80
34
|
|
81
|
-
|
35
|
+
### PUPPETDB_CERT_FILE
|
82
36
|
|
83
|
-
|
37
|
+
An SSL certificate signed by your site’s Puppet CA
|
84
38
|
|
85
|
-
|
86
|
-
------------------
|
39
|
+
### PUPPETDB_KEY_FILE
|
87
40
|
|
88
|
-
|
89
|
-
will be excluded from the dead code detection. Useful for upstream modules where
|
90
|
-
you are are not using everything.
|
41
|
+
The private key for that certificate
|
91
42
|
|
92
|
-
Example
|
43
|
+
Example output
|
44
|
+
--------------
|
93
45
|
|
46
|
+
TODO
|
94
47
|
```
|
95
|
-
|
96
|
-
modules/
|
97
|
-
modules/
|
48
|
+
$ find . -type f -exec puppet-lint --only-checks ghostbuster_classes,ghostbuster_defines,ghostbuster_files,ghostbuster_templates {} \+
|
49
|
+
./modules/foo/manifests/install.pp - WARNING: Class Foo::Install seems unused on line 1
|
50
|
+
./modules/foo/manifests/service.pp - WARNING: Class Foo::Service seems unused on line 1
|
51
|
+
./modules/foo/manifests/init.pp - WARNING: Class Foo seems unused on line 1
|
52
|
+
./modules/bar/manifests/baz.pp - WARNING: Define Bar::Baz seems unused on line 1
|
53
|
+
./modules/modulename/templates/foo.erb - WARNING: Template modulename/foo.erb seems unused on line 1
|
54
|
+
./modules/modulename/templates/bar.erb - WARNING: Template modulename/bar.erb seems unused on line 1
|
55
|
+
./modules/modulename/templates/baz.erb - WARNING: Template modulename/baz.erb seems unused on line 1
|
56
|
+
./modules/foo/files/bar.txt - WARNING: File foo/bar.txt seems unused on line 1
|
57
|
+
./modules/foo/files/baz.txt - WARNING: File foo/baz.txt seems unused on line 1
|
98
58
|
```
|
data/Rakefile
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'puppetdb'
|
2
|
+
|
3
|
+
class PuppetGhostbuster
|
4
|
+
class PuppetDB
|
5
|
+
def self.client
|
6
|
+
@@client ||= ::PuppetDB::Client.new({
|
7
|
+
:server => "#{ENV['PUPPETDB_URL'] || 'http://puppetdb:8080'}/pdb/query",
|
8
|
+
:pem => {
|
9
|
+
'key' => ENV['PUPPETDB_KEY_FILE'],
|
10
|
+
'cert' => ENV['PUPPETDB_CERT_FILE'],
|
11
|
+
'ca_file' => ENV['PUPPETDB_CACERT_FILE'],
|
12
|
+
}
|
13
|
+
}, 4)
|
14
|
+
end
|
15
|
+
|
16
|
+
def client
|
17
|
+
self.class.client
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.classes
|
21
|
+
@@classes ||= client.request('resources', [:'=', 'type', 'Class']).data.map { |r| r['title'] }.uniq
|
22
|
+
end
|
23
|
+
|
24
|
+
def classes
|
25
|
+
self.class.classes
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'puppet-ghostbuster/puppetdb'
|
2
|
+
|
3
|
+
PuppetLint.new_check(:ghostbuster_classes) do
|
4
|
+
def check
|
5
|
+
return if path.match(%r{^\./(:?[^/]+/){2}?manifests/.+$}).nil?
|
6
|
+
|
7
|
+
puppetdb = PuppetGhostbuster::PuppetDB.new
|
8
|
+
|
9
|
+
class_indexes.each do |class_idx|
|
10
|
+
title_token = class_idx[:name_token]
|
11
|
+
title = title_token.value.split('::').map(&:capitalize).join('::')
|
12
|
+
|
13
|
+
return if puppetdb.classes.include? title
|
14
|
+
|
15
|
+
notify :warning, {
|
16
|
+
:message => "Class #{title} seems unused",
|
17
|
+
:line => title_token.line,
|
18
|
+
:column => title_token.column,
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'puppet-ghostbuster/puppetdb'
|
2
|
+
|
3
|
+
PuppetLint.new_check(:ghostbuster_defines) do
|
4
|
+
def check
|
5
|
+
return if path.match(%r{^\./(:?[^/]+/){2}?manifests/.+$}).nil?
|
6
|
+
|
7
|
+
puppetdb = PuppetGhostbuster::PuppetDB.new
|
8
|
+
|
9
|
+
defined_type_indexes.each do |define_idx|
|
10
|
+
title_token = define_idx[:name_token]
|
11
|
+
type = title_token.value.split('::').map(&:capitalize).join('::')
|
12
|
+
|
13
|
+
return if puppetdb.client.request('resources', [:'=', 'type', type]).data.size > 0
|
14
|
+
|
15
|
+
notify :warning, {
|
16
|
+
:message => "Define #{type} seems unused",
|
17
|
+
:line => title_token.line,
|
18
|
+
:column => title_token.column,
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'puppet-ghostbuster/puppetdb'
|
2
|
+
|
3
|
+
class PuppetLint::Checks
|
4
|
+
def load_data(path, content)
|
5
|
+
lexer = PuppetLint::Lexer.new
|
6
|
+
PuppetLint::Data.path = path
|
7
|
+
begin
|
8
|
+
PuppetLint::Data.manifest_lines = content.split("\n", -1)
|
9
|
+
PuppetLint::Data.tokens = lexer.tokenise(content)
|
10
|
+
PuppetLint::Data.parse_control_comments
|
11
|
+
rescue
|
12
|
+
PuppetLint::Data.tokens = []
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
PuppetLint.new_check(:ghostbuster_files) do
|
18
|
+
def manifests
|
19
|
+
Dir.glob('./**/manifests/**/*.pp')
|
20
|
+
end
|
21
|
+
|
22
|
+
def check
|
23
|
+
m = path.match(%r{.*/([^/]+)/files/(.+)$})
|
24
|
+
return if m.nil?
|
25
|
+
|
26
|
+
puppetdb = PuppetGhostbuster::PuppetDB.new
|
27
|
+
|
28
|
+
module_name, file_name = m.captures
|
29
|
+
return if puppetdb.client.request('resources', [:'=', ['parameter', 'source'], "puppet:///modules/#{module_name}/#{file_name}"],).data.size > 0
|
30
|
+
|
31
|
+
dir_name = File.dirname(file_name)
|
32
|
+
while dir_name != '.' do
|
33
|
+
return if puppetdb.client.request(
|
34
|
+
'resources',
|
35
|
+
[:'and',
|
36
|
+
[:'or',
|
37
|
+
[:'=', ['parameter', 'source'], "puppet:///modules/#{module_name}/#{dir_name}"],
|
38
|
+
[:'=', ['parameter', 'source'], "puppet:///modules/#{module_name}/#{dir_name}/"],
|
39
|
+
],
|
40
|
+
[:'=', ['parameter', 'recurse'], true],
|
41
|
+
],
|
42
|
+
).data.size > 0
|
43
|
+
dir_name = File.dirname(dir_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
manifests.each do |manifest|
|
47
|
+
return if File.readlines(manifest).grep(%r{["']#{module_name}/#{file_name}["']}).size > 0
|
48
|
+
if match = manifest.match(%r{.*/([^/]+)/manifests/.+$})
|
49
|
+
if match.captures[0] == module_name
|
50
|
+
return if File.readlines(manifest).grep(/["']\$\{module_name\}\/#{file_name}["']/).size > 0
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
notify :warning, {
|
56
|
+
:message => "File #{module_name}/#{file_name} seems unused",
|
57
|
+
:line => 1,
|
58
|
+
:column => 1,
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class PuppetLint::Checks
|
2
|
+
def load_data(path, content)
|
3
|
+
lexer = PuppetLint::Lexer.new
|
4
|
+
PuppetLint::Data.path = path
|
5
|
+
begin
|
6
|
+
PuppetLint::Data.manifest_lines = content.split("\n", -1)
|
7
|
+
PuppetLint::Data.tokens = lexer.tokenise(content)
|
8
|
+
PuppetLint::Data.parse_control_comments
|
9
|
+
rescue
|
10
|
+
PuppetLint::Data.tokens = []
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
PuppetLint.new_check(:ghostbuster_templates) do
|
16
|
+
def manifests
|
17
|
+
Dir.glob('./**/manifests/**/*.pp')
|
18
|
+
end
|
19
|
+
|
20
|
+
def check
|
21
|
+
m = path.match(%r{.*/([^/]+)/templates/(.+)$})
|
22
|
+
return if m.nil?
|
23
|
+
|
24
|
+
module_name, template_name = m.captures
|
25
|
+
|
26
|
+
manifests.each do |manifest|
|
27
|
+
return if File.readlines(manifest).grep(%r{["']#{module_name}/#{template_name}["']}).size > 0
|
28
|
+
if match = manifest.match(%r{.*/([^/]+)/manifests/.+$})
|
29
|
+
if match.captures[0] == module_name
|
30
|
+
return if File.readlines(manifest).grep(/["']\$\{module_name\}\/#{template_name}["']/).size > 0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
notify :warning, {
|
36
|
+
:message => "Template #{module_name}/#{template_name} seems unused",
|
37
|
+
:line => 1,
|
38
|
+
:column => 1,
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
data/puppet-ghostbuster.gemspec
CHANGED
@@ -17,9 +17,12 @@ Gem::Specification.new do |s|
|
|
17
17
|
|
18
18
|
s.add_development_dependency 'coveralls'
|
19
19
|
s.add_development_dependency 'rake'
|
20
|
-
s.add_development_dependency 'rspec'
|
20
|
+
s.add_development_dependency 'rspec', '~> 3.0'
|
21
|
+
s.add_development_dependency 'rspec-its', '~> 1.0'
|
22
|
+
s.add_development_dependency 'rspec-collection_matchers', '~> 1.0'
|
21
23
|
s.add_development_dependency 'github_changelog_generator'
|
22
24
|
s.add_runtime_dependency 'json'
|
23
25
|
s.add_runtime_dependency 'puppet'
|
26
|
+
s.add_dependency 'puppet-lint', '~> 1.0'
|
24
27
|
s.add_runtime_dependency 'puppetdb-ruby'
|
25
28
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class PuppetDBRequest
|
4
|
+
def initialize(data)
|
5
|
+
@data = data
|
6
|
+
end
|
7
|
+
|
8
|
+
def data
|
9
|
+
@data
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'ghostbuster_classes' do
|
14
|
+
#let(:path) { "./manifests/site.pp" }
|
15
|
+
let(:path) { "./modules/foo/manifests/init.pp" }
|
16
|
+
|
17
|
+
context 'with fix disabled' do
|
18
|
+
|
19
|
+
before :each do
|
20
|
+
expect(PuppetGhostbuster::PuppetDB).to \
|
21
|
+
receive(:classes).and_return(['Foo'])
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when class is used' do
|
25
|
+
let(:code) { "class foo {}" }
|
26
|
+
|
27
|
+
it 'should not detect any problem' do
|
28
|
+
expect(problems).to have(0).problems
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when class is not used' do
|
33
|
+
let(:code) { "class bar {}" }
|
34
|
+
|
35
|
+
it 'should detect one problem' do
|
36
|
+
expect(problems).to have(1).problems
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should create a warning' do
|
40
|
+
expect(problems).to contain_warning('Class Bar seems unused')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class PuppetDBRequest
|
4
|
+
def initialize(data)
|
5
|
+
@data = data
|
6
|
+
end
|
7
|
+
|
8
|
+
def data
|
9
|
+
@data
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'ghostbuster_defines' do
|
14
|
+
let(:path) { "./modules/foo/manifests/init.pp" }
|
15
|
+
|
16
|
+
context 'with fix disabled' do
|
17
|
+
|
18
|
+
context 'when define is used' do
|
19
|
+
let(:code) { "define foo {}" }
|
20
|
+
|
21
|
+
before :each do
|
22
|
+
expect_any_instance_of(PuppetDB::Client).to \
|
23
|
+
receive(:request).with('resources', [:'=', 'type', 'Foo'])
|
24
|
+
.and_return(PuppetDBRequest.new([
|
25
|
+
{
|
26
|
+
'type' => 'Foo',
|
27
|
+
'title' => 'bar',
|
28
|
+
},
|
29
|
+
]))
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should not detect any problem' do
|
33
|
+
expect(problems).to have(0).problems
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when define is not used' do
|
38
|
+
let(:code) { "define foo {}" }
|
39
|
+
|
40
|
+
before :each do
|
41
|
+
expect_any_instance_of(PuppetDB::Client).to \
|
42
|
+
receive(:request).with('resources', [:'=', 'type', 'Foo'])
|
43
|
+
.and_return(PuppetDBRequest.new([]))
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should detect one problem' do
|
47
|
+
expect(problems).to have(1).problems
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should create a warning' do
|
51
|
+
expect(problems).to contain_warning('Define Foo seems unused')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'ghostbuster_files' do
|
4
|
+
let(:path) { "./modules/foo/files/bar/baz" }
|
5
|
+
let(:code) { "" }
|
6
|
+
|
7
|
+
context 'with fix disabled' do
|
8
|
+
|
9
|
+
context 'when file usage is found in puppetdb' do
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
expect_any_instance_of(PuppetDB::Client).to\
|
13
|
+
receive(:request).with(
|
14
|
+
'resources',
|
15
|
+
[:'=', ['parameter', 'source'], "puppet:///modules/foo/bar/baz"],
|
16
|
+
)
|
17
|
+
.and_return(PuppetDBRequest.new([{}]))
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should not detect any problem' do
|
21
|
+
expect(problems).to have(0).problems
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when file usage is not found in puppetdb' do
|
26
|
+
|
27
|
+
before :each do
|
28
|
+
expect_any_instance_of(PuppetDB::Client).to\
|
29
|
+
receive(:request).with(
|
30
|
+
'resources',
|
31
|
+
[:'=', ['parameter', 'source'], "puppet:///modules/foo/bar/baz"],
|
32
|
+
)
|
33
|
+
.and_return(PuppetDBRequest.new([]))
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when parent directory with recurse => true usage is found in puppetdb' do
|
37
|
+
before :each do
|
38
|
+
expect_any_instance_of(PuppetDB::Client).to \
|
39
|
+
receive(:request).with(
|
40
|
+
'resources',
|
41
|
+
[:'and',
|
42
|
+
[:'or',
|
43
|
+
[:'=', ['parameter', 'source'], "puppet:///modules/foo/bar"],
|
44
|
+
[:'=', ['parameter', 'source'], "puppet:///modules/foo/bar/"],
|
45
|
+
],
|
46
|
+
[:'=', ['parameter', 'recurse'], true],
|
47
|
+
],
|
48
|
+
)
|
49
|
+
.and_return(PuppetDBRequest.new([
|
50
|
+
{
|
51
|
+
},
|
52
|
+
]))
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should not detect any problem' do
|
56
|
+
expect(problems).to have(0).problems
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when parent directory usage is not found in puppetdb' do
|
61
|
+
before :each do
|
62
|
+
expect_any_instance_of(PuppetDB::Client).to \
|
63
|
+
receive(:request).with(
|
64
|
+
'resources',
|
65
|
+
[:'and',
|
66
|
+
[:'or',
|
67
|
+
[:'=', ['parameter', 'source'], "puppet:///modules/foo/bar"],
|
68
|
+
[:'=', ['parameter', 'source'], "puppet:///modules/foo/bar/"],
|
69
|
+
],
|
70
|
+
[:'=', ['parameter', 'recurse'], true],
|
71
|
+
],
|
72
|
+
)
|
73
|
+
.and_return(PuppetDBRequest.new([]))
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when file usage is found in manifests' do
|
77
|
+
|
78
|
+
before :each do
|
79
|
+
expect(Dir).to receive(:glob){["./modules/foo/manifests/bar.pp" ]}
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when using full module name syntax' do
|
83
|
+
it 'should not detect any problem' do
|
84
|
+
expect(File).to receive(:readlines).with("./modules/foo/manifests/bar.pp").and_return(["file{'foo':", " content => file('foo/bar/baz'),", " }"])
|
85
|
+
expect(problems).to have(0).problems
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'when using $module_name syntax' do
|
90
|
+
it 'should not detect any problem' do
|
91
|
+
expect(File).to receive(:readlines).with("./modules/foo/manifests/bar.pp").and_return(["file{'foo':", " content => file('bar/foo'),", " }"])
|
92
|
+
expect(File).to receive(:readlines).with("./modules/foo/manifests/bar.pp").and_return(["file{'foo':", ' content => file("${module_name}/bar/baz"),', " }"])
|
93
|
+
expect(problems).to have(0).problems
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'when file usage is not found in manifests' do
|
99
|
+
it 'should detect one problem' do
|
100
|
+
expect(problems).to have(1).problems
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should create a warning' do
|
104
|
+
expect(problems).to contain_warning("File foo/bar/baz seems unused")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'ghostbuster_templates' do
|
4
|
+
let(:path) { "./modules/foo/templates/bar" }
|
5
|
+
let(:code) { "" }
|
6
|
+
|
7
|
+
context 'with fix disabled' do
|
8
|
+
|
9
|
+
context 'when template usage is found in manifests' do
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
expect(Dir).to receive(:glob){["./modules/foo/manifests/bar.pp" ]}
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when using full module name syntax' do
|
16
|
+
it 'should not detect any problem' do
|
17
|
+
expect(File).to receive(:readlines).with("./modules/foo/manifests/bar.pp").and_return(["file{'foo':", " content => template('foo/bar'),", " }"])
|
18
|
+
expect(problems).to have(0).problems
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when using $module_name syntax' do
|
23
|
+
it 'should not detect any problem' do
|
24
|
+
expect(File).to receive(:readlines).with("./modules/foo/manifests/bar.pp").and_return(["file{'foo':", " content => template('bar/foo'),", " }"])
|
25
|
+
expect(File).to receive(:readlines).with("./modules/foo/manifests/bar.pp").and_return(["file{'foo':", ' content => template("${module_name}/bar"),', " }"])
|
26
|
+
expect(problems).to have(0).problems
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when template usage is not found in manifests' do
|
32
|
+
it 'should detect one problem' do
|
33
|
+
expect(problems).to have(1).problems
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should create a warning' do
|
37
|
+
expect(problems).to contain_warning("Template foo/bar seems unused")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppet-ghostbuster
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Camptocamp
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coveralls
|
@@ -42,16 +42,44 @@ dependencies:
|
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
47
|
+
version: '3.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-its
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.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: '1.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: github_changelog_generator
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +122,20 @@ dependencies:
|
|
94
122
|
- - ">="
|
95
123
|
- !ruby/object:Gem::Version
|
96
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: puppet-lint
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.0'
|
97
139
|
- !ruby/object:Gem::Dependency
|
98
140
|
name: puppetdb-ruby
|
99
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,8 +152,7 @@ dependencies:
|
|
110
152
|
version: '0'
|
111
153
|
description: Try and find dead code in Puppet receipts
|
112
154
|
email:
|
113
|
-
executables:
|
114
|
-
- puppet-ghostbuster
|
155
|
+
executables: []
|
115
156
|
extensions: []
|
116
157
|
extra_rdoc_files: []
|
117
158
|
files:
|
@@ -122,13 +163,18 @@ files:
|
|
122
163
|
- LICENSE
|
123
164
|
- README.md
|
124
165
|
- Rakefile
|
125
|
-
-
|
126
|
-
- lib/puppet-ghostbuster.rb
|
127
|
-
- lib/puppet-ghostbuster/bin.rb
|
128
|
-
- lib/puppet-ghostbuster/configuration.rb
|
129
|
-
- lib/puppet-ghostbuster/optparser.rb
|
166
|
+
- lib/puppet-ghostbuster/puppetdb.rb
|
130
167
|
- lib/puppet-ghostbuster/version.rb
|
168
|
+
- lib/puppet-lint/plugins/check_ghostbuster_classes.rb
|
169
|
+
- lib/puppet-lint/plugins/check_ghostbuster_defines.rb
|
170
|
+
- lib/puppet-lint/plugins/check_ghostbuster_files.rb
|
171
|
+
- lib/puppet-lint/plugins/check_ghostbuster_templates.rb
|
131
172
|
- puppet-ghostbuster.gemspec
|
173
|
+
- spec/puppet-lint/plugins/ghostbuster_classes_spec.rb
|
174
|
+
- spec/puppet-lint/plugins/ghostbuster_defines_spec.rb
|
175
|
+
- spec/puppet-lint/plugins/ghostbuster_files_spec.rb
|
176
|
+
- spec/puppet-lint/plugins/ghostbuster_templates_spec.rb
|
177
|
+
- spec/spec_helper.rb
|
132
178
|
homepage: http://github.com/camptocamp/puppet-ghostbuster
|
133
179
|
licenses:
|
134
180
|
- Apache-2.0
|
data/bin/puppet-ghostbuster
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'puppet-ghostbuster/optparser'
|
2
|
-
class PuppetGhostbuster::Bin
|
3
|
-
def initialize(args)
|
4
|
-
@args = args
|
5
|
-
end
|
6
|
-
|
7
|
-
def run
|
8
|
-
opts = PuppetGhostbuster::OptParser.build
|
9
|
-
|
10
|
-
begin
|
11
|
-
opts.parse!(@args)
|
12
|
-
rescue OptionParser::InvalidOption
|
13
|
-
puts "puppet-ghostbuster: #{$!.message}"
|
14
|
-
puts "puppet-ghostbuster: try 'puppet-ghostbuster --help' for more information"
|
15
|
-
return 1
|
16
|
-
end
|
17
|
-
|
18
|
-
if PuppetGhostbuster.configuration.display_version
|
19
|
-
puts "puppet-ghostbuster #{PuppetGhostbuster::VERSION}"
|
20
|
-
return 0
|
21
|
-
end
|
22
|
-
|
23
|
-
if @args[0].nil?
|
24
|
-
PuppetGhostbuster.new().run
|
25
|
-
else
|
26
|
-
PuppetGhostbuster.new(@args[0]).run
|
27
|
-
end
|
28
|
-
|
29
|
-
exit 0
|
30
|
-
end
|
31
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
class PuppetGhostbuster
|
2
|
-
# Public: A singleton class to store the running configuration of
|
3
|
-
# puppet-ghostbuster.
|
4
|
-
class Configuration
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
Puppet.initialize_settings
|
8
|
-
end
|
9
|
-
|
10
|
-
# Public: Catch situations where options are being set for the first time
|
11
|
-
# and create the necessary methods to get & set the option in the future.
|
12
|
-
#
|
13
|
-
# args - An Array of values to set the option to.
|
14
|
-
# method - The String name of the option.
|
15
|
-
# block - Unused.
|
16
|
-
#
|
17
|
-
# Returns nothing.
|
18
|
-
#
|
19
|
-
# Signature
|
20
|
-
#
|
21
|
-
# <option>=(value)
|
22
|
-
def method_missing(method, *args, &block)
|
23
|
-
if method.to_s =~ /^(\w+)=$/
|
24
|
-
option = $1
|
25
|
-
add_option(option.to_s) if settings[option].nil?
|
26
|
-
settings[option] = args[0]
|
27
|
-
else
|
28
|
-
nil
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# Internal: Add options to the PuppetGhostbuster::Configuration object from inside
|
33
|
-
# the class.
|
34
|
-
#
|
35
|
-
# option - The String name of the option.
|
36
|
-
#
|
37
|
-
# Returns nothing.
|
38
|
-
#
|
39
|
-
# Signature
|
40
|
-
#
|
41
|
-
# <option>
|
42
|
-
# <option>=(value)
|
43
|
-
def add_option(option)
|
44
|
-
self.class.add_option(option)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Public: Add an option to the PuppetGhostbuster::Configuration object from
|
48
|
-
# outside the class.
|
49
|
-
#
|
50
|
-
# option - The String name of the option.
|
51
|
-
#
|
52
|
-
# Returns nothing.
|
53
|
-
#
|
54
|
-
# Signature
|
55
|
-
#
|
56
|
-
# <option>
|
57
|
-
# <option>=(value)
|
58
|
-
def self.add_option(option)
|
59
|
-
# Public: Set the value of the named option.
|
60
|
-
#
|
61
|
-
# value - The value to set the option to.
|
62
|
-
#
|
63
|
-
# Returns nothing.
|
64
|
-
define_method("#{option}=") do |value|
|
65
|
-
settings[option] = value
|
66
|
-
end
|
67
|
-
|
68
|
-
# Public: Get the value of the named option.
|
69
|
-
#
|
70
|
-
# Returns the value of the option.
|
71
|
-
define_method(option) do
|
72
|
-
settings[option]
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# Internal: Access the internal storage for settings.
|
77
|
-
#
|
78
|
-
# Returns a Hash containing all the settings.
|
79
|
-
def settings
|
80
|
-
@settings ||= {}
|
81
|
-
end
|
82
|
-
|
83
|
-
# Public: Clear the PuppetGhostbuster::Configuration storage and set some sane
|
84
|
-
# default values.
|
85
|
-
#
|
86
|
-
# Returns nothing.
|
87
|
-
def defaults
|
88
|
-
settings.clear
|
89
|
-
self.loglevel = Logger::INFO
|
90
|
-
self.puppetdbserverurl = "https://#{Puppet[:server]}:8081"
|
91
|
-
self.hostprivkey = Puppet[:hostprivkey]
|
92
|
-
self.hostcert = Puppet[:hostcert]
|
93
|
-
self.localcacert = Puppet[:localcacert]
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'optparse'
|
2
|
-
|
3
|
-
# Public: Contains the puppet-ghostbuster option parser so that it can be used easily
|
4
|
-
# in multiple places.
|
5
|
-
class PuppetGhostbuster::OptParser
|
6
|
-
HELP_TEXT = <<-EOF
|
7
|
-
puppet-ghostbuster
|
8
|
-
|
9
|
-
Basic Command Line Usage:
|
10
|
-
puppet-ghostbuster [OPTIONS] [PATH]
|
11
|
-
|
12
|
-
PATH Path to the Root directory of puppet code. Current dir by default.
|
13
|
-
|
14
|
-
Option:
|
15
|
-
EOF
|
16
|
-
|
17
|
-
# Public: Initialise a new puppet-ghostbuster OptionParser.
|
18
|
-
#
|
19
|
-
# Returns an OptionParser object.
|
20
|
-
def self.build
|
21
|
-
OptionParser.new do |opts|
|
22
|
-
opts.banner = HELP_TEXT
|
23
|
-
|
24
|
-
opts.on('--version', 'Display the current version.') do
|
25
|
-
PuppetGhostbuster.configuration.display_version = true
|
26
|
-
end
|
27
|
-
|
28
|
-
opts.on('-c', '--config FILE', 'Load puppet-ghostbuster options from file.') do |file|
|
29
|
-
opts.load(file)
|
30
|
-
end
|
31
|
-
|
32
|
-
opts.on('--log-level LEVEL', [:debug, :info, :warn, :error],
|
33
|
-
'The level of verbosity (debug, info, warn or error)') do |loglevel|
|
34
|
-
PuppetGhostbuster.configuration.loglevel=Logger::DEBUG if loglevel==:debug
|
35
|
-
PuppetGhostbuster.configuration.loglevel=Logger::INFO if loglevel==:info
|
36
|
-
PuppetGhostbuster.configuration.loglevel=Logger::WARN if loglevel==:warn
|
37
|
-
PuppetGhostbuster.configuration.loglevel=Logger::ERROR if loglevel==:error
|
38
|
-
end
|
39
|
-
|
40
|
-
opts.on('-s', '--puppetdburl SERVER',
|
41
|
-
'puppet db server url to connect to.',
|
42
|
-
'Defaults to the puppet server found in puppet configuration') do |s|
|
43
|
-
PuppetGhostbuster.configuration.puppetdbserverurl = s
|
44
|
-
end
|
45
|
-
|
46
|
-
opts.on('--key FILE', 'Load private key from the given file.') do |key|
|
47
|
-
PuppetGhostbuster.configuration.hostprivkey = key
|
48
|
-
end
|
49
|
-
|
50
|
-
opts.on('--cert FILE', 'Load cert from the given file.') do |cert|
|
51
|
-
PuppetGhostbuster.configuration.hostcert = cert
|
52
|
-
end
|
53
|
-
|
54
|
-
opts.on('--ca FILE', 'Load local ca cert from the given file.') do |ca|
|
55
|
-
PuppetGhostbuster.configuration.localcacert = ca
|
56
|
-
end
|
57
|
-
|
58
|
-
opts.load('/etc/puppet-ghostbuster.rc')
|
59
|
-
begin
|
60
|
-
opts.load(File.expand_path('~/.puppet-ghostbuster.rc')) if ENV['HOME']
|
61
|
-
rescue Errno::EACCES
|
62
|
-
# silently skip loading this file if HOME is set to a directory that
|
63
|
-
# the user doesn't have read access to.
|
64
|
-
end
|
65
|
-
opts.load('.puppet-ghostbuster.rc')
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
data/lib/puppet-ghostbuster.rb
DELETED
@@ -1,207 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'puppet'
|
3
|
-
require 'puppetdb'
|
4
|
-
require 'optparse'
|
5
|
-
|
6
|
-
require 'puppet-ghostbuster/version'
|
7
|
-
require 'puppet-ghostbuster/bin'
|
8
|
-
require 'puppet-ghostbuster/configuration'
|
9
|
-
|
10
|
-
class PuppetGhostbuster
|
11
|
-
|
12
|
-
attr_accessor :path
|
13
|
-
@@issues = []
|
14
|
-
|
15
|
-
def exclude(filelist)
|
16
|
-
ignorefile = "#{path}/.ghostbusterignore"
|
17
|
-
if File.exist?(ignorefile) then
|
18
|
-
ignorelist = File.readlines(ignorefile).each {|l| l.chomp!}
|
19
|
-
ignorelist.each do |ignorerule|
|
20
|
-
filelist.reject! { |item| item =~ /^#{path}\/#{ignorerule}/ }
|
21
|
-
end
|
22
|
-
end
|
23
|
-
filelist
|
24
|
-
end
|
25
|
-
|
26
|
-
def manifests
|
27
|
-
exclude Dir["#{path}/**/manifests/**/*.pp"]
|
28
|
-
end
|
29
|
-
|
30
|
-
def templates
|
31
|
-
exclude Dir["#{path}/**/templates/**/*"]
|
32
|
-
end
|
33
|
-
|
34
|
-
def files
|
35
|
-
exclude Dir["#{path}/**/files/**/*"]
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.configuration
|
39
|
-
@configuration ||= PuppetGhostbuster::Configuration.new
|
40
|
-
end
|
41
|
-
|
42
|
-
def configuration
|
43
|
-
self.class.configuration
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.puppetdbserverfilename
|
47
|
-
return configuration.puppetdbserverurl.gsub(/[:\/]/,'_')
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.cache
|
51
|
-
"/var/tmp/puppet-ghostbuster.#{puppetdbserverfilename}.cache"
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.update_cache(value)
|
55
|
-
File.open(cache, 'w') do |f|
|
56
|
-
f.write(value)
|
57
|
-
end
|
58
|
-
value
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.get_cache
|
62
|
-
if File.exists?(cache)
|
63
|
-
JSON.parse(File.read(cache))
|
64
|
-
else
|
65
|
-
false
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.client
|
70
|
-
@@logger.debug "Connecting to puppet DB #{configuration.puppetdbserverurl}"
|
71
|
-
PuppetDB::Client.new({
|
72
|
-
:server => "#{configuration.puppetdbserverurl}/pdb/query",
|
73
|
-
:pem => {
|
74
|
-
'key' => configuration.hostprivkey,
|
75
|
-
'cert' => configuration.hostcert,
|
76
|
-
'ca_file' => configuration.localcacert,
|
77
|
-
}
|
78
|
-
}, 4)
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.used_classes
|
82
|
-
return get_cache || update_cache(
|
83
|
-
client.request(
|
84
|
-
'resources',
|
85
|
-
[:'=', 'type', 'Class'],
|
86
|
-
).data.map { |resource|
|
87
|
-
resource['title']
|
88
|
-
}
|
89
|
-
)
|
90
|
-
end
|
91
|
-
|
92
|
-
def find_unused_classes
|
93
|
-
@@logger.info 'Now trying to find unused classes'
|
94
|
-
manifests.each do |file|
|
95
|
-
@@logger.debug " file #{file}."
|
96
|
-
if File.symlink?(file)
|
97
|
-
@@logger.warn " Skipping symlink #{file}"
|
98
|
-
next
|
99
|
-
end
|
100
|
-
if c = File.readlines(file).grep(/^class\s+([^\s\(\{]+)/){$1}[0]
|
101
|
-
class_name = c.split('::').map(&:capitalize).join('::')
|
102
|
-
count = self.class.used_classes.select { |klass| klass == class_name }.size
|
103
|
-
@@issues << { :title => "[GhostBuster] Class #{class_name} seems unused", :body => file } if count == 0
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def find_unused_defines
|
109
|
-
@@logger.info 'Now trying to find unused defines'
|
110
|
-
manifests.each do |file|
|
111
|
-
if File.symlink?(file)
|
112
|
-
@@logger.warn " Skipping symlink #{file}"
|
113
|
-
next
|
114
|
-
end
|
115
|
-
if d = File.readlines(file).grep(/^define\s+([^\s\(\{]+)/){$1}[0]
|
116
|
-
define_name = d.split('::').map(&:capitalize).join('::')
|
117
|
-
count = self.class.client.request('resources', [:'=', 'type', define_name]).data.size
|
118
|
-
@@issues << { :title => "[GhostBuster] Define #{define_name} seems unused", :body => file } if count == 0
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def find_unused_templates
|
124
|
-
@@logger.info 'Now trying to find unused templates'
|
125
|
-
templates.each do |template|
|
126
|
-
next unless File.file?(template)
|
127
|
-
module_name, template_name = template.match(/.*\/([^\/]+)\/templates\/(.+)$/).captures
|
128
|
-
count = 0
|
129
|
-
manifests.each do |manifest|
|
130
|
-
if File.symlink?(manifest)
|
131
|
-
@@logger.warn " Skipping symlink #{manifest}"
|
132
|
-
next
|
133
|
-
end
|
134
|
-
if match = manifest.match(/.*\/([^\/]+)\/manifests\/.+$/)
|
135
|
-
manifest_module_name = match.captures[0]
|
136
|
-
count += File.readlines(manifest).grep(/["']\$\{module_name\}\/#{template_name}["']/).size if manifest_module_name == module_name
|
137
|
-
end
|
138
|
-
count += File.readlines(manifest).grep(/["']#{module_name}\/#{template_name}["']/).size
|
139
|
-
end
|
140
|
-
@@issues << { :title => "[GhostBuster] Template #{module_name}/#{template_name} seems unused", :body => template } if count == 0
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def find_unused_files
|
145
|
-
@@logger.info 'Now trying to find unused files'
|
146
|
-
files.each do |file|
|
147
|
-
next unless File.file?(file)
|
148
|
-
module_name, file_name = file.match(/.*\/([^\/]+)\/files\/(.+)$/).captures
|
149
|
-
found = false
|
150
|
-
|
151
|
-
found = true if self.class.client.request('resources', [:'=', ['parameter', 'source'], "puppet:///modules/#{module_name}/#{file_name}"],).data.size > 0
|
152
|
-
|
153
|
-
dir_name = File.dirname(file_name)
|
154
|
-
while dir_name != '.' do
|
155
|
-
found = true if self.class.client.request(
|
156
|
-
'resources',
|
157
|
-
[:'and',
|
158
|
-
[:'or',
|
159
|
-
[:'=', ['parameter', 'source'], "puppet:///modules/#{module_name}/#{dir_name}"],
|
160
|
-
[:'=', ['parameter', 'source'], "puppet:///modules/#{module_name}/#{dir_name}/"],
|
161
|
-
],
|
162
|
-
[:'=', ['parameter', 'recurse'], true],
|
163
|
-
],
|
164
|
-
).data.size > 0
|
165
|
-
dir_name = File.dirname(dir_name)
|
166
|
-
end
|
167
|
-
|
168
|
-
manifests.each do |manifest|
|
169
|
-
if File.symlink?(manifest)
|
170
|
-
@@logger.warn " Skipping symlink #{manifest}"
|
171
|
-
next
|
172
|
-
end
|
173
|
-
|
174
|
-
if match = manifest.match(/.*\/([^\/]+)\/manifests\/.+$/)
|
175
|
-
manifest_module_name = match.captures[0]
|
176
|
-
if manifest_module_name == module_name
|
177
|
-
found = true if File.readlines(manifest).grep(/["']\$\{module_name\}\/#{file_name}["']/).size > 0
|
178
|
-
break if found
|
179
|
-
end
|
180
|
-
end
|
181
|
-
found = true if File.readlines(manifest).grep(/#{module_name}\/#{file_name}/).size > 0
|
182
|
-
break if found
|
183
|
-
end
|
184
|
-
|
185
|
-
@@issues << { :title => "[GhostBuster] File #{module_name}/#{file_name} seems unused", :body => file } unless found
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
def initialize(path = '.')
|
190
|
-
self.path = path
|
191
|
-
@@logger = Logger.new(STDERR).tap do |log|
|
192
|
-
log.progname = 'PuppetGhostbuster'
|
193
|
-
log.level=PuppetGhostbuster.configuration.loglevel
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def run
|
198
|
-
find_unused_classes
|
199
|
-
find_unused_defines
|
200
|
-
find_unused_templates
|
201
|
-
find_unused_files
|
202
|
-
puts @@issues.to_json
|
203
|
-
end
|
204
|
-
|
205
|
-
end
|
206
|
-
|
207
|
-
PuppetGhostbuster.configuration.defaults
|