vcloud-edge_gateway 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/README.md +219 -11
  3. data/examples/firewall-rules.yaml +50 -0
  4. data/examples/loadbalancer-rules.yaml +55 -0
  5. data/examples/nat-rules.yaml +58 -0
  6. data/lib/vcloud/edge_gateway.rb +2 -3
  7. data/lib/vcloud/edge_gateway/configuration_differ.rb +13 -1
  8. data/lib/vcloud/edge_gateway/configuration_generator/nat_service.rb +10 -10
  9. data/lib/vcloud/edge_gateway/edge_gateway_configuration.rb +2 -2
  10. data/lib/vcloud/edge_gateway/firewall_configuration_differ.rb +18 -0
  11. data/lib/vcloud/edge_gateway/load_balancer_configuration_differ.rb +3 -13
  12. data/lib/vcloud/edge_gateway/nat_configuration_differ.rb +18 -0
  13. data/lib/vcloud/edge_gateway/version.rb +1 -1
  14. data/lib/vcloud/edge_gateway_services.rb +1 -1
  15. data/spec/integration/edge_gateway/edge_gateway_services_spec.rb +7 -13
  16. data/spec/integration/edge_gateway/firewall_service_spec.rb +2 -12
  17. data/spec/integration/edge_gateway/load_balancer_service_spec.rb +4 -4
  18. data/spec/integration/edge_gateway/nat_service_spec.rb +4 -4
  19. data/spec/spec_helper.rb +2 -2
  20. data/spec/vcloud/edge_gateway/configuration_differ_shared_examples.rb +132 -0
  21. data/spec/vcloud/edge_gateway/configuration_differ_spec.rb +5 -122
  22. data/spec/vcloud/edge_gateway/configuration_generator/firewall_service_spec.rb +46 -52
  23. data/spec/vcloud/edge_gateway/firewall_configuration_differ_spec.rb +65 -0
  24. data/spec/vcloud/edge_gateway/firewall_schema_validation_spec.rb +2 -2
  25. data/spec/vcloud/edge_gateway/load_balancer_configuration_differ_spec.rb +32 -147
  26. data/spec/vcloud/edge_gateway/load_balancer_schema_validation_spec.rb +7 -7
  27. data/spec/vcloud/edge_gateway/nat_configuration_differ_spec.rb +65 -0
  28. data/spec/vcloud/edge_gateway/nat_schema_validation_spec.rb +4 -4
  29. data/vcloud-edge_gateway.gemspec +2 -2
  30. metadata +18 -13
  31. data/lib/vcloud/config_loader.rb +0 -27
  32. data/lib/vcloud/config_validator.rb +0 -207
  33. data/spec/vcloud/config_loader_spec.rb +0 -112
  34. data/spec/vcloud/config_validator_spec.rb +0 -570
@@ -3,9 +3,6 @@ require 'vcloud/edge_gateway/version'
3
3
  require 'vcloud/core'
4
4
  require 'vcloud/fog'
5
5
 
6
- require 'vcloud/config_loader'
7
- require 'vcloud/config_validator'
8
-
9
6
  require 'vcloud/edge_gateway_services'
10
7
 
11
8
  require 'vcloud/schema/nat_service'
@@ -18,6 +15,8 @@ require 'vcloud/edge_gateway/configuration_generator/firewall_service'
18
15
  require 'vcloud/edge_gateway/configuration_generator/nat_service'
19
16
  require 'vcloud/edge_gateway/configuration_generator/load_balancer_service'
20
17
  require 'vcloud/edge_gateway/configuration_differ'
18
+ require 'vcloud/edge_gateway/nat_configuration_differ'
19
+ require 'vcloud/edge_gateway/firewall_configuration_differ'
21
20
  require 'vcloud/edge_gateway/load_balancer_configuration_differ'
22
21
  require 'vcloud/edge_gateway/edge_gateway_configuration'
23
22
 
@@ -8,7 +8,19 @@ module Vcloud
8
8
  end
9
9
 
10
10
  def diff
11
- ( @local == @remote ) ? [] : HashDiff.diff(@local, @remote)
11
+ ( stripped_local_config == stripped_remote_config ) ? [] : HashDiff.diff(stripped_local_config, stripped_remote_config)
12
+ end
13
+
14
+ def stripped_local_config
15
+ strip_fields_for_differ_to_ignore(@local) unless @local.nil?
16
+ end
17
+
18
+ def stripped_remote_config
19
+ strip_fields_for_differ_to_ignore(@remote) unless @remote.nil?
20
+ end
21
+
22
+ def strip_fields_for_differ_to_ignore(config)
23
+ config
12
24
  end
13
25
 
14
26
  end
@@ -19,16 +19,16 @@ module Vcloud
19
19
 
20
20
  def populate_nat_rules
21
21
  rules = @input_config[:nat_rules]
22
- i = ID_RANGES::NAT_SERVICE[:min]
23
- rules.collect do |rule|
24
- new_rule = {}
25
- new_rule[:Id] = rule.key?(:id) ? rule[:id] : i.to_s
26
- new_rule[:IsEnabled] = rule.key?(:enabled) ? rule[:enabled].to_s : 'true'
27
- new_rule[:RuleType] = rule[:rule_type]
28
- gateway_nat_rule = populate_gateway_nat_rule(rule)
29
- new_rule[:GatewayNatRule] = gateway_nat_rule
30
- i += 1
31
- new_rule
22
+ i = ID_RANGES::NAT_SERVICE[:min]
23
+ rules.collect do |rule|
24
+ new_rule = {}
25
+ new_rule[:Id] = rule.key?(:id) ? rule[:id] : i.to_s
26
+ new_rule[:IsEnabled] = rule.key?(:enabled) ? rule[:enabled].to_s : 'true'
27
+ new_rule[:RuleType] = rule[:rule_type]
28
+ gateway_nat_rule = populate_gateway_nat_rule(rule)
29
+ new_rule[:GatewayNatRule] = gateway_nat_rule
30
+ i += 1
31
+ new_rule
32
32
  end
33
33
  end
34
34
 
@@ -15,7 +15,7 @@ module Vcloud
15
15
 
16
16
  firewall_service_config = EdgeGateway::ConfigurationGenerator::FirewallService.new.generate_fog_config(@local_config[:firewall_service])
17
17
  unless firewall_service_config.nil?
18
- differ = EdgeGateway::ConfigurationDiffer.new(firewall_service_config, @remote_config[:FirewallService])
18
+ differ = EdgeGateway::FirewallConfigurationDiffer.new(firewall_service_config, @remote_config[:FirewallService])
19
19
  unless differ.diff.empty?
20
20
  @config[:FirewallService] = firewall_service_config
21
21
  @update_required = true
@@ -28,7 +28,7 @@ module Vcloud
28
28
  ).generate_fog_config
29
29
 
30
30
  unless nat_service_config.nil?
31
- differ = EdgeGateway::ConfigurationDiffer.new(nat_service_config, @remote_config[:NatService])
31
+ differ = EdgeGateway::NatConfigurationDiffer.new(nat_service_config, @remote_config[:NatService])
32
32
  unless differ.diff.empty?
33
33
  @config[:NatService] = nat_service_config
34
34
  @update_required = true
@@ -0,0 +1,18 @@
1
+ module Vcloud
2
+ module EdgeGateway
3
+ class FirewallConfigurationDiffer < ConfigurationDiffer
4
+
5
+ def strip_fields_for_differ_to_ignore(config)
6
+ deep_cloned_config = Marshal.load( Marshal.dump(config) )
7
+ if deep_cloned_config.key?(:FirewallRule)
8
+ deep_cloned_config[:FirewallRule].each do |firewall_rule|
9
+ firewall_rule.delete(:Id)
10
+ end
11
+ end
12
+ deep_cloned_config
13
+ end
14
+
15
+ end
16
+ end
17
+
18
+ end
@@ -1,19 +1,9 @@
1
1
  module Vcloud
2
2
  module EdgeGateway
3
- class LoadBalancerConfigurationDiffer
3
+ class LoadBalancerConfigurationDiffer < ConfigurationDiffer
4
4
 
5
- def initialize local, remote
6
- @local = local
7
- @remote = remote
8
- end
9
-
10
- def diff
11
- ( @local == stripped_remote_config ) ? [] : HashDiff.diff(@local, stripped_remote_config)
12
- end
13
-
14
- def stripped_remote_config
15
- return nil if @remote.nil?
16
- deep_cloned_remote_config = Marshal.load( Marshal.dump(@remote) )
5
+ def strip_fields_for_differ_to_ignore(config)
6
+ deep_cloned_remote_config = Marshal.load( Marshal.dump(config) )
17
7
  if deep_cloned_remote_config.key?(:Pool)
18
8
  deep_cloned_remote_config[:Pool].each do |pool_entry|
19
9
  pool_entry.delete(:Operational)
@@ -0,0 +1,18 @@
1
+ module Vcloud
2
+ module EdgeGateway
3
+ class NatConfigurationDiffer < ConfigurationDiffer
4
+
5
+ def strip_fields_for_differ_to_ignore(config)
6
+ deep_cloned_config = Marshal.load( Marshal.dump(config) )
7
+ if deep_cloned_config.key?(:NatRule)
8
+ deep_cloned_config[:NatRule].each do |nat_rule|
9
+ nat_rule.delete(:Id)
10
+ end
11
+ end
12
+ deep_cloned_config
13
+ end
14
+
15
+ end
16
+ end
17
+
18
+ end
@@ -1,6 +1,6 @@
1
1
  module Vcloud
2
2
  module EdgeGateway
3
- VERSION = '0.2.2'
3
+ VERSION = '0.2.3'
4
4
  end
5
5
  end
6
6
 
@@ -4,7 +4,7 @@ module Vcloud
4
4
  class EdgeGatewayServices
5
5
 
6
6
  def initialize
7
- @config_loader = Vcloud::ConfigLoader.new
7
+ @config_loader = Vcloud::Core::ConfigLoader.new
8
8
  end
9
9
 
10
10
  def update(config_file = nil)
@@ -49,13 +49,6 @@ module Vcloud
49
49
 
50
50
  context "Check update is functional" do
51
51
 
52
- before(:all) do
53
- local_config = ConfigLoader.new.load_config(
54
- @initial_config_file,
55
- Vcloud::Schema::EDGE_GATEWAY_SERVICES
56
- )
57
- end
58
-
59
52
  it "should be starting our tests from an empty EdgeGateway" do
60
53
  remote_vcloud_config = @edge_gateway.vcloud_attributes[:Configuration][:EdgeGatewayServiceConfiguration]
61
54
  expect(remote_vcloud_config[:FirewallService][:FirewallRule].empty?).to be_true
@@ -65,7 +58,7 @@ module Vcloud
65
58
  end
66
59
 
67
60
  it "should only create one edgeGateway update task when updating the configuration" do
68
- start_time = DateTime.now()
61
+ start_time = Time.now.getutc
69
62
  task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
70
63
  EdgeGatewayServices.new.update(@initial_config_file)
71
64
  task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
@@ -81,7 +74,7 @@ module Vcloud
81
74
  end
82
75
 
83
76
  it "should not update the EdgeGateway again if the config hasn't changed" do
84
- start_time = DateTime.now()
77
+ start_time = Time.now.getutc
85
78
  task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
86
79
  EdgeGatewayServices.new.update(@initial_config_file)
87
80
  task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
@@ -89,7 +82,7 @@ module Vcloud
89
82
  end
90
83
 
91
84
  it "should only create one additional edgeGateway update task when adding the LoadBalancer config" do
92
- start_time = DateTime.now()
85
+ start_time = Time.now.getutc
93
86
  task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
94
87
  EdgeGatewayServices.new.update(@adding_load_balancer_config_file)
95
88
  task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
@@ -97,7 +90,7 @@ module Vcloud
97
90
  end
98
91
 
99
92
  it "should not update the EdgeGateway again if we reapply the 'adding load balancer' config" do
100
- start_time = DateTime.now()
93
+ start_time = Time.now.getutc
101
94
  task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
102
95
  EdgeGatewayServices.new.update(@adding_load_balancer_config_file)
103
96
  task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
@@ -147,12 +140,13 @@ module Vcloud
147
140
 
148
141
  def get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(timestamp)
149
142
  vcloud_time = timestamp.strftime('%FT%T.000Z')
150
- q = Query.new('task',
143
+ q = QueryRunner.new
144
+
145
+ q.run('task',
151
146
  :filter =>
152
147
  "name==networkConfigureEdgeGatewayServices;objectName==#{@edge_name};startDate=ge=#{vcloud_time}",
153
148
  :sortDesc => 'startDate',
154
149
  )
155
- q.get_all_results
156
150
  end
157
151
 
158
152
  end
@@ -41,20 +41,10 @@ module Vcloud
41
41
  @firewall_service = {}
42
42
  end
43
43
 
44
- context "Check input schema checking is working" do
45
-
46
- it "should raise exception if input yaml does not match with schema" do
47
- config_yaml = File.expand_path('data/incorrect_firewall_config.yaml', File.dirname(__FILE__))
48
- expect(Vcloud::EdgeGateway.logger).to receive(:fatal)
49
- expect { EdgeGatewayServices.new.update(config_yaml) }.to raise_error('Supplied configuration does not match supplied schema')
50
- end
51
-
52
- end
53
-
54
44
  context "Check update is functional" do
55
45
 
56
46
  before(:all) do
57
- local_config = ConfigLoader.new.load_config(@initial_firewall_config_file, Vcloud::Schema::EDGE_GATEWAY_SERVICES)
47
+ local_config = Core::ConfigLoader.new.load_config(@initial_firewall_config_file, Vcloud::Schema::EDGE_GATEWAY_SERVICES)
58
48
  @local_vcloud_config = EdgeGateway::ConfigurationGenerator::FirewallService.new.generate_fog_config(local_config[:firewall_service])
59
49
  end
60
50
 
@@ -94,7 +84,7 @@ module Vcloud
94
84
  it "should highlight a difference if local firewall config has been updated" do
95
85
  input_config_file = generate_input_config_file('firewall_config_updated_rule.yaml.erb', edge_gateway_erb_input)
96
86
 
97
- local_config = ConfigLoader.new.load_config(input_config_file, Vcloud::Schema::EDGE_GATEWAY_SERVICES)
87
+ local_config = Core::ConfigLoader.new.load_config(input_config_file, Vcloud::Schema::EDGE_GATEWAY_SERVICES)
98
88
  local_firewall_config = EdgeGateway::ConfigurationGenerator::FirewallService.new.generate_fog_config(local_config[:firewall_service])
99
89
 
100
90
  edge_gateway = Core::EdgeGateway.get_by_name local_config[:gateway]
@@ -44,7 +44,7 @@ module Vcloud
44
44
  context "Check update is functional" do
45
45
 
46
46
  before(:all) do
47
- local_config = ConfigLoader.new.load_config(
47
+ local_config = Core::ConfigLoader.new.load_config(
48
48
  @initial_load_balancer_config_file,
49
49
  Vcloud::Schema::EDGE_GATEWAY_SERVICES
50
50
  )
@@ -61,7 +61,7 @@ module Vcloud
61
61
  end
62
62
 
63
63
  it "should only make one EdgeGateway update task, to minimise EdgeGateway reload events" do
64
- start_time = DateTime.now()
64
+ start_time = Time.now.getutc
65
65
  task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
66
66
  EdgeGatewayServices.new.update(@initial_load_balancer_config_file)
67
67
  task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
@@ -190,12 +190,12 @@ module Vcloud
190
190
 
191
191
  def get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(timestamp)
192
192
  vcloud_time = timestamp.strftime('%FT%T.000Z')
193
- q = Query.new('task',
193
+ q = QueryRunner.new
194
+ q.run('task',
194
195
  :filter =>
195
196
  "name==networkConfigureEdgeGatewayServices;objectName==#{@edge_name};startDate=ge=#{vcloud_time}",
196
197
  :sortDesc => 'startDate',
197
198
  )
198
- q.get_all_results
199
199
  end
200
200
 
201
201
  end
@@ -49,7 +49,7 @@ module Vcloud
49
49
  context "Check update is functional" do
50
50
 
51
51
  before(:all) do
52
- local_config = ConfigLoader.new.load_config(
52
+ local_config = Core::ConfigLoader.new.load_config(
53
53
  @initial_nat_config_file, Vcloud::Schema::EDGE_GATEWAY_SERVICES
54
54
  )
55
55
  @local_vcloud_config = EdgeGateway::ConfigurationGenerator::NatService.new(
@@ -64,7 +64,7 @@ module Vcloud
64
64
  end
65
65
 
66
66
  it "should only make one EdgeGateway update task, to minimise EdgeGateway reload events" do
67
- start_time = DateTime.now()
67
+ start_time = Time.now.getutc
68
68
  task_list_before_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
69
69
  EdgeGatewayServices.new.update(@initial_nat_config_file)
70
70
  task_list_after_update = get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(start_time)
@@ -200,11 +200,11 @@ module Vcloud
200
200
 
201
201
  def get_all_edge_gateway_update_tasks_ordered_by_start_date_since_time(timestamp)
202
202
  vcloud_time = timestamp.strftime('%FT%T.000Z')
203
- q = Query.new('task',
203
+ q = QueryRunner.new
204
+ q.run('task',
204
205
  :filter => "name==networkConfigureEdgeGatewayServices;objectName==#{@edge_name};startDate=ge=#{vcloud_time}",
205
206
  :sortDesc => 'startDate',
206
207
  )
207
- q.get_all_results
208
208
  end
209
209
 
210
210
  end
@@ -18,9 +18,9 @@ require 'vcloud/edge_gateway'
18
18
  SimpleCov.at_exit do
19
19
  SimpleCov.result.format!
20
20
  # do not change the coverage percentage, instead add more unit tests to fix coverage failures.
21
- if SimpleCov.result.covered_percent < 60
21
+ if SimpleCov.result.covered_percent < 90
22
22
  print "ERROR::BAD_COVERAGE\n"
23
- print "Coverage is less than acceptable limit(71%). Please add more tests to improve the coverage"
23
+ print "Coverage is less than acceptable limit(90%). Please add more tests to improve the coverage\n"
24
24
  exit(1)
25
25
  end
26
26
  end
@@ -0,0 +1,132 @@
1
+ module Vcloud
2
+ module EdgeGateway
3
+
4
+ shared_examples "a configuration differ" do
5
+
6
+ let(:config_differ) { described_class }
7
+
8
+ it 'should return an empty array for two identical empty Hashes' do
9
+ local = { }
10
+ remote = { }
11
+ output = []
12
+ differ = config_differ.new(local, remote)
13
+ expect(differ.diff).to eq(output)
14
+ end
15
+
16
+ it 'should return an empty array for two identical simple Hashes' do
17
+ local = { testing: 'testing', one: 1, two: 'two', three: "3" }
18
+ remote = { testing: 'testing', one: 1, two: 'two', three: "3" }
19
+ output = []
20
+ differ = config_differ.new(local, remote)
21
+ expect(differ.diff).to eq(output)
22
+ end
23
+
24
+ it 'should return an empty array for two identical deep Hashes' do
25
+ local = { testing: 'testing', one: 1, deep: [
26
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
27
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
28
+ ]}
29
+ remote = { testing: 'testing', one: 1, deep: [
30
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
31
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
32
+ ]}
33
+ output = []
34
+ differ = config_differ.new(local, remote)
35
+ expect(differ.diff).to eq(output)
36
+ end
37
+
38
+ it 'should highlight a simple addition' do
39
+ local = { foo: '1' }
40
+ remote = { foo: '1', bar: '2' }
41
+ output = [["+", "bar", "2"]]
42
+ differ = config_differ.new(local, remote)
43
+ expect(differ.diff).to eq(output)
44
+ end
45
+
46
+ it 'should highlight a simple subtraction' do
47
+ local = { foo: '1', bar: '2' }
48
+ remote = { foo: '1' }
49
+ output = [["-", "bar", "2"]]
50
+ differ = config_differ.new(local, remote)
51
+ expect(differ.diff).to eq(output)
52
+ end
53
+
54
+ it 'should highlight a deep addition' do
55
+ local = { testing: 'testing', one: 1, deep: [
56
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
57
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
58
+ ]}
59
+ remote = { testing: 'testing', one: 1, deep: [
60
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5, 6 ] },
61
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
62
+ ]}
63
+ output = [["+", "deep[0].deeper[5]", 6]]
64
+ differ = config_differ.new(local, remote)
65
+ expect(differ.diff).to eq(output)
66
+ end
67
+
68
+ it 'should highlight a deep subtraction' do
69
+ local = { testing: 'testing', one: 1, deep: [
70
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
71
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
72
+ ]}
73
+ remote = { testing: 'testing', one: 1, deep: [
74
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
75
+ { baz: 'bop', deeper: [ 6, 5, 3, 2 ] },
76
+ ]}
77
+ output = [["-", "deep[1].deeper[2]", 4]]
78
+ differ = config_differ.new(local, remote)
79
+ expect(differ.diff).to eq(output)
80
+ end
81
+
82
+ it 'should return an empty array when hash params are reordered' do
83
+ local = { one: 1, testing: 'testing', deep: [
84
+ { deeper: [ 1, 2, 3, 4, 5 ], foo: 'bar' },
85
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
86
+ ]}
87
+ remote = { testing: 'testing', one: 1, deep: [
88
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
89
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
90
+ ]}
91
+ output = []
92
+ differ = config_differ.new(local, remote)
93
+ expect(differ.diff).to eq(output)
94
+ end
95
+
96
+ it 'should highlight when array elements are reordered' do
97
+ local = { testing: 'testing', one: 1, deep: [
98
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
99
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
100
+ ]}
101
+ remote = { testing: 'testing', one: 1, deep: [
102
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
103
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
104
+ ]}
105
+ output = [
106
+ ["+", "deep[0]", {:foo=>"bar", :deeper=>[1, 2, 3, 4, 5]}],
107
+ ["-", "deep[2]", {:foo=>"bar", :deeper=>[1, 2, 3, 4, 5]}],
108
+ ]
109
+ differ = config_differ.new(local, remote)
110
+ expect(differ.diff).to eq(output)
111
+ end
112
+
113
+ it 'should highlight when deep array elements are reordered' do
114
+ local = { testing: 'testing', one: 1, deep: [
115
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
116
+ { baz: 'bop', deeper: [ 5, 6, 4, 3, 2 ] },
117
+ ]}
118
+ remote = { testing: 'testing', one: 1, deep: [
119
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
120
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
121
+ ]}
122
+ output = [
123
+ ["+", "deep[1].deeper[0]", 6],
124
+ ["-", "deep[1].deeper[2]", 6]
125
+ ]
126
+ differ = config_differ.new(local, remote)
127
+ expect(differ.diff).to eq(output)
128
+ end
129
+ end
130
+
131
+ end
132
+ end