Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

[#64589182] Ignoring Id parameter when diffing Nat and Firewall rules. #25

Merged
merged 18 commits into from

3 participants

Mike Pountney Anna Shipman Dan Abel
Mike Pountney

The automatically generated Id parameter would cause an issue with Diff display when inserting new Firewall or Nat rules - every rule following the insertion would have its Id incremented, and hence be 'different' (despite the content remaining the same).

This PR adds two new Differ classes: FirewallConfigurationDiffer and NatConfigurationDiffer

These strip out the Id field (in FirewallRule and NatRule sections) before comparison, and hence provide clean diff output.

mikepea added some commits
Mike Pountney mikepea Fix indentation in nat_service generator 0c16404
Mike Pountney mikepea DRY out differ tests before adding more classes
In anticipation of adding the Nat and Firewall differ classes
(to handle Id fields), DRY out the ConfigurationDiffer and
LoadBalancerConfigurationDiffer tests to have a common set
of test cases that we can use to ensure all differ classes are
obeying the same basic set of rules.
74b1568
Mike Pountney mikepea Add NatConfigurationDiffer class to ignore Id
When new nat_rules are inserted, the resulting generator output
dutifully increments the Id value of NatRules that follow.

This creates a problem when comparing with ConfigurationDiffer,
since the rules after our insertion have not changed, bar their
Id value increasing in relation to the new rules.

This commit adds a NatConfigurationDiffer class which strips out
these Id values before comparison.
daebc34
Mike Pountney mikepea Add missing newline from coverage message 7f2a309
Mike Pountney mikepea Add FirewallConfigurationDiffer class to ignore Id
(as per the NatConfigurationDiffer class in daebc34)

When new firewall_rules are inserted, the resulting generator output
dutifully increments the Id value of FirewallRules that follow.

This creates a problem when comparing with ConfigurationDiffer,
since the rules after our insertion have not changed, bar their
Id value increasing in relation to the new rules.

This commit adds a FirewallConfigurationDiffer class which strips out
these Id values before comparison.
7426b4f
Mike Pountney mikepea DRY out the ConfigurationDiffer classes
Make ConfigurationDiffer the parent of all per-service differs,
since they are all sharing common behaviour, just altering
what they consider to be 'the configuration for comparison'
ffb91aa
Anna Shipman
Owner

I'm not very happy with the use of inheritance or the abstracting of the test away from where the tests are being run... am thinking about whether to change it or merge it as is.

Anna Shipman
Owner

I'm going to make some changes to this.

annashipman added some commits
Anna Shipman annashipman Do inheritance in a clearer way
There's no need for code to be repeated in every subclass. The only thing that really needs to change is what the unused field is.

The difference between this and what was there before is that the unused field is stripped from both local and remote whereas in the case of the Load Balancer, it won't be in the local. This doesn't matter though, as there is a test for whether it's present before attemptint to remove it.
d27853c
Anna Shipman annashipman Artefacts of the way inheritance was being done 4119af6
Anna Shipman annashipman Simplify method calls to what is required 26b7269
Anna Shipman annashipman Remove common differ cases from subclass tests
The looping through test cases is bad (this will be explained more fully in the next commit). Removing them from the subclasses. They will later be reimplemented.
9faa82c
Anna Shipman annashipman Looped through tests are bad
Instead of failing, they just don't run if the circumstances aren't right. For example:
 - 0f29d67: one of tests wasn't running due to a very small typo
 - gds-operations/vcloud-core@ebd3305: the code they were testing is no longer present, so the tests just don't run; when I remove code that is tested, I expect the tests to fail.

This makes them fairly useless as tests. This commit reimplements the tests as actual tests. They only test the configuration differ file as this stage.
9883ea5
Anna Shipman annashipman Rewrite config differ subclass tests as tests
Rather than as loops, as per 9883ea5.
201ca87
Anna Shipman annashipman Make the config differ tests shared_examples
This will allow the subclasses to call the tests of the superclass without repeating all the tests. Also changed the name of the file to include to reflect what it now is.
187935b
Anna Shipman annashipman Pass the type of Configuration Differ
So that subclasses are testing themselves rather than all just testing ConfigurationDiffer again. `?w=1` will help to see the changes in this commit as I also fixed indenting.
9c4124c
Anna Shipman annashipman Make subclasses run the Config Differ tests bc8f32a
Anna Shipman
Owner

Hi @danielabel - I've rewritten this PR and it would be good if you could take a look. I know there are a lot of commits but hopefully it should be fairly straightforward.

I've done two things:

  1. Improved the inheritance of the Configuration Differs so they only implement the one thing that has to be different (ie which field to suppress when doing diffs).

  2. Reimplemented the tests, moving them away from the looping through a constant of test cases in another file (which is bad 9883ea5) and instead using shared_examples https://www.relishapp.com/rspec/rspec-core/v/2-11/docs/example-groups/shared-examples so the subclasses just say it_behaves_like "a configuration differ" to run all the configuration differ tests against that class.

spec/spec_helper.rb
@@ -20,7 +20,7 @@
# do not change the coverage percentage, instead add more unit tests to fix coverage failures.
if SimpleCov.result.covered_percent < 60
print "ERROR::BAD_COVERAGE\n"
- print "Coverage is less than acceptable limit(71%). Please add more tests to improve the coverage"
+ print "Coverage is less than acceptable limit(71%). Please add more tests to improve the coverage\n"

Not your fault, but it looks like the coverage got reduced on line 21 and it's not reflected in the copy - fix in this or do we need a pivotal ticket.

Anna Shipman Owner

I can go one better. See 1616c2d

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Anna Shipman annashipman I've added a lot of tests here
So coverage is higher. I'm not entirely convinced by this, because the tests were all in one area - it's clearly not testing lines of code or paths through the code. However, this is the tool we are using for coverage at the moment so might as well make use of it.
1616c2d
lib/vcloud/edge_gateway/configuration_differ.rb
@@ -8,7 +8,19 @@ def initialize local, remote
end
def diff
- ( @local == @remote ) ? [] : HashDiff.diff(@local, @remote)
+ ( stripped_local_config == stripped_remote_config ) ? [] : HashDiff.diff(stripped_local_config, stripped_remote_config)
+ end
+
+ def stripped_local_config
+ strip_unused_field_from_config(@local) unless @local.nil?
+ end
+
+ def stripped_remote_config
+ strip_unused_field_from_config(@remote) unless @remote.nil?
+ end
+
+ def strip_unused_field_from_config(config)

This method name threw us for 5 mins. We think that what it does is remove fields to be ignored for/excluded by the differ. Is that correct and is there a clearer method name that could be used?

Anna Shipman Owner

Very good point. How about remove_fields_for_differ_to_ignore? And to that end, do you think stripped_local_config and stripped_local_config are clear enough? Perhaps if I call the method strip_fields_for_differ_to_ignore?

We like both of your suggestions :+1:

Anna Shipman Owner

And it is so! cf9c995

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Dan Abel

general thoughts: we think this code is testing the ConfigurationDiffer three times, due to the nature of it using inheritance - needing to test once for each instance. It's good that we don't have those tests verbatim, or in a loop.

We considered the alternative of having a concrete differ that has exclude/ignore filter behaviour injected into it (composition style). We can see how that would be better if this were to scale any further, and might make the concerns in the tests clearer also.

We weren't sure if you had considered and dismissed this option, or if as the code is unlikely to scale past 3 instances it wasn't valued enough to re-implement in this way?

/cc @zoodor

Anna Shipman
Owner

Ha! Yes, I completely agree. I told Mike I wasn't a fan of inheritance and preferred composition, but he did it this way. I continued with inheritance because basically I am rewriting someone else's piece of work as he is now on paternity leave - arguably though I've made so many changes to his original work that I might as well have changed it entirely.

My feeling on this is that at this stage I don't want to put any extra time into this because of the points you make.

It's not exactly testing the ConfigurationDiffer three times though - it's testing that the subclass does the same things required of the superclass - a check worth putting in when inheritance is about...

Dan Abel

Super! :blossom:

Dan Abel danielabel merged commit 415ab46 into from
Dan Abel danielabel deleted the branch
Anna Shipman annashipman referenced this pull request from a commit
Anna Shipman annashipman Reduce coverage required
#25 increased the coverage required dramatically from 60% to 95%, which is fine when running unit tests, but when integration tests are run, it's not enough.

I am not convinced of the value of this coverage tool, so I am working around this problem by reducing the coverage I claim to have.
1845980
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 6, 2014
  1. Mike Pountney
  2. Mike Pountney

    DRY out differ tests before adding more classes

    mikepea authored
    In anticipation of adding the Nat and Firewall differ classes
    (to handle Id fields), DRY out the ConfigurationDiffer and
    LoadBalancerConfigurationDiffer tests to have a common set
    of test cases that we can use to ensure all differ classes are
    obeying the same basic set of rules.
  3. Mike Pountney

    Add NatConfigurationDiffer class to ignore Id

    mikepea authored
    When new nat_rules are inserted, the resulting generator output
    dutifully increments the Id value of NatRules that follow.
    
    This creates a problem when comparing with ConfigurationDiffer,
    since the rules after our insertion have not changed, bar their
    Id value increasing in relation to the new rules.
    
    This commit adds a NatConfigurationDiffer class which strips out
    these Id values before comparison.
  4. Mike Pountney
  5. Mike Pountney

    Add FirewallConfigurationDiffer class to ignore Id

    mikepea authored
    (as per the NatConfigurationDiffer class in daebc34)
    
    When new firewall_rules are inserted, the resulting generator output
    dutifully increments the Id value of FirewallRules that follow.
    
    This creates a problem when comparing with ConfigurationDiffer,
    since the rules after our insertion have not changed, bar their
    Id value increasing in relation to the new rules.
    
    This commit adds a FirewallConfigurationDiffer class which strips out
    these Id values before comparison.
  6. Mike Pountney

    DRY out the ConfigurationDiffer classes

    mikepea authored
    Make ConfigurationDiffer the parent of all per-service differs,
    since they are all sharing common behaviour, just altering
    what they consider to be 'the configuration for comparison'
Commits on Mar 11, 2014
  1. Anna Shipman
Commits on Mar 14, 2014
  1. Anna Shipman

    Do inheritance in a clearer way

    annashipman authored
    There's no need for code to be repeated in every subclass. The only thing that really needs to change is what the unused field is.
    
    The difference between this and what was there before is that the unused field is stripped from both local and remote whereas in the case of the Load Balancer, it won't be in the local. This doesn't matter though, as there is a test for whether it's present before attemptint to remove it.
  2. Anna Shipman
  3. Anna Shipman
  4. Anna Shipman

    Remove common differ cases from subclass tests

    annashipman authored
    The looping through test cases is bad (this will be explained more fully in the next commit). Removing them from the subclasses. They will later be reimplemented.
  5. Anna Shipman

    Looped through tests are bad

    annashipman authored
    Instead of failing, they just don't run if the circumstances aren't right. For example:
     - 0f29d67: one of tests wasn't running due to a very small typo
     - gds-operations/vcloud-core@ebd3305: the code they were testing is no longer present, so the tests just don't run; when I remove code that is tested, I expect the tests to fail.
    
    This makes them fairly useless as tests. This commit reimplements the tests as actual tests. They only test the configuration differ file as this stage.
  6. Anna Shipman

    Rewrite config differ subclass tests as tests

    annashipman authored
    Rather than as loops, as per 9883ea5.
Commits on Mar 16, 2014
  1. Anna Shipman

    Make the config differ tests shared_examples

    annashipman authored
    This will allow the subclasses to call the tests of the superclass without repeating all the tests. Also changed the name of the file to include to reflect what it now is.
  2. Anna Shipman

    Pass the type of Configuration Differ

    annashipman authored
    So that subclasses are testing themselves rather than all just testing ConfigurationDiffer again. `?w=1` will help to see the changes in this commit as I also fixed indenting.
  3. Anna Shipman
Commits on Mar 18, 2014
  1. Anna Shipman

    I've added a lot of tests here

    annashipman authored
    So coverage is higher. I'm not entirely convinced by this, because the tests were all in one area - it's clearly not testing lines of code or paths through the code. However, this is the tool we are using for coverage at the moment so might as well make use of it.
  2. Anna Shipman
This page is out of date. Refresh to see the latest.
2  lib/vcloud/edge_gateway.rb
View
@@ -15,6 +15,8 @@
require 'vcloud/edge_gateway/configuration_generator/nat_service'
require 'vcloud/edge_gateway/configuration_generator/load_balancer_service'
require 'vcloud/edge_gateway/configuration_differ'
+require 'vcloud/edge_gateway/nat_configuration_differ'
+require 'vcloud/edge_gateway/firewall_configuration_differ'
require 'vcloud/edge_gateway/load_balancer_configuration_differ'
require 'vcloud/edge_gateway/edge_gateway_configuration'
14 lib/vcloud/edge_gateway/configuration_differ.rb
View
@@ -8,7 +8,19 @@ def initialize local, remote
end
def diff
- ( @local == @remote ) ? [] : HashDiff.diff(@local, @remote)
+ ( stripped_local_config == stripped_remote_config ) ? [] : HashDiff.diff(stripped_local_config, stripped_remote_config)
+ end
+
+ def stripped_local_config
+ strip_fields_for_differ_to_ignore(@local) unless @local.nil?
+ end
+
+ def stripped_remote_config
+ strip_fields_for_differ_to_ignore(@remote) unless @remote.nil?
+ end
+
+ def strip_fields_for_differ_to_ignore(config)
+ config
end
end
20 lib/vcloud/edge_gateway/configuration_generator/nat_service.rb
View
@@ -19,16 +19,16 @@ def generate_fog_config
def populate_nat_rules
rules = @input_config[:nat_rules]
- i = ID_RANGES::NAT_SERVICE[:min]
- rules.collect do |rule|
- new_rule = {}
- new_rule[:Id] = rule.key?(:id) ? rule[:id] : i.to_s
- new_rule[:IsEnabled] = rule.key?(:enabled) ? rule[:enabled].to_s : 'true'
- new_rule[:RuleType] = rule[:rule_type]
- gateway_nat_rule = populate_gateway_nat_rule(rule)
- new_rule[:GatewayNatRule] = gateway_nat_rule
- i += 1
- new_rule
+ i = ID_RANGES::NAT_SERVICE[:min]
+ rules.collect do |rule|
+ new_rule = {}
+ new_rule[:Id] = rule.key?(:id) ? rule[:id] : i.to_s
+ new_rule[:IsEnabled] = rule.key?(:enabled) ? rule[:enabled].to_s : 'true'
+ new_rule[:RuleType] = rule[:rule_type]
+ gateway_nat_rule = populate_gateway_nat_rule(rule)
+ new_rule[:GatewayNatRule] = gateway_nat_rule
+ i += 1
+ new_rule
end
end
4 lib/vcloud/edge_gateway/edge_gateway_configuration.rb
View
@@ -15,7 +15,7 @@ def update_required?
firewall_service_config = EdgeGateway::ConfigurationGenerator::FirewallService.new.generate_fog_config(@local_config[:firewall_service])
unless firewall_service_config.nil?
- differ = EdgeGateway::ConfigurationDiffer.new(firewall_service_config, @remote_config[:FirewallService])
+ differ = EdgeGateway::FirewallConfigurationDiffer.new(firewall_service_config, @remote_config[:FirewallService])
unless differ.diff.empty?
@config[:FirewallService] = firewall_service_config
@update_required = true
@@ -28,7 +28,7 @@ def update_required?
).generate_fog_config
unless nat_service_config.nil?
- differ = EdgeGateway::ConfigurationDiffer.new(nat_service_config, @remote_config[:NatService])
+ differ = EdgeGateway::NatConfigurationDiffer.new(nat_service_config, @remote_config[:NatService])
unless differ.diff.empty?
@config[:NatService] = nat_service_config
@update_required = true
18 lib/vcloud/edge_gateway/firewall_configuration_differ.rb
View
@@ -0,0 +1,18 @@
+module Vcloud
+ module EdgeGateway
+ class FirewallConfigurationDiffer < ConfigurationDiffer
+
+ def strip_fields_for_differ_to_ignore(config)
+ deep_cloned_config = Marshal.load( Marshal.dump(config) )
+ if deep_cloned_config.key?(:FirewallRule)
+ deep_cloned_config[:FirewallRule].each do |firewall_rule|
+ firewall_rule.delete(:Id)
+ end
+ end
+ deep_cloned_config
+ end
+
+ end
+ end
+
+end
16 lib/vcloud/edge_gateway/load_balancer_configuration_differ.rb
View
@@ -1,19 +1,9 @@
module Vcloud
module EdgeGateway
- class LoadBalancerConfigurationDiffer
+ class LoadBalancerConfigurationDiffer < ConfigurationDiffer
- def initialize local, remote
- @local = local
- @remote = remote
- end
-
- def diff
- ( @local == stripped_remote_config ) ? [] : HashDiff.diff(@local, stripped_remote_config)
- end
-
- def stripped_remote_config
- return nil if @remote.nil?
- deep_cloned_remote_config = Marshal.load( Marshal.dump(@remote) )
+ def strip_fields_for_differ_to_ignore(config)
+ deep_cloned_remote_config = Marshal.load( Marshal.dump(config) )
if deep_cloned_remote_config.key?(:Pool)
deep_cloned_remote_config[:Pool].each do |pool_entry|
pool_entry.delete(:Operational)
18 lib/vcloud/edge_gateway/nat_configuration_differ.rb
View
@@ -0,0 +1,18 @@
+module Vcloud
+ module EdgeGateway
+ class NatConfigurationDiffer < ConfigurationDiffer
+
+ def strip_fields_for_differ_to_ignore(config)
+ deep_cloned_config = Marshal.load( Marshal.dump(config) )
+ if deep_cloned_config.key?(:NatRule)
+ deep_cloned_config[:NatRule].each do |nat_rule|
+ nat_rule.delete(:Id)
+ end
+ end
+ deep_cloned_config
+ end
+
+ end
+ end
+
+end
4 spec/spec_helper.rb
View
@@ -18,9 +18,9 @@
SimpleCov.at_exit do
SimpleCov.result.format!
# do not change the coverage percentage, instead add more unit tests to fix coverage failures.
- if SimpleCov.result.covered_percent < 60
+ if SimpleCov.result.covered_percent < 95
print "ERROR::BAD_COVERAGE\n"
- print "Coverage is less than acceptable limit(71%). Please add more tests to improve the coverage"
+ print "Coverage is less than acceptable limit(95%). Please add more tests to improve the coverage\n"
exit(1)
end
end
132 spec/vcloud/edge_gateway/configuration_differ_shared_examples.rb
View
@@ -0,0 +1,132 @@
+module Vcloud
+ module EdgeGateway
+
+ shared_examples "a configuration differ" do
+
+ let(:config_differ) { described_class }
+
+ it 'should return an empty array for two identical empty Hashes' do
+ local = { }
+ remote = { }
+ output = []
+ differ = config_differ.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should return an empty array for two identical simple Hashes' do
+ local = { testing: 'testing', one: 1, two: 'two', three: "3" }
+ remote = { testing: 'testing', one: 1, two: 'two', three: "3" }
+ output = []
+ differ = config_differ.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should return an empty array for two identical deep Hashes' do
+ local = { testing: 'testing', one: 1, deep: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
+ ]}
+ remote = { testing: 'testing', one: 1, deep: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
+ ]}
+ output = []
+ differ = config_differ.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should highlight a simple addition' do
+ local = { foo: '1' }
+ remote = { foo: '1', bar: '2' }
+ output = [["+", "bar", "2"]]
+ differ = config_differ.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should highlight a simple subtraction' do
+ local = { foo: '1', bar: '2' }
+ remote = { foo: '1' }
+ output = [["-", "bar", "2"]]
+ differ = config_differ.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should highlight a deep addition' do
+ local = { testing: 'testing', one: 1, deep: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
+ ]}
+ remote = { testing: 'testing', one: 1, deep: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5, 6 ] },
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
+ ]}
+ output = [["+", "deep[0].deeper[5]", 6]]
+ differ = config_differ.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should highlight a deep subtraction' do
+ local = { testing: 'testing', one: 1, deep: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
+ ]}
+ remote = { testing: 'testing', one: 1, deep: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 6, 5, 3, 2 ] },
+ ]}
+ output = [["-", "deep[1].deeper[2]", 4]]
+ differ = config_differ.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should return an empty array when hash params are reordered' do
+ local = { one: 1, testing: 'testing', deep: [
+ { deeper: [ 1, 2, 3, 4, 5 ], foo: 'bar' },
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
+ ]}
+ remote = { testing: 'testing', one: 1, deep: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
+ ]}
+ output = []
+ differ = config_differ.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should highlight when array elements are reordered' do
+ local = { testing: 'testing', one: 1, deep: [
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ ]}
+ remote = { testing: 'testing', one: 1, deep: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
+ ]}
+ output = [
+ ["+", "deep[0]", {:foo=>"bar", :deeper=>[1, 2, 3, 4, 5]}],
+ ["-", "deep[2]", {:foo=>"bar", :deeper=>[1, 2, 3, 4, 5]}],
+ ]
+ differ = config_differ.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should highlight when deep array elements are reordered' do
+ local = { testing: 'testing', one: 1, deep: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 5, 6, 4, 3, 2 ] },
+ ]}
+ remote = { testing: 'testing', one: 1, deep: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
+ ]}
+ output = [
+ ["+", "deep[1].deeper[0]", 6],
+ ["-", "deep[1].deeper[2]", 6]
+ ]
+ differ = config_differ.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+ end
+
+ end
+end
127 spec/vcloud/edge_gateway/configuration_differ_spec.rb
View
@@ -1,131 +1,14 @@
require 'spec_helper'
+require_relative 'configuration_differ_shared_examples'
module Vcloud
module EdgeGateway
- describe ConfigurationDiffer do
-
- test_cases = [
- {
- title: 'should return an empty array for two identical empty Hashes',
- src: { },
- dest: { },
- output: [],
- },
-
- {
- title: 'should return an empty array for two identical simple Hashes',
- src: { testing: 'testing', one: 1, two: 'two', three: "3" },
- dest: { testing: 'testing', one: 1, two: 'two', three: "3" },
- output: [],
- },
-
- {
- title: 'should return an empty array for two identical deep Hashes',
- src: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [],
- },
-
- {
- title: 'should highlight a simple addition',
- src: { foo: '1' },
- dest: { foo: '1', bar: '2' },
- output: [["+", "bar", "2"]],
- },
-
- {
- title: 'should highlight a simple subtraction',
- src: { foo: '1', bar: '2' },
- dest: { foo: '1' },
- output: [["-", "bar", "2"]],
- },
-
- {
- title: 'should highlight a deep addition',
- src: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5, 6 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [["+", "deep[0].deeper[5]", 6]],
- },
-
- {
- title: 'should highlight a deep subtraction',
- src: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 3, 2 ] },
- ]},
- output: [["-", "deep[1].deeper[2]", 4]],
- },
- {
- title: 'should return an empty array when hash params are reordered',
- src: { one: 1, testing: 'testing', deep: [
- { deeper: [ 1, 2, 3, 4, 5 ], foo: 'bar' },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [],
- },
-
- {
- title: 'should highlight when array elements are reordered',
- src: { testing: 'testing', one: 1, deep: [
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [
- ["+", "deep[0]", {:foo=>"bar", :deeper=>[1, 2, 3, 4, 5]}],
- ["-", "deep[2]", {:foo=>"bar", :deeper=>[1, 2, 3, 4, 5]}],
- ]
- },
-
- {
- title: 'should highlight when deep array elements are reordered',
- src: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 5, 6, 4, 3, 2 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [
- ["+", "deep[1].deeper[0]", 6],
- ["-", "deep[1].deeper[2]", 6]
- ]
- },
-
- ]
-
- test_cases.each do |test_case|
- it "#{test_case[:title]}" do
- differ = ConfigurationDiffer.new(test_case[:src], test_case[:dest])
- expect(differ.diff).to eq(test_case[:output])
- end
+ describe ConfigurationDiffer do
+ it_behaves_like "a configuration differ" do
+ let(:config_differ) { ConfigurationDiffer }
end
-
end
+
end
end
65 spec/vcloud/edge_gateway/firewall_configuration_differ_spec.rb
View
@@ -0,0 +1,65 @@
+require 'spec_helper'
+require_relative 'configuration_differ_shared_examples.rb'
+
+module Vcloud
+ module EdgeGateway
+ describe FirewallConfigurationDiffer do
+
+ it_behaves_like "a configuration differ" do
+ let(:config_differ) { FirewallConfigurationDiffer }
+ end
+
+ it 'should ignore Id parameters in FirewallRule sections, when showing additions' do
+ local = { FirewallRule: [
+ { Id: '1', deeper: [ 1, 2, 3, 4, 5 ] },
+ { Id: '2', deeper: [ 5, 6, 4, 3, 2 ] },
+ ]}
+ remote = { FirewallRule: [
+ { Id: '1', deeper: [ 1, 1, 1, 1, 1 ] },
+ { Id: '2', deeper: [ 1, 2, 3, 4, 5 ] },
+ { Id: '3', deeper: [ 5, 6, 4, 3, 2 ] },
+ ]}
+ output = [
+ ["+", "FirewallRule[0]", {:deeper=>[1, 1, 1, 1, 1]}]
+ ]
+ differ = FirewallConfigurationDiffer.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should still highlight a reordering despite ignoring Id' do
+ local = { FirewallRule: [
+ { Id: '1', deeper: [ 1, 1, 1, 1, 1 ] },
+ { Id: '2', deeper: [ 1, 2, 3, 4, 5 ] },
+ { Id: '3', deeper: [ 5, 6, 4, 3, 2 ] },
+ ]}
+ remote = { FirewallRule: [
+ { Id: '1', deeper: [ 1, 2, 3, 4, 5 ] },
+ { Id: '2', deeper: [ 5, 6, 4, 3, 2 ] },
+ { Id: '3', deeper: [ 1, 1, 1, 1, 1 ] },
+ ]}
+ output = [
+ ["-", "FirewallRule[0]", {:deeper=>[1, 1, 1, 1, 1]}],
+ ["+", "FirewallRule[2]", {:deeper=>[1, 1, 1, 1, 1]}],
+ ]
+ differ = FirewallConfigurationDiffer.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should not ignore Id parameter outside of a FirewallRule (just in case)' do
+ local = {
+ FirewallRule: [ { Id: '1', deeper: [ 1, 1, 1, 1, 1 ] } ],
+ Id: 'outside of firewall rule'
+ }
+ remote = {
+ FirewallRule: [ { Id: '1', deeper: [ 1, 1, 1, 1, 1 ] } ],
+ }
+ output = [
+ ["-", "Id", 'outside of firewall rule']
+ ]
+ differ = FirewallConfigurationDiffer.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ end
+ end
+end
179 spec/vcloud/edge_gateway/load_balancer_configuration_differ_spec.rb
View
@@ -1,158 +1,43 @@
require 'spec_helper'
+require_relative 'configuration_differ_shared_examples.rb'
module Vcloud
module EdgeGateway
describe LoadBalancerConfigurationDiffer do
- test_cases = [
- {
- title: 'should return an empty array for two identical empty Hashes',
- src: { },
- dest: { },
- output: [],
- },
-
- {
- title: 'should return an empty array for two identical simple Hashes',
- src: { testing: 'testing', one: 1, two: 'two', three: "3" },
- dest: { testing: 'testing', one: 1, two: 'two', three: "3" },
- output: [],
- },
-
- {
- title: 'should return an empty array for two identical deep Hashes',
- src: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [],
- },
-
- {
- title: 'should highlight a simple addition',
- src: { foo: '1' },
- dest: { foo: '1', bar: '2' },
- output: [["+", "bar", "2"]],
- },
-
- {
- title: 'should highlight a simple subtraction',
- src: { foo: '1', bar: '2' },
- dest: { foo: '1' },
- output: [["-", "bar", "2"]],
- },
-
- {
- title: 'should highlight a deep addition',
- src: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5, 6 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [["+", "deep[0].deeper[5]", 6]],
- },
-
- {
- title: 'should highlight a deep subtraction',
- src: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 3, 2 ] },
- ]},
- output: [["-", "deep[1].deeper[2]", 4]],
- },
-
- {
- title: 'should return an empty array when hash params are reordered',
- src: { one: 1, testing: 'testing', deep: [
- { deeper: [ 1, 2, 3, 4, 5 ], foo: 'bar' },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [],
- },
-
- {
- title: 'should highlight when array elements are reordered',
- src: { testing: 'testing', one: 1, deep: [
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [
- ["+", "deep[0]", {:foo=>"bar", :deeper=>[1, 2, 3, 4, 5]}],
- ["-", "deep[2]", {:foo=>"bar", :deeper=>[1, 2, 3, 4, 5]}],
- ]
- },
-
- {
- title: 'should highlight when deep array elements are reordered',
- src: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 5, 6, 4, 3, 2 ] },
- ]},
- dest: { testing: 'testing', one: 1, deep: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [
- ["+", "deep[1].deeper[0]", 6],
- ["-", "deep[1].deeper[2]", 6]
- ]
- },
-
- {
- title: 'should ignore remote config having additional :Operational keys in :Pool entries',
- src: { Pool: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 5, 6, 4, 3, 2 ] },
- ]},
- dest: { Pool: [
- { foo: 'bar', Operational: 'wibble', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', Operational: 'wobble', deeper: [ 5, 6, 4, 3, 2 ] },
- ]},
- output: []
- },
-
- {
- title: 'should ignore remote config having additional :Operational keys in :Pool entries, yet still report other differences ',
- src: { Pool: [
- { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', deeper: [ 5, 6, 4, 3, 2 ] },
- ]},
- dest: { Pool: [
- { foo: 'bar', Operational: 'wibble', deeper: [ 1, 2, 3, 4, 5 ] },
- { baz: 'bop', Operational: 'wobble', deeper: [ 6, 5, 4, 3, 2 ] },
- ]},
- output: [
- ["+", "Pool[1].deeper[0]", 6],
- ["-", "Pool[1].deeper[2]", 6]
- ]
- },
+ it_behaves_like "a configuration differ" do
+ let(:config_differ) { LoadBalancerConfigurationDiffer }
+ end
- ]
+ it 'should ignore remote config having additional :Operational keys in :Pool entries' do
+ local = { Pool: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 5, 6, 4, 3, 2 ] },
+ ]}
+ remote = { Pool: [
+ { foo: 'bar', Operational: 'wibble', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', Operational: 'wobble', deeper: [ 5, 6, 4, 3, 2 ] },
+ ]}
+ output = []
+ differ = LoadBalancerConfigurationDiffer.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
- test_cases.each do |test_case|
- it "#{test_case[:title]}" do
- differ = LoadBalancerConfigurationDiffer.new(test_case[:src], test_case[:dest])
- expect(differ.diff).to eq(test_case[:output])
- end
+ it 'should ignore remote config having additional :Operational keys in :Pool entries, yet still report other differences' do
+ local = { Pool: [
+ { foo: 'bar', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', deeper: [ 5, 6, 4, 3, 2 ] },
+ ]}
+ remote = { Pool: [
+ { foo: 'bar', Operational: 'wibble', deeper: [ 1, 2, 3, 4, 5 ] },
+ { baz: 'bop', Operational: 'wobble', deeper: [ 6, 5, 4, 3, 2 ] },
+ ]}
+ output = [
+ ["+", "Pool[1].deeper[0]", 6],
+ ["-", "Pool[1].deeper[2]", 6]
+ ]
+ differ = LoadBalancerConfigurationDiffer.new(local, remote)
+ expect(differ.diff).to eq(output)
end
end
65 spec/vcloud/edge_gateway/nat_configuration_differ_spec.rb
View
@@ -0,0 +1,65 @@
+require 'spec_helper'
+require_relative 'configuration_differ_shared_examples.rb'
+
+module Vcloud
+ module EdgeGateway
+ describe NatConfigurationDiffer do
+
+ it_behaves_like "a configuration differ" do
+ let(:config_differ) { NatConfigurationDiffer }
+ end
+
+ it 'should ignore Id parameters in NatRule sections, when showing additions' do
+ local = { NatRule: [
+ { Id: '65539', deeper: [ 1, 2, 3, 4, 5 ] },
+ { Id: '65540', deeper: [ 5, 6, 4, 3, 2 ] },
+ ]}
+ remote = { NatRule: [
+ { Id: '65539', deeper: [ 1, 1, 1, 1, 1 ] },
+ { Id: '65540', deeper: [ 1, 2, 3, 4, 5 ] },
+ { Id: '65541', deeper: [ 5, 6, 4, 3, 2 ] },
+ ]}
+ output = [
+ ["+", "NatRule[0]", {:deeper=>[1, 1, 1, 1, 1]}]
+ ]
+ differ = NatConfigurationDiffer.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should still highlight a reordering despite ignoring Id' do
+ local = { NatRule: [
+ { Id: '65538', deeper: [ 1, 1, 1, 1, 1 ] },
+ { Id: '65539', deeper: [ 1, 2, 3, 4, 5 ] },
+ { Id: '65540', deeper: [ 5, 6, 4, 3, 2 ] },
+ ]}
+ remote = { NatRule: [
+ { Id: '65538', deeper: [ 1, 2, 3, 4, 5 ] },
+ { Id: '65539', deeper: [ 5, 6, 4, 3, 2 ] },
+ { Id: '65540', deeper: [ 1, 1, 1, 1, 1 ] },
+ ]}
+ output = [
+ ["-", "NatRule[0]", {:deeper=>[1, 1, 1, 1, 1]}],
+ ["+", "NatRule[2]", {:deeper=>[1, 1, 1, 1, 1]}],
+ ]
+ differ = NatConfigurationDiffer.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ it 'should not ignore Id parameter outside of a NatRule (just in case)' do
+ local = {
+ NatRule: [ { Id: '65538', deeper: [ 1, 1, 1, 1, 1 ] } ],
+ Id: 'outside of NAT rule'
+ }
+ remote = {
+ NatRule: [ { Id: '65538', deeper: [ 1, 1, 1, 1, 1 ] } ],
+ }
+ output = [
+ ["-", "Id", 'outside of NAT rule']
+ ]
+ differ = NatConfigurationDiffer.new(local, remote)
+ expect(differ.diff).to eq(output)
+ end
+
+ end
+ end
+end
Something went wrong with that request. Please try again.