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 +7 -3
- data/lib/health_inspector.rb +4 -3
- data/lib/health_inspector/checklists/base.rb +60 -0
- data/lib/health_inspector/checklists/cookbooks.rb +21 -63
- data/lib/health_inspector/checklists/data_bag_items.rb +71 -0
- data/lib/health_inspector/checklists/data_bags.rb +44 -0
- data/lib/health_inspector/checklists/environments.rb +65 -0
- data/lib/health_inspector/checklists/roles.rb +65 -0
- data/lib/health_inspector/context.rb +6 -4
- data/lib/health_inspector/inspector.rb +5 -0
- data/lib/health_inspector/version.rb +1 -1
- metadata +10 -6
data/HISTORY.md
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
## 0.0.
|
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
|
data/lib/health_inspector.rb
CHANGED
@@ -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
|
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
|
-
|
15
|
-
|
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
|
-
|
21
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
69
|
-
|
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
|
-
|
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 ||=
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
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.
|
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-
|
12
|
+
date: 2012-04-09 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
16
|
-
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: *
|
24
|
+
version_requirements: *2168869000
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: chef
|
27
|
-
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: *
|
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
|