knife-audit 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +4 -0
- data/README.md +55 -0
- data/Rakefile +1 -0
- data/knife-audit.gemspec +20 -0
- data/lib/chef/knife/audit.rb +136 -0
- data/lib/knife-audit/version.rb +5 -0
- metadata +73 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
knife-audit
|
2
|
+
========
|
3
|
+
A knife plugin for determining which cookbooks are in use on which nodes of your Chef server or Opscode organization.
|
4
|
+
Allows you to safely maintain a chef cookbook set by determining which cookbooks are currently in use by nodes (included in node runlists).
|
5
|
+
|
6
|
+
|
7
|
+
Installing knife-audit
|
8
|
+
-------------------
|
9
|
+
|
10
|
+
#### Script install
|
11
|
+
|
12
|
+
Copy the knife-audit script from https://github.com/jbz/knife-audit/blob/master/lib/chef/knife/audit.rb to your .chef/plugins/knife directory.
|
13
|
+
|
14
|
+
|
15
|
+
Usage
|
16
|
+
---------------
|
17
|
+
|
18
|
+
knife audit <COOKBOOK COOKBOOK ...>
|
19
|
+
|
20
|
+
If no cookbooks are specified, knife-audit will return a list of *all* cookbooks available on the currently configured Chef server or Opscode Platform organization, along with a count for each of how many nodes in the current Chef server or Opscode Platform organization explicitly reference that cookbook in their expanded runlist.
|
21
|
+
|
22
|
+
Note that this does *not* include nodes that call the cookbook via 'include' and/or 'depends' statements. The 'complete runlist' for nodes, which includes all cookbooks pulled in due to includes, is kept in Node.run_state.seen_recipes], but this is an ephemeral attribute and is only populated locally on the node during a client run. It is not saved to the Chef server, therefore knife-audit cannot 'see' it.
|
23
|
+
|
24
|
+
If one or more cookbook names are specified on the command line, knife-audit will return a list of only those cookbooks and their counts. Specifying a cookbook which is not available on the Chef server will result in an error.
|
25
|
+
|
26
|
+
The '-s' or '--show-nodelist' option will cause knife-audit to include in its output a list of all nodes which reference each cookbook.
|
27
|
+
|
28
|
+
**NOTE** knife-audit retrieves an array of *all* nodes present on your chef server for each run. As a result, it is relatively slow; if you have many ( >= 16) nodes, it will take noticeable wallclock time to complete its run. In addition. it may use lots of memory to hold those node objects.
|
29
|
+
|
30
|
+
|
31
|
+
Disclaimer
|
32
|
+
----------
|
33
|
+
|
34
|
+
This is my first knife plugin, and I haven't been using Ruby that long. Plus, I'm an op, not a software engineer. :-) If you run into problems with knife-audit, by all means let me know; you can find me via the github page or on irc at freenode #chef, usually. Thanks.
|
35
|
+
|
36
|
+
|
37
|
+
License terms
|
38
|
+
-------------
|
39
|
+
Authors:: J.B. Zimmerman
|
40
|
+
Copyright:: Copyright (c) 2009-2011 J.B. Zimmerman
|
41
|
+
License:: Apache License, Version 2.0
|
42
|
+
|
43
|
+
|
44
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
45
|
+
you may not use this file except in compliance with the License.
|
46
|
+
You may obtain a copy of the License at
|
47
|
+
|
48
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
49
|
+
|
50
|
+
Unless required by applicable law or agreed to in writing, software
|
51
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
52
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
53
|
+
See the License for the specific language governing permissions and
|
54
|
+
limitations under the License.
|
55
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/knife-audit.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "knife-audit/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "knife-audit"
|
7
|
+
s.version = Knife::Audit::VERSION
|
8
|
+
s.authors = ["Jacob Zimmerman"]
|
9
|
+
s.email = ["jzimmerman@mdsol.com"]
|
10
|
+
s.homepage = "https://github.com/jbz/knife-audit"
|
11
|
+
s.summary = %q{A Chef plugin for determining which cookbooks are in use on which nodes of your Chef server or Opscode organization.}
|
12
|
+
s.description = %q{Allows you to safely maintain a chef cookbook set by determining which cookbooks are currently in use by nodes (included in node runlists).}
|
13
|
+
|
14
|
+
s.rubyforge_project = "knife-audit"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#
|
2
|
+
## Author:: Jacob Zimmermann (<jzimmerman@mdsol.com>)
|
3
|
+
##
|
4
|
+
## Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
## you may not use this file except in compliance with the License.
|
6
|
+
## You may obtain a copy of the License at
|
7
|
+
##
|
8
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
##
|
10
|
+
## Unless required by applicable law or agreed to in writing, software
|
11
|
+
## distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
## See the License for the specific language governing permissions and
|
14
|
+
## limitations under the License.
|
15
|
+
##
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'chef/knife'
|
19
|
+
|
20
|
+
module KnifeAudit
|
21
|
+
class Audit < Chef::Knife
|
22
|
+
|
23
|
+
deps do
|
24
|
+
require 'chef/cookbook_loader'
|
25
|
+
require 'chef/environment'
|
26
|
+
require 'chef/node'
|
27
|
+
require 'chef/run_list'
|
28
|
+
require 'chef/json_compat'
|
29
|
+
require 'chef/shef/ext'
|
30
|
+
end
|
31
|
+
|
32
|
+
banner "knife audit <COOKBOOK COOKBOOK ...>"
|
33
|
+
|
34
|
+
option :show_nodelist,
|
35
|
+
:short => "-s",
|
36
|
+
:long => "--show-nodelist",
|
37
|
+
:description => "Show all nodes running each cookbook"
|
38
|
+
|
39
|
+
def run
|
40
|
+
|
41
|
+
if @name_args.empty?
|
42
|
+
display_cookbooks = {}
|
43
|
+
else
|
44
|
+
display_cookbooks = @name_args
|
45
|
+
end
|
46
|
+
|
47
|
+
self.config = Chef::Config.merge!(config)
|
48
|
+
|
49
|
+
# 1) Get a list (hash, actually, with key of 'name') of cookbooks available on the current server/org
|
50
|
+
# unless we've been given a cookbook/cookbooks on the command line
|
51
|
+
env = config[:environment]
|
52
|
+
num_versions = config[:all_versions] ? "num_versions=all" : "num_versions=1"
|
53
|
+
|
54
|
+
if display_cookbooks.empty?
|
55
|
+
api_endpoint = env ? "/environments/#{env}/cookbooks?#{num_versions}" : "/cookbooks?#{num_versions}"
|
56
|
+
cookbook_list = rest.get_rest(api_endpoint)
|
57
|
+
else
|
58
|
+
cookbook_list = {}
|
59
|
+
display_cookbooks.each do |cookbook_name|
|
60
|
+
api_endpoint = env ? "/environments/#{env}/cookbooks/#{cookbook_name}" : "cookbooks/#{cookbook_name}"
|
61
|
+
begin
|
62
|
+
cookbook_list.merge!(rest.get_rest(api_endpoint))
|
63
|
+
rescue
|
64
|
+
ui.error("Cookbook #{cookbook_name} could not be found on the server!")
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# add count => 0 to each cookbook hash
|
73
|
+
cookbook_list.each do |name,book|
|
74
|
+
book["count"] = 0
|
75
|
+
book["nodes"] = []
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# 2) Get an array of Chef::Nodes known to the current server/org
|
80
|
+
|
81
|
+
query = "*:*" # find all nodes
|
82
|
+
|
83
|
+
Shef::Extensions.extend_context_object(self)
|
84
|
+
node_list = nodes.find(query)
|
85
|
+
|
86
|
+
# 3) Iterate over each node
|
87
|
+
|
88
|
+
node_list.each do |node|
|
89
|
+
|
90
|
+
# 3a) Get node's runlist
|
91
|
+
|
92
|
+
# using expand!.recipes catches multi-level roles (roles with roles with recipes, etc.)
|
93
|
+
recipes = node.expand!.recipes.to_a
|
94
|
+
node_cookbook_list = recipes.map{ |x| x.match(/[^\:]+/)[0] }.uniq
|
95
|
+
|
96
|
+
# 3b) For each cookbook in the node runlist, if it's in our cookbook array increment its count and
|
97
|
+
# add the node to its running node array
|
98
|
+
|
99
|
+
node_cookbook_list.each do |cookbook|
|
100
|
+
if cookbook_list.has_key?(cookbook)
|
101
|
+
# Up the cookbook count
|
102
|
+
cookbook_list[cookbook]["count"] += 1
|
103
|
+
# Add the node to the cookbook's nodes array
|
104
|
+
cookbook_list[cookbook]["nodes"] << node.name
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end # step 3 iterate end
|
109
|
+
|
110
|
+
# 4) Output
|
111
|
+
|
112
|
+
format_cookbook_audit_list_for_display(cookbook_list).each do |line|
|
113
|
+
ui.msg(line)
|
114
|
+
end
|
115
|
+
|
116
|
+
end # 'run' def end
|
117
|
+
|
118
|
+
|
119
|
+
def format_cookbook_audit_list_for_display(item)
|
120
|
+
key_length = item.empty? ? 0 : item.keys.map {|name| name.size }.max + 2
|
121
|
+
if config[:show_nodelist]
|
122
|
+
item.sort.map do |name, cookbook|
|
123
|
+
"#{name.ljust(key_length)} #{cookbook["count"]} [ #{cookbook["nodes"].join(' ')} ]"
|
124
|
+
end
|
125
|
+
else
|
126
|
+
item.sort.map do |name, cookbook|
|
127
|
+
"#{name.ljust(key_length)} #{cookbook["count"]}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end # format_cokbook_audit... def end
|
132
|
+
|
133
|
+
|
134
|
+
end #class end
|
135
|
+
|
136
|
+
end #module end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: knife-audit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jacob Zimmerman
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-08-31 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Allows you to safely maintain a chef cookbook set by determining which cookbooks are currently in use by nodes (included in node runlists).
|
23
|
+
email:
|
24
|
+
- jzimmerman@mdsol.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- Gemfile
|
33
|
+
- README.md
|
34
|
+
- Rakefile
|
35
|
+
- knife-audit.gemspec
|
36
|
+
- lib/chef/knife/audit.rb
|
37
|
+
- lib/knife-audit/version.rb
|
38
|
+
has_rdoc: true
|
39
|
+
homepage: https://github.com/jbz/knife-audit
|
40
|
+
licenses: []
|
41
|
+
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
hash: 3
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project: knife-audit
|
68
|
+
rubygems_version: 1.5.2
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: A Chef plugin for determining which cookbooks are in use on which nodes of your Chef server or Opscode organization.
|
72
|
+
test_files: []
|
73
|
+
|