puppet-ghostbuster 0.4.5 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|