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.
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