health_inspector 0.0.3 → 0.0.4

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