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 ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in knife-audit.gemspec
4
+ gemspec
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'
@@ -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
@@ -0,0 +1,5 @@
1
+ module Knife
2
+ module Audit
3
+ VERSION = "0.0.1"
4
+ end
5
+ 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
+