knife-inspect 0.8.0 → 0.9.0
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.
- 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
|