health_inspector 0.0.3 → 0.0.4

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/HISTORY.md CHANGED
@@ -1,11 +1,15 @@
1
- ## 0.0.3 ( 2012-03-27)
1
+ ## 0.0.4 ( 2012-04-09 )
2
+
3
+ * Add checks for data bags, data bag items, environments, and roles
4
+
5
+ ## 0.0.3 ( 2012-03-27 )
2
6
 
3
7
  * Read cookbook paths from knife config file instead of hardcoding /cookbooks
4
8
 
5
- ## 0.0.2 ( 2012-03-27)
9
+ ## 0.0.2 ( 2012-03-27 )
6
10
 
7
11
  * Make sure we iterate over actual cookbooks in cookbooks folder
8
12
 
9
- ## 0.0.1 ( 2012-03-27)
13
+ ## 0.0.1 ( 2012-03-27 )
10
14
 
11
15
  * Initial release
@@ -6,11 +6,12 @@ require "health_inspector/check"
6
6
  require "health_inspector/inspector"
7
7
  require "health_inspector/checklists/base"
8
8
  require "health_inspector/checklists/cookbooks"
9
+ require "health_inspector/checklists/data_bags"
10
+ require "health_inspector/checklists/data_bag_items"
11
+ require "health_inspector/checklists/environments"
12
+ require "health_inspector/checklists/roles"
9
13
  require "health_inspector/cli"
10
14
  require "json"
11
15
 
12
- # TODO:
13
- # * Check if cookbook version is same as on server
14
- # * Check if remote origin not in sync with local
15
16
  module HealthInspector
16
17
  end
@@ -5,6 +5,66 @@ module HealthInspector
5
5
  class Base
6
6
  include Color
7
7
 
8
+ class << self
9
+ attr_reader :checks, :title
10
+
11
+ def add_check(name, &block)
12
+ @checks ||= []
13
+ @checks << block
14
+ end
15
+
16
+ def title(val=nil)
17
+ val.nil? ? @title : @title = val
18
+ end
19
+ end
20
+
21
+ def self.run(context)
22
+ new(context).run
23
+ end
24
+
25
+ def initialize(context)
26
+ @context = context
27
+ end
28
+
29
+ def run
30
+ banner "Inspecting #{self.class.title}"
31
+
32
+ items.each do |item|
33
+ failures = checks.map { |check| run_check(check, item) }.compact
34
+
35
+ if failures.empty?
36
+ print_success(item.name)
37
+ else
38
+ print_failures(item.name, failures)
39
+ end
40
+ end
41
+ end
42
+
43
+ def checks
44
+ self.class.checks
45
+ end
46
+
47
+ class CheckContext
48
+ include Check
49
+ attr_accessor :item, :context
50
+
51
+ def initialize(check, item, context)
52
+ @item = item
53
+ @context = context
54
+ @check = check
55
+ end
56
+
57
+ def call
58
+ instance_eval(&@check)
59
+ end
60
+ end
61
+
62
+ def run_check(check, item)
63
+ check_context = CheckContext.new(check, item, @context)
64
+ check_context.call
65
+ return check_context.failure
66
+ end
67
+
8
68
  def banner(message)
9
69
  puts
10
70
  puts message
@@ -1,84 +1,52 @@
1
1
  module HealthInspector
2
2
  module Checklists
3
3
 
4
- class Cookbook < Struct.new(:name, :path, :server_version, :local_version)
5
- def git_repo?
6
- self.path && File.exist?("#{self.path}/.git")
7
- end
8
- end
9
-
10
- class CookbookCheck < Struct.new(:cookbook)
11
- include Check
12
- end
4
+ class Cookbooks < Base
13
5
 
14
- class CheckLocalCopyExists < CookbookCheck
15
- def check
16
- failure( "exists on chef server but not locally" ) if cookbook.path.nil?
6
+ add_check "local copy exists" do
7
+ failure( "exists on chef server but not locally" ) if item.path.nil?
17
8
  end
18
- end
19
9
 
20
- class CheckServerCopyExists < CookbookCheck
21
- def check
22
- failure( "exists locally but not on chef server" ) if cookbook.server_version.nil?
10
+ add_check "server copy exists" do
11
+ failure( "exists locally but not on chef server" ) if item.server_version.nil?
23
12
  end
24
- end
25
13
 
26
- class CheckVersionsAreTheSame < CookbookCheck
27
- def check
28
- if cookbook.local_version && cookbook.server_version &&
29
- cookbook.local_version != cookbook.server_version
30
- failure "chef server has #{cookbook.server_version} but local version is #{cookbook.local_version}"
14
+ add_check "versions" do
15
+ if item.local_version && item.server_version &&
16
+ item.local_version != item.server_version
17
+ failure "chef server has #{item.server_version} but local version is #{item.local_version}"
31
18
  end
32
19
  end
33
- end
34
20
 
35
- class CheckUncommittedChanges < CookbookCheck
36
- def check
37
- if cookbook.git_repo?
38
- result = `cd #{cookbook.path} && git status -s`
21
+ add_check "uncommitted changes" do
22
+ if item.git_repo?
23
+ result = `cd #{item.path} && git status -s`
39
24
 
40
25
  unless result.empty?
41
26
  failure "Uncommitted changes:\n#{result.chomp}"
42
27
  end
43
28
  end
44
29
  end
45
- end
46
30
 
47
- class CheckCommitsNotPushedToRemote < CookbookCheck
48
- def check
49
- if cookbook.git_repo?
50
- result = `cd #{cookbook.path} && git status`
31
+ add_check "commits not pushed to remote" do
32
+ if item.git_repo?
33
+ result = `cd #{item.path} && git status`
51
34
 
52
35
  if result =~ /Your branch is ahead of (.+)/
53
36
  failure "ahead of #{$1}"
54
37
  end
55
38
  end
56
39
  end
57
- end
58
-
59
- class Cookbooks < Base
60
- def self.run(context)
61
- new(context).run
62
- end
63
-
64
- def initialize(context)
65
- @context = context
66
- end
67
40
 
68
- def run
69
- banner "Inspecting cookbooks"
70
-
71
- cookbooks.each do |cookbook|
72
- failures = cookbook_checks.map { |c| c.new(cookbook).run_check }.compact
73
- if failures.empty?
74
- print_success(cookbook.name)
75
- else
76
- print_failures(cookbook.name, failures)
77
- end
41
+ class Cookbook < Struct.new(:name, :path, :server_version, :local_version)
42
+ def git_repo?
43
+ self.path && File.exist?("#{self.path}/.git")
78
44
  end
79
45
  end
80
46
 
81
- def cookbooks
47
+ title "cookbooks"
48
+
49
+ def items
82
50
  server_cookbooks = cookbooks_on_server
83
51
  local_cookbooks = cookbooks_in_repo
84
52
  all_cookbook_names = ( server_cookbooks.keys + local_cookbooks.keys ).uniq.sort
@@ -120,16 +88,6 @@ module HealthInspector
120
88
  path = @context.cookbook_path.find { |f| File.exist?("#{f}/#{name}") }
121
89
  path ? File.join(path, name) : nil
122
90
  end
123
-
124
- def cookbook_checks
125
- [
126
- CheckLocalCopyExists,
127
- CheckServerCopyExists,
128
- CheckVersionsAreTheSame,
129
- CheckUncommittedChanges,
130
- CheckCommitsNotPushedToRemote
131
- ]
132
- end
133
91
  end
134
92
  end
135
93
  end
@@ -0,0 +1,71 @@
1
+ require "chef/data_bag"
2
+
3
+ module HealthInspector
4
+ module Checklists
5
+ class DataBagItems < Base
6
+ title "data bag items"
7
+
8
+ add_check "local copy exists" do
9
+ failure "exists on server but not locally" unless item.local
10
+ end
11
+
12
+ add_check "server copy exists" do
13
+ failure "exists locally but not on server" unless item.server
14
+ end
15
+
16
+ add_check "items are the same" do
17
+ if item.server && item.local
18
+ failure "#{item.server}\n is not equal to\n #{item.local}" unless item.server == item.local
19
+ end
20
+ end
21
+
22
+ DataBagItem = Struct.new(:name, :server, :local)
23
+
24
+ def items
25
+ server_data_bag_items = data_bag_items_on_server
26
+ local_data_bag_items = data_bag_items_in_repo
27
+ all_data_bag_item_names = ( server_data_bag_items + local_data_bag_items ).uniq.sort
28
+
29
+ all_data_bag_item_names.map do |name|
30
+ DataBagItem.new.tap do |data_bag_item|
31
+ data_bag_item.name = name
32
+ data_bag_item.server = load_item_from_server(name)
33
+ data_bag_item.local = load_item_from_local(name)
34
+ end
35
+ end
36
+ end
37
+
38
+ def data_bag_items_on_server
39
+ @data_bags_on_server ||= Chef::DataBag.list.keys.map do |bag_name|
40
+ [ bag_name, Chef::DataBag.load(bag_name) ]
41
+ end.inject([]) do |arr, (bag_name, data_bag)|
42
+ arr += data_bag.keys.map { |item_name| "#{bag_name}/#{item_name}"}
43
+ end
44
+ end
45
+
46
+ def data_bag_items_in_repo
47
+ entries = nil
48
+
49
+ Dir.chdir("#{@context.repo_path}/data_bags") do
50
+ entries = Dir["**/*.json"].map { |entry| entry.gsub('.json', '') }
51
+ end
52
+
53
+ return entries
54
+ end
55
+
56
+ def load_item_from_server(name)
57
+ bag_name, item_name = name.split("/")
58
+ Chef::DataBagItem.load(bag_name, item_name).raw_data
59
+ rescue
60
+ nil
61
+ end
62
+
63
+ def load_item_from_local(name)
64
+ JSON.parse( File.read("#{@context.repo_path}/data_bags/#{name}.json") )
65
+ rescue IOError
66
+ nil
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,44 @@
1
+ require "chef/data_bag"
2
+
3
+ module HealthInspector
4
+ module Checklists
5
+ class DataBags < Base
6
+ title "data bags"
7
+
8
+ add_check "local copy exists" do
9
+ failure "exists on server but not locally" unless item.exists_locally
10
+ end
11
+
12
+ add_check "server copy exists" do
13
+ failure "exists locally but not on server" unless item.exists_on_server
14
+ end
15
+
16
+ DataBag = Struct.new(:name, :exists_on_server, :exists_locally)
17
+
18
+ def items
19
+ server_data_bags = data_bags_on_server
20
+ local_data_bags = data_bags_in_repo
21
+ all_data_bag_names = ( server_data_bags + local_data_bags ).uniq.sort
22
+
23
+ all_data_bag_names.map do |name|
24
+ DataBag.new.tap do |data_bag|
25
+ data_bag.name = name
26
+ data_bag.exists_on_server = data_bags_on_server.include?(name)
27
+ data_bag.exists_locally = data_bags_in_repo.include?(name)
28
+ end
29
+ end
30
+ end
31
+
32
+ def data_bags_on_server
33
+ @data_bags_on_server ||= Chef::DataBag.list.keys
34
+ end
35
+
36
+ def data_bags_in_repo
37
+ @data_bags_in_repo ||= Dir["#{@context.repo_path}/data_bags/*"].entries.
38
+ select { |e| File.directory?(e) }.
39
+ map { |e| File.basename(e) }
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,65 @@
1
+ require "chef/environment"
2
+
3
+ module HealthInspector
4
+ module Checklists
5
+ class Environments < Base
6
+ title "environments"
7
+
8
+ add_check "local copy exists" do
9
+ failure "exists on server but not locally" unless item.local
10
+ end
11
+
12
+ add_check "server copy exists" do
13
+ failure "exists locally but not on server" unless item.server
14
+ end
15
+
16
+ add_check "items are the same" do
17
+ if item.server && item.local
18
+ failure "#{item.server}\n is not equal to\n #{item.local}" unless item.server == item.local
19
+ end
20
+ end
21
+
22
+ Environment = Struct.new(:name, :server, :local)
23
+
24
+ def items
25
+ server_items = items_on_server
26
+ local_items = items_in_repo
27
+ all_item_names = ( server_items + local_items ).uniq.sort
28
+
29
+ all_item_names.map do |name|
30
+ Environment.new.tap do |item|
31
+ item.name = name
32
+ item.server = load_item_from_server(name)
33
+ item.local = load_item_from_local(name)
34
+ end
35
+ end
36
+ end
37
+
38
+ def items_on_server
39
+ @items_on_server ||= Chef::Environment.list.keys
40
+ end
41
+
42
+ def items_in_repo
43
+ Dir.chdir("#{@context.repo_path}/environments") do
44
+ Dir["*.rb"].map { |e| e.gsub('.rb', '') }
45
+ end
46
+ end
47
+
48
+ def load_item_from_server(name)
49
+ env = Chef::Environment.load(name)
50
+ env.to_hash
51
+ rescue
52
+ nil
53
+ end
54
+
55
+ def load_item_from_local(name)
56
+ env = Chef::Environment.new
57
+ env.from_file( "#{@context.repo_path}/environments/#{name}.rb" )
58
+ env.to_hash
59
+ rescue IOError
60
+ nil
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,65 @@
1
+ require "chef/role"
2
+
3
+ module HealthInspector
4
+ module Checklists
5
+ class Roles < Base
6
+ title "roles"
7
+
8
+ add_check "local copy exists" do
9
+ failure "exists on server but not locally" unless item.local
10
+ end
11
+
12
+ add_check "server copy exists" do
13
+ failure "exists locally but not on server" unless item.server
14
+ end
15
+
16
+ add_check "items are the same" do
17
+ if item.server && item.local
18
+ failure "#{item.server}\n is not equal to\n #{item.local}" unless item.server == item.local
19
+ end
20
+ end
21
+
22
+ Role = Struct.new(:name, :server, :local)
23
+
24
+ def items
25
+ server_items = items_on_server
26
+ local_items = items_in_repo
27
+ all_item_names = ( server_items + local_items ).uniq.sort
28
+
29
+ all_item_names.map do |name|
30
+ Role.new.tap do |item|
31
+ item.name = name
32
+ item.server = load_item_from_server(name)
33
+ item.local = load_item_from_local(name)
34
+ end
35
+ end
36
+ end
37
+
38
+ def items_on_server
39
+ @items_on_server ||= Chef::Role.list.keys
40
+ end
41
+
42
+ def items_in_repo
43
+ Dir.chdir("#{@context.repo_path}/roles") do
44
+ Dir["*.rb"].map { |e| e.gsub('.rb', '') }
45
+ end
46
+ end
47
+
48
+ def load_item_from_server(name)
49
+ role = Chef::Role.load(name)
50
+ role.to_hash
51
+ rescue
52
+ nil
53
+ end
54
+
55
+ def load_item_from_local(name)
56
+ role = Chef::Role.new
57
+ role.from_file( "#{@context.repo_path}/roles/#{name}.rb" )
58
+ role.to_hash
59
+ rescue IOError
60
+ nil
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -11,10 +11,12 @@ module HealthInspector
11
11
  end
12
12
 
13
13
  def config
14
- @config ||= begin
15
- Chef::Config.from_file(config_path)
16
- Chef::Config
17
- end
14
+ @config ||= configure
15
+ end
16
+
17
+ def configure
18
+ Chef::Config.from_file(config_path)
19
+ Chef::Config
18
20
  end
19
21
  end
20
22
  end
@@ -6,10 +6,15 @@ module HealthInspector
6
6
 
7
7
  def initialize(repo_path, config_path)
8
8
  @context = Context.new( repo_path, File.join(repo_path, config_path) )
9
+ @context.configure
9
10
  end
10
11
 
11
12
  def inspect
12
13
  Checklists::Cookbooks.run(@context)
14
+ Checklists::DataBags.run(@context)
15
+ Checklists::DataBagItems.run(@context)
16
+ Checklists::Environments.run(@context)
17
+ Checklists::Roles.run(@context)
13
18
  end
14
19
  end
15
20
  end
@@ -1,3 +1,3 @@
1
1
  module HealthInspector
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: health_inspector
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-27 00:00:00.000000000Z
12
+ date: 2012-04-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
16
- requirement: &2164944480 !ruby/object:Gem::Requirement
16
+ requirement: &2168869000 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2164944480
24
+ version_requirements: *2168869000
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: chef
27
- requirement: &2164944060 !ruby/object:Gem::Requirement
27
+ requirement: &2168868580 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2164944060
35
+ version_requirements: *2168868580
36
36
  description: A tool to inspect your chef repo as is compares to what is on your chef
37
37
  server
38
38
  email:
@@ -54,6 +54,10 @@ files:
54
54
  - lib/health_inspector/check.rb
55
55
  - lib/health_inspector/checklists/base.rb
56
56
  - lib/health_inspector/checklists/cookbooks.rb
57
+ - lib/health_inspector/checklists/data_bag_items.rb
58
+ - lib/health_inspector/checklists/data_bags.rb
59
+ - lib/health_inspector/checklists/environments.rb
60
+ - lib/health_inspector/checklists/roles.rb
57
61
  - lib/health_inspector/cli.rb
58
62
  - lib/health_inspector/color.rb
59
63
  - lib/health_inspector/context.rb