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.
Files changed (41) hide show
  1. checksums.yaml +5 -13
  2. data/.travis.yml +3 -2
  3. data/HISTORY.md +12 -0
  4. data/README.md +10 -0
  5. data/knife-inspect.gemspec +2 -2
  6. data/lib/chef/knife/cookbook_inspect.rb +4 -27
  7. data/lib/chef/knife/data_bag_inspect.rb +7 -3
  8. data/lib/chef/knife/environment_inspect.rb +4 -16
  9. data/lib/chef/knife/inspect.rb +6 -5
  10. data/lib/chef/knife/role_inspect.rb +4 -16
  11. data/lib/health_inspector.rb +11 -10
  12. data/lib/health_inspector/checklists/base.rb +30 -27
  13. data/lib/health_inspector/checklists/cookbooks.rb +44 -52
  14. data/lib/health_inspector/checklists/data_bag_items.rb +11 -12
  15. data/lib/health_inspector/checklists/data_bags.rb +5 -6
  16. data/lib/health_inspector/checklists/environments.rb +8 -9
  17. data/lib/health_inspector/checklists/roles.rb +6 -7
  18. data/lib/health_inspector/color.rb +18 -19
  19. data/lib/health_inspector/context.rb +1 -1
  20. data/lib/health_inspector/pairing.rb +27 -32
  21. data/lib/health_inspector/runner.rb +29 -0
  22. data/lib/health_inspector/version.rb +1 -1
  23. data/spec/chef-repo/data_bags/data_bag_one/one.json +4 -0
  24. data/spec/chef-repo/data_bags/data_bag_two/two.json +1 -0
  25. data/spec/chef/knife/cookbook_inspect_spec.rb +10 -0
  26. data/spec/chef/knife/data_bag_inspect_spec.rb +79 -0
  27. data/spec/chef/knife/environment_inspect_spec.rb +10 -0
  28. data/spec/chef/knife/inspect_spec.rb +51 -0
  29. data/spec/chef/knife/role_inspect_spec.rb +10 -0
  30. data/spec/health_inspector/checklists/cookbook_spec.rb +23 -21
  31. data/spec/health_inspector/checklists/cookbooks_spec.rb +14 -12
  32. data/spec/health_inspector/checklists/data_bag_item_spec.rb +3 -3
  33. data/spec/health_inspector/checklists/data_bag_items_spec.rb +96 -10
  34. data/spec/health_inspector/checklists/data_bag_spec.rb +3 -3
  35. data/spec/health_inspector/checklists/data_bags_spec.rb +28 -11
  36. data/spec/health_inspector/checklists/environment_spec.rb +6 -7
  37. data/spec/health_inspector/checklists/environments_spec.rb +9 -11
  38. data/spec/health_inspector/checklists/role_spec.rb +3 -3
  39. data/spec/health_inspector/checklists/roles_spec.rb +9 -11
  40. data/spec/spec_helper.rb +122 -56
  41. metadata +37 -26
@@ -1,4 +1,4 @@
1
- require "chef/data_bag"
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 "data bag items"
11
+ title 'data bag items'
12
12
 
13
13
  def load_item(name)
14
14
  DataBagItem.new(@context,
15
- :name => name,
16
- :server => load_item_from_server(name),
17
- :local => load_item_from_local(name)
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
- [ bag_name, Chef::DataBag.load(bag_name) ]
24
- end.inject([]) do |arr, (bag_name, data_bag)|
25
- arr += data_bag.keys.map { |item_name| "#{bag_name}/#{item_name}"}
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 IOError, Errno::ENOENT
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 "chef/data_bag"
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 "data bags"
10
+ title 'data bags'
11
11
 
12
12
  def load_item(name)
13
13
  DataBag.new(@context,
14
- :name => name,
15
- :server => server_items.include?(name),
16
- :local => local_items.include?(name)
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 "chef/environment"
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 "environments"
18
+ title 'environments'
18
19
 
19
20
  def load_item(name)
20
21
  Environment.new(@context,
21
- :name => name,
22
- :server => load_item_from_server(name),
23
- :local => load_item_from_local(name)
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
- env = Chef::Environment.load(name)
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, "environments", name)
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 "chef/role"
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 "roles"
12
+ title 'roles'
13
13
 
14
14
  def load_item(name)
15
15
  Role.new(@context,
16
- :name => name,
17
- :server => load_item_from_server(name),
18
- :local => load_item_from_local(name)
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, "roles", name)
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],# 90,
8
- 'fail' => [:red],# 31,
9
- 'bright pass' => [:bold, :green],# 92,
10
- 'bright fail' => [:bold, :red],# 91,
11
- 'bright yellow' => [:bold, :yellow],# 93,
12
- 'pending' => [:yellow],# 36,
13
- 'suite' => [],# 0,
14
- 'error title' => [],# 0,
15
- 'error message' => [:red],# 31,
16
- 'error stack' => [:green],# 90,
17
- 'checkmark' => [:green],# 32,
18
- 'fast' => [:green],# 90,
19
- 'medium' => [:green],# 33,
20
- 'slow' => [:red],# 31,
21
- 'green' => [:green],# 32,
22
- 'light' => [:green],# 90,
23
- 'diff gutter' => [:green],# 90,
24
- 'diff added' => [:green],# 42,
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,4 +1,4 @@
1
- require "chef/config"
1
+ require 'chef/config'
2
2
 
3
3
  module HealthInspector
4
4
  class Context
@@ -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
- def add(message)
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
- self.methods.grep(/^validate_/).each { |meth| send(meth) }
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.inject({}) do |original_strkey, key|
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.kind_of?(Hash)
45
+ if item.is_a?(Hash)
53
46
  stringify_hash_keys(item)
54
- elsif item.kind_of?(Array)
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.inject({}) do |memo, key|
63
- unless original[key] == other[key]
64
- if original[key].kind_of?(Hash) && other[key].kind_of?(Hash)
65
- diff = recursive_diff(original[key], other[key])
66
- memo[key] = diff unless diff.empty?
67
- else
68
- memo[key] = {"server" => original[key], "local" => other[key]}
69
- end
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 "does not exist locally or on server"
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 "exists on server but not locally" if local.nil?
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 "exists locally but not on server" if server.nil?
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 && local
101
- differences = hash_diff(server, local)
102
- errors.add differences unless differences.empty?
103
- end
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
@@ -1,3 +1,3 @@
1
1
  module HealthInspector
2
- VERSION = '0.8.0'
2
+ VERSION = '0.9.0'
3
3
  end
@@ -0,0 +1,4 @@
1
+ {
2
+ "id": "one",
3
+ "some": "key"
4
+ }
@@ -0,0 +1 @@
1
+ { 'this': 'is not really json' }
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'chef/knife/cookbook_inspect'
3
+
4
+ RSpec.describe Chef::Knife::CookbookInspect do
5
+ it_behaves_like 'a knife inspect runner' do
6
+ let :checklist do
7
+ HealthInspector::Checklists::Cookbooks
8
+ end
9
+ end
10
+ end
@@ -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