knife-inspect 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.travis.yml +3 -2
- data/HISTORY.md +12 -0
- data/README.md +10 -0
- data/knife-inspect.gemspec +2 -2
- data/lib/chef/knife/cookbook_inspect.rb +4 -27
- data/lib/chef/knife/data_bag_inspect.rb +7 -3
- data/lib/chef/knife/environment_inspect.rb +4 -16
- data/lib/chef/knife/inspect.rb +6 -5
- data/lib/chef/knife/role_inspect.rb +4 -16
- data/lib/health_inspector.rb +11 -10
- data/lib/health_inspector/checklists/base.rb +30 -27
- data/lib/health_inspector/checklists/cookbooks.rb +44 -52
- data/lib/health_inspector/checklists/data_bag_items.rb +11 -12
- data/lib/health_inspector/checklists/data_bags.rb +5 -6
- data/lib/health_inspector/checklists/environments.rb +8 -9
- data/lib/health_inspector/checklists/roles.rb +6 -7
- data/lib/health_inspector/color.rb +18 -19
- data/lib/health_inspector/context.rb +1 -1
- data/lib/health_inspector/pairing.rb +27 -32
- data/lib/health_inspector/runner.rb +29 -0
- data/lib/health_inspector/version.rb +1 -1
- data/spec/chef-repo/data_bags/data_bag_one/one.json +4 -0
- data/spec/chef-repo/data_bags/data_bag_two/two.json +1 -0
- data/spec/chef/knife/cookbook_inspect_spec.rb +10 -0
- data/spec/chef/knife/data_bag_inspect_spec.rb +79 -0
- data/spec/chef/knife/environment_inspect_spec.rb +10 -0
- data/spec/chef/knife/inspect_spec.rb +51 -0
- data/spec/chef/knife/role_inspect_spec.rb +10 -0
- data/spec/health_inspector/checklists/cookbook_spec.rb +23 -21
- data/spec/health_inspector/checklists/cookbooks_spec.rb +14 -12
- data/spec/health_inspector/checklists/data_bag_item_spec.rb +3 -3
- data/spec/health_inspector/checklists/data_bag_items_spec.rb +96 -10
- data/spec/health_inspector/checklists/data_bag_spec.rb +3 -3
- data/spec/health_inspector/checklists/data_bags_spec.rb +28 -11
- data/spec/health_inspector/checklists/environment_spec.rb +6 -7
- data/spec/health_inspector/checklists/environments_spec.rb +9 -11
- data/spec/health_inspector/checklists/role_spec.rb +3 -3
- data/spec/health_inspector/checklists/roles_spec.rb +9 -11
- data/spec/spec_helper.rb +122 -56
- metadata +37 -26
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'chef/data_bag'
|
2
2
|
|
3
3
|
module HealthInspector
|
4
4
|
module Checklists
|
@@ -8,21 +8,21 @@ module HealthInspector
|
|
8
8
|
end
|
9
9
|
|
10
10
|
class DataBagItems < Base
|
11
|
-
title
|
11
|
+
title 'data bag items'
|
12
12
|
|
13
13
|
def load_item(name)
|
14
14
|
DataBagItem.new(@context,
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
name: name,
|
16
|
+
server: load_item_from_server(name),
|
17
|
+
local: load_item_from_local(name)
|
18
18
|
)
|
19
19
|
end
|
20
20
|
|
21
21
|
def server_items
|
22
22
|
@server_items ||= Chef::DataBag.list.keys.map do |bag_name|
|
23
|
-
[
|
24
|
-
end.
|
25
|
-
arr
|
23
|
+
[bag_name, Chef::DataBag.load(bag_name)]
|
24
|
+
end.reduce([]) do |arr, (bag_name, data_bag)|
|
25
|
+
arr + data_bag.keys.map { |item_name| "#{bag_name}/#{item_name}" }
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -34,9 +34,9 @@ module HealthInspector
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def load_item_from_server(name)
|
37
|
-
bag_name, item_name = name.split(
|
37
|
+
bag_name, item_name = name.split('/')
|
38
38
|
Chef::DataBagItem.load(bag_name, item_name).raw_data
|
39
|
-
rescue
|
39
|
+
rescue Net::HTTPServerException
|
40
40
|
nil
|
41
41
|
end
|
42
42
|
|
@@ -50,10 +50,9 @@ module HealthInspector
|
|
50
50
|
return nil if local_data_bag_item.nil?
|
51
51
|
|
52
52
|
Yajl::Parser.parse(File.read(local_data_bag_item))
|
53
|
-
rescue
|
53
|
+
rescue Yajl::ParseError
|
54
54
|
nil
|
55
55
|
end
|
56
56
|
end
|
57
|
-
|
58
57
|
end
|
59
58
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'chef/data_bag'
|
2
2
|
|
3
3
|
module HealthInspector
|
4
4
|
module Checklists
|
@@ -7,13 +7,13 @@ module HealthInspector
|
|
7
7
|
end
|
8
8
|
|
9
9
|
class DataBags < Base
|
10
|
-
title
|
10
|
+
title 'data bags'
|
11
11
|
|
12
12
|
def load_item(name)
|
13
13
|
DataBag.new(@context,
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
name: name,
|
15
|
+
server: server_items.include?(name),
|
16
|
+
local: local_items.include?(name)
|
17
17
|
)
|
18
18
|
end
|
19
19
|
|
@@ -28,6 +28,5 @@ module HealthInspector
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
32
31
|
end
|
33
32
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'chef/environment'
|
2
2
|
|
3
3
|
module HealthInspector
|
4
4
|
module Checklists
|
@@ -7,6 +7,7 @@ module HealthInspector
|
|
7
7
|
include JsonValidations
|
8
8
|
|
9
9
|
private
|
10
|
+
|
10
11
|
# Override to ignore _default environment if it is missing locally
|
11
12
|
def validate_local_copy_exists
|
12
13
|
super unless name == '_default'
|
@@ -14,13 +15,13 @@ module HealthInspector
|
|
14
15
|
end
|
15
16
|
|
16
17
|
class Environments < Base
|
17
|
-
title
|
18
|
+
title 'environments'
|
18
19
|
|
19
20
|
def load_item(name)
|
20
21
|
Environment.new(@context,
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
name: name,
|
23
|
+
server: load_item_from_server(name),
|
24
|
+
local: load_item_from_local(name)
|
24
25
|
)
|
25
26
|
end
|
26
27
|
|
@@ -35,16 +36,14 @@ module HealthInspector
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def load_item_from_server(name)
|
38
|
-
|
39
|
-
env.to_hash
|
39
|
+
Chef::Environment.load(name).to_hash
|
40
40
|
rescue
|
41
41
|
nil
|
42
42
|
end
|
43
43
|
|
44
44
|
def load_item_from_local(name)
|
45
|
-
load_ruby_or_json_from_local(Chef::Environment,
|
45
|
+
load_ruby_or_json_from_local(Chef::Environment, 'environments', name)
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
49
48
|
end
|
50
49
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'chef/role'
|
2
2
|
require 'yajl'
|
3
3
|
|
4
4
|
module HealthInspector
|
@@ -9,13 +9,13 @@ module HealthInspector
|
|
9
9
|
end
|
10
10
|
|
11
11
|
class Roles < Base
|
12
|
-
title
|
12
|
+
title 'roles'
|
13
13
|
|
14
14
|
def load_item(name)
|
15
15
|
Role.new(@context,
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
name: name,
|
17
|
+
server: load_item_from_server(name),
|
18
|
+
local: load_item_from_local(name)
|
19
19
|
)
|
20
20
|
end
|
21
21
|
|
@@ -37,9 +37,8 @@ module HealthInspector
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def load_item_from_local(name)
|
40
|
-
load_ruby_or_json_from_local(Chef::Role,
|
40
|
+
load_ruby_or_json_from_local(Chef::Role, 'roles', name)
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
44
43
|
end
|
45
44
|
end
|
@@ -1,27 +1,26 @@
|
|
1
1
|
module HealthInspector
|
2
2
|
module Color
|
3
|
-
|
4
3
|
# TODO: Use a highline color scheme here instead
|
5
4
|
def color(type, str)
|
6
5
|
colors = {
|
7
|
-
'pass' => [:green]
|
8
|
-
'fail' => [:red]
|
9
|
-
'bright pass' => [:bold, :green]
|
10
|
-
'bright fail' => [:bold, :red]
|
11
|
-
'bright yellow' => [:bold, :yellow]
|
12
|
-
'pending' => [:yellow]
|
13
|
-
'suite' => []
|
14
|
-
'error title' => []
|
15
|
-
'error message' => [:red]
|
16
|
-
'error stack' => [:green]
|
17
|
-
'checkmark' => [:green]
|
18
|
-
'fast' => [:green]
|
19
|
-
'medium' => [:green]
|
20
|
-
'slow' => [:red]
|
21
|
-
'green' => [:green]
|
22
|
-
'light' => [:green]
|
23
|
-
'diff gutter' => [:green]
|
24
|
-
'diff added' => [:green]
|
6
|
+
'pass' => [:green], # 90,
|
7
|
+
'fail' => [:red], # 31,
|
8
|
+
'bright pass' => [:bold, :green], # 92,
|
9
|
+
'bright fail' => [:bold, :red], # 91,
|
10
|
+
'bright yellow' => [:bold, :yellow], # 93,
|
11
|
+
'pending' => [:yellow], # 36,
|
12
|
+
'suite' => [], # 0,
|
13
|
+
'error title' => [], # 0,
|
14
|
+
'error message' => [:red], # 31,
|
15
|
+
'error stack' => [:green], # 90,
|
16
|
+
'checkmark' => [:green], # 32,
|
17
|
+
'fast' => [:green], # 90,
|
18
|
+
'medium' => [:green], # 33,
|
19
|
+
'slow' => [:red], # 31,
|
20
|
+
'green' => [:green], # 32,
|
21
|
+
'light' => [:green], # 90,
|
22
|
+
'diff gutter' => [:green], # 90,
|
23
|
+
'diff added' => [:green], # 42,
|
25
24
|
'diff removed' => [:red]# 41
|
26
25
|
}
|
27
26
|
|
@@ -1,29 +1,22 @@
|
|
1
1
|
module HealthInspector
|
2
2
|
class Errors
|
3
|
+
extend Forwardable
|
4
|
+
def_delegators :@errors, :each, :empty?, :<<
|
5
|
+
|
3
6
|
include Enumerable
|
4
7
|
|
5
8
|
def initialize
|
6
9
|
@errors = []
|
7
10
|
end
|
8
11
|
|
9
|
-
|
10
|
-
@errors << message
|
11
|
-
end
|
12
|
-
|
13
|
-
def each
|
14
|
-
@errors.each { |e| yield(e) }
|
15
|
-
end
|
16
|
-
|
17
|
-
def empty?
|
18
|
-
@errors.empty?
|
19
|
-
end
|
12
|
+
alias_method :add, :<<
|
20
13
|
end
|
21
14
|
|
22
15
|
class Pairing
|
23
16
|
attr_accessor :name, :local, :server
|
24
17
|
attr_reader :context, :errors
|
25
18
|
|
26
|
-
def initialize(context, opts={})
|
19
|
+
def initialize(context, opts = {})
|
27
20
|
@context = context
|
28
21
|
@name = opts[:name]
|
29
22
|
@local = opts[:local]
|
@@ -34,7 +27,7 @@ module HealthInspector
|
|
34
27
|
end
|
35
28
|
|
36
29
|
def validate
|
37
|
-
|
30
|
+
methods.grep(/^validate_/).each { |meth| send(meth) }
|
38
31
|
end
|
39
32
|
|
40
33
|
def hash_diff(original, other)
|
@@ -42,32 +35,33 @@ module HealthInspector
|
|
42
35
|
end
|
43
36
|
|
44
37
|
def stringify_hash_keys(original)
|
45
|
-
original.keys.
|
38
|
+
original.keys.reduce({}) do |original_strkey, key|
|
46
39
|
original_strkey[key.to_s] = stringify_item(original[key])
|
47
40
|
original_strkey
|
48
41
|
end
|
49
42
|
end
|
50
43
|
|
51
44
|
def stringify_item(item)
|
52
|
-
if item.
|
45
|
+
if item.is_a?(Hash)
|
53
46
|
stringify_hash_keys(item)
|
54
|
-
elsif item.
|
55
|
-
item.map {|array_item| stringify_item(array_item) }
|
47
|
+
elsif item.is_a?(Array)
|
48
|
+
item.map { |array_item| stringify_item(array_item) }
|
56
49
|
else # must be a string
|
57
50
|
item
|
58
51
|
end
|
59
52
|
end
|
60
53
|
|
61
54
|
def recursive_diff(original, other)
|
62
|
-
(original.keys + other.keys).uniq.
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
55
|
+
(original.keys + other.keys).uniq.reduce({}) do |memo, key|
|
56
|
+
return memo if original[key] == other[key]
|
57
|
+
|
58
|
+
if original[key].is_a?(Hash) && other[key].is_a?(Hash)
|
59
|
+
diff = recursive_diff(original[key], other[key])
|
60
|
+
memo[key] = diff unless diff.empty?
|
61
|
+
else
|
62
|
+
memo[key] = { 'server' => original[key], 'local' => other[key] }
|
70
63
|
end
|
64
|
+
|
71
65
|
memo
|
72
66
|
end
|
73
67
|
end
|
@@ -77,7 +71,7 @@ module HealthInspector
|
|
77
71
|
module ExistenceValidations
|
78
72
|
def validate_existence
|
79
73
|
if local.nil? && server.nil?
|
80
|
-
errors.add
|
74
|
+
errors.add 'does not exist locally or on server'
|
81
75
|
return
|
82
76
|
end
|
83
77
|
|
@@ -86,21 +80,22 @@ module HealthInspector
|
|
86
80
|
end
|
87
81
|
|
88
82
|
private
|
83
|
+
|
89
84
|
def validate_local_copy_exists
|
90
|
-
errors.add
|
85
|
+
errors.add 'exists on server but not locally' if local.nil?
|
91
86
|
end
|
92
87
|
|
93
88
|
def validate_server_copy_exists
|
94
|
-
errors.add
|
89
|
+
errors.add 'exists locally but not on server' if server.nil?
|
95
90
|
end
|
96
91
|
end
|
97
92
|
|
98
93
|
module JsonValidations
|
99
94
|
def validate_items_are_the_same
|
100
|
-
if server
|
101
|
-
|
102
|
-
|
103
|
-
|
95
|
+
return if server.nil? || local.nil?
|
96
|
+
|
97
|
+
differences = hash_diff(server, local)
|
98
|
+
errors.add differences unless differences.empty?
|
104
99
|
end
|
105
100
|
end
|
106
101
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HealthInspector
|
2
|
+
module Runner
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
attr_reader :checklist
|
9
|
+
|
10
|
+
def checklist(value = nil)
|
11
|
+
return @checklist if value.nil?
|
12
|
+
|
13
|
+
@checklist = value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
case @name_args.length
|
19
|
+
when 1 # We are inspecting an item
|
20
|
+
item = @name_args[0]
|
21
|
+
validator = self.class.checklist.new(self)
|
22
|
+
item = validator.load_item item
|
23
|
+
exit validator.validate_item item
|
24
|
+
when 0 # We are inspecting all the items
|
25
|
+
exit self.class.checklist.run(self)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{ 'this': 'is not really json' }
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'chef/knife/data_bag_inspect'
|
3
|
+
|
4
|
+
RSpec.describe Chef::Knife::DataBagInspect do
|
5
|
+
describe '#run' do
|
6
|
+
context 'when not passing arguments' do
|
7
|
+
let :data_bag_inspect do
|
8
|
+
described_class.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'inspects all the data bags and data bag items' do
|
12
|
+
expect(HealthInspector::Checklists::DataBags).to receive(:run)
|
13
|
+
.with(data_bag_inspect)
|
14
|
+
.and_return true
|
15
|
+
expect(HealthInspector::Checklists::DataBagItems).to receive(:run)
|
16
|
+
.with(data_bag_inspect)
|
17
|
+
.and_return true
|
18
|
+
expect(data_bag_inspect).to receive(:exit).with true
|
19
|
+
|
20
|
+
data_bag_inspect.run
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when passing a data_bag as an argument' do
|
25
|
+
let :data_bag_inspect do
|
26
|
+
described_class.new ['some_data_bag']
|
27
|
+
end
|
28
|
+
|
29
|
+
let :checklist do
|
30
|
+
double
|
31
|
+
end
|
32
|
+
|
33
|
+
let :data_bag do
|
34
|
+
double
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'inspects this data_bag' do
|
38
|
+
expect(HealthInspector::Checklists::DataBags).to receive(:new)
|
39
|
+
.with(data_bag_inspect)
|
40
|
+
.and_return checklist
|
41
|
+
expect(checklist).to receive(:load_item)
|
42
|
+
.with('some_data_bag').and_return data_bag
|
43
|
+
expect(checklist).to receive(:validate_item)
|
44
|
+
.with(data_bag).and_return true
|
45
|
+
expect(data_bag_inspect).to receive(:exit).with true
|
46
|
+
|
47
|
+
data_bag_inspect.run
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'when passing a data bag and data_bag item as arguments' do
|
52
|
+
let :data_bag_inspect do
|
53
|
+
described_class.new ['some_data_bag', 'item']
|
54
|
+
end
|
55
|
+
|
56
|
+
let :checklist do
|
57
|
+
double
|
58
|
+
end
|
59
|
+
|
60
|
+
let :data_bag do
|
61
|
+
double
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'inspects this data_bag' do
|
65
|
+
expect(HealthInspector::Checklists::DataBagItems).to receive(:new)
|
66
|
+
.with(data_bag_inspect)
|
67
|
+
.and_return checklist
|
68
|
+
expect(checklist).to receive(:load_item)
|
69
|
+
.with('some_data_bag/item')
|
70
|
+
.and_return data_bag
|
71
|
+
expect(checklist).to receive(:validate_item)
|
72
|
+
.with(data_bag).and_return true
|
73
|
+
expect(data_bag_inspect).to receive(:exit).with true
|
74
|
+
|
75
|
+
data_bag_inspect.run
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|