-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
INFRA-3218 Initial commit of boolean comparators
Initial commit of greater_than, equal_or_greater_than, equal_to, equal_or_less_than, and less_than comparator functions and their unit tests.
- Loading branch information
1 parent
ed615a9
commit 28f5ed7
Showing
10 changed files
with
394 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'ipaddr' | ||
|
||
Puppet::Functions.create_function(:"ipcalc::equal_or_greater_than") do | ||
# Compare two IP addresses and return a Boolean indicating whether the first operand is equal to | ||
# (or possibly greater than) the second. Contextually, this makes the most sense when using | ||
# Puppet's dotted function notation, because the function name sits where a comparison operator | ||
# would normally go. This will work with either plain addresses or CIDR-notation addresses; if a | ||
# plain address is supplied, a full-width netmask is assumed. That is, '127.0.0.1' and | ||
# '127.0.0.1/32' are equivalent, just as 'fe80::1' and 'fe80::1/128' are equivalent. The netmask | ||
# IS assessed in the comparison, but is only relevant if the remainder of the address is exactly | ||
# equivalent down to the start of the netmask. If addresses of mixed families are given, an error | ||
# is raised and the catalog will fail. There is no obvious implied relation between the two, and | ||
# even the underlying Ruby implementation will refuse to make comparisons between addresses of | ||
# different families. | ||
# @param first | ||
# The first address for comparison. If no netmask is given, full-width is assumed. | ||
# @param second | ||
# The second address for comparison. If no netmask is given, full-width is assumed. | ||
# @return [Boolean] | ||
# `true` if the first operand is equal to (or greater than) the second, or `false` if it's less | ||
# than the second. | ||
# @example Use with dotted function notation | ||
# $first_ip.equal_or_greater_than($second_ip) ? { | ||
# true => { 'We did it, go team, first operand is equal or bigger' }, | ||
# default => { 'I\'m afraid I have some bad news...' }, | ||
# } | ||
dispatch :equal_or_greater_than do | ||
param 'Stdlib::IP::Address::V4', :first | ||
param 'Stdlib::IP::Address::V4', :second | ||
return_type 'Boolean' | ||
end | ||
|
||
dispatch :equal_or_greater_than do | ||
param 'Stdlib::IP::Address::V6', :first | ||
param 'Stdlib::IP::Address::V6', :second | ||
return_type 'Boolean' | ||
end | ||
|
||
# Refuse to handle addresses in different families. There isn't a clear precedence between the | ||
# two families; if you need to establish an order, you can use type comparison to handle this in | ||
# your Puppet code. | ||
argument_mismatch :mixed_families do | ||
param 'Stdlib::IP::Address::V4', :first | ||
param 'Stdlib::IP::Address::V6', :second | ||
end | ||
|
||
argument_mismatch :mixed_families do | ||
param 'Stdlib::IP::Address::V6', :first | ||
param 'Stdlib::IP::Address::V4', :second | ||
end | ||
|
||
def equal_or_greater_than(first, second) | ||
first_addr = IPAddr.new(first) | ||
second_addr = IPAddr.new(second) | ||
|
||
first_addr >= second_addr | ||
end | ||
|
||
def mixed_families(*) | ||
'both addresses must be in the same family' | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'ipaddr' | ||
|
||
Puppet::Functions.create_function(:"ipcalc::equal_or_less_than") do | ||
# Compare two IP addresses and return a Boolean indicating whether the first operand is equal to | ||
# (or possibly less than) the second. Contextually, this makes the most sense when using | ||
# Puppet's dotted function notation, because the function name sits where a comparison operator | ||
# would normally go. This will work with either plain addresses or CIDR-notation addresses; if a | ||
# plain address is supplied, a full-width netmask is assumed. That is, '127.0.0.1' and | ||
# '127.0.0.1/32' are equivalent, just as 'fe80::1' and 'fe80::1/128' are equivalent. The netmask | ||
# IS assessed in the comparison, but is only relevant if the remainder of the address is exactly | ||
# equivalent down to the start of the netmask. If addresses of mixed families are given, an error | ||
# is raised and the catalog will fail. There is no obvious implied relation between the two, and | ||
# even the underlying Ruby implementation will refuse to make comparisons between addresses of | ||
# different families. | ||
# @param first | ||
# The first address for comparison. If no netmask is given, full-width is assumed. | ||
# @param second | ||
# The second address for comparison. If no netmask is given, full-width is assumed. | ||
# @return [Boolean] | ||
# `true` if the first operand is equal to (or less than) the second, or `false` if it's greater | ||
# than the second. | ||
# @example Use with dotted function notation | ||
# $first_ip.equal_or_less_than($second_ip) ? { | ||
# true => { 'We did it, go team, first operand is equal or smaller' }, | ||
# default => { 'I\'m afraid I have some bad news...' }, | ||
# } | ||
dispatch :equal_or_less_than do | ||
param 'Stdlib::IP::Address::V4', :first | ||
param 'Stdlib::IP::Address::V4', :second | ||
return_type 'Boolean' | ||
end | ||
|
||
dispatch :equal_or_less_than do | ||
param 'Stdlib::IP::Address::V6', :first | ||
param 'Stdlib::IP::Address::V6', :second | ||
return_type 'Boolean' | ||
end | ||
|
||
# Refuse to handle addresses in different families. There isn't a clear precedence between the | ||
# two families; if you need to establish an order, you can use type comparison to handle this in | ||
# your Puppet code. | ||
argument_mismatch :mixed_families do | ||
param 'Stdlib::IP::Address::V4', :first | ||
param 'Stdlib::IP::Address::V6', :second | ||
end | ||
|
||
argument_mismatch :mixed_families do | ||
param 'Stdlib::IP::Address::V6', :first | ||
param 'Stdlib::IP::Address::V4', :second | ||
end | ||
|
||
def equal_or_less_than(first, second) | ||
first_addr = IPAddr.new(first) | ||
second_addr = IPAddr.new(second) | ||
|
||
first_addr <= second_addr | ||
end | ||
|
||
def mixed_families(*) | ||
'both addresses must be in the same family' | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'ipaddr' | ||
|
||
Puppet::Functions.create_function(:"ipcalc::equal_to") do | ||
# Compare two IP addresses and return a Boolean indicating whether the first operand is equal to | ||
# the second. This differs from comparing the address Strings in that it compares native 32-bit | ||
# (or for IPv6, 128-bit) binary values, regardless of their human-readable representations. For | ||
# IPv4 addresses this is usually not much of a problem, as representations are simpler and | ||
# zero-padded values are relatively rare (enough that Stdlib::IP::Address::V4 filters them out as | ||
# invalid). For IPv6 addresses, however, IPv6's collapsed notation can be a very serious problem, | ||
# and this function allows IPv6 addresses with un-collapsed runs of zeroes, leading zeroes, etc. | ||
# to be compared meaningfully without needing to worry about normalizing their human-readable | ||
# representations first. | ||
# | ||
# Contextually, this function makes the most sense when using Puppet's dotted function notation, | ||
# because the function name sits where a comparison operator would normally go. This will work | ||
# with either plain addresses or CIDR-notation addresses; if a plain address is supplied, a | ||
# full-width netmask is assumed. That is, '127.0.0.1' and '127.0.0.1/32' are equivalent, just as | ||
# 'fe80::1' and 'fe80::1/128' are equivalent. The netmask IS assessed in the comparison, but is | ||
# only relevant if the remainder of the address is exactly equivalent down to the start of the | ||
# netmask. Addresses of mixed families are always considered unequal. | ||
# @param first | ||
# The first address for comparison. If no netmask is given, full-width is assumed. | ||
# @param second | ||
# The second address for comparison. If no netmask is given, full-width is assumed. | ||
# @return [Boolean] | ||
# `true` if the operands are equal, or `false` otherwise. | ||
# @example Use with dotted function notation | ||
# $first_ip.equal_to($second_ip) ? { | ||
# true => { 'We did it, go team, the operands are equal' }, | ||
# default => { 'I\'m afraid I have some bad news...' }, | ||
# } | ||
dispatch :equal_to do | ||
param 'Stdlib::IP::Address::V4', :first | ||
param 'Stdlib::IP::Address::V4', :second | ||
return_type 'Boolean' | ||
end | ||
|
||
dispatch :equal_to do | ||
param 'Stdlib::IP::Address::V6', :first | ||
param 'Stdlib::IP::Address::V6', :second | ||
return_type 'Boolean' | ||
end | ||
|
||
dispatch :mixed_families do | ||
param 'Stdlib::IP::Address::V4', :first | ||
param 'Stdlib::IP::Address::V6', :second | ||
end | ||
|
||
dispatch :mixed_families do | ||
param 'Stdlib::IP::Address::V6', :first | ||
param 'Stdlib::IP::Address::V4', :second | ||
end | ||
|
||
def equal_to(first, second) | ||
first_addr = IPAddr.new(first) | ||
second_addr = IPAddr.new(second) | ||
|
||
first_addr == second_addr | ||
end | ||
|
||
def mixed_families(*) | ||
false | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'ipaddr' | ||
|
||
Puppet::Functions.create_function(:"ipcalc::greater_than") do | ||
# Compare two IP addresses and return a Boolean indicating whether the first operand is greater | ||
# than the second. Contextually, this makes the most sense when using Puppet's dotted function | ||
# notation, because the function name sits where a comparison operator would normally go. This | ||
# will work with either plain addresses or CIDR-notation addresses; if a plain address is | ||
# supplied, a full-width netmask is assumed. That is, '127.0.0.1' and '127.0.0.1/32' are | ||
# equivalent, just as 'fe80::1' and 'fe80::1/128' are equivalent. The netmask IS assessed in the | ||
# comparison, but is only relevant if the remainder of the address is exactly equivalent down to | ||
# the start of the netmask. If addresses of mixed families are given, an error is raised and the | ||
# catalog will fail. There is no obvious implied relation between the two, and even the | ||
# underlying Ruby implementation will refuse to make comparisons between addresses of different | ||
# families. | ||
# @param first | ||
# The first address for comparison. If no netmask is given, full-width is assumed. | ||
# @param second | ||
# The second address for comparison. If no netmask is given, full-width is assumed. | ||
# @return [Boolean] | ||
# `true` if the first operand is greater than the second, or `false` otherwise. | ||
# @example Use with dotted function notation | ||
# $first_ip.greater_than($second_ip) ? { | ||
# true => { 'We did it, go team, first operand is bigger' }, | ||
# default => { 'I\'m afraid I have some bad news...' }, | ||
# } | ||
dispatch :greater_than do | ||
param 'Stdlib::IP::Address::V4', :first | ||
param 'Stdlib::IP::Address::V4', :second | ||
return_type 'Boolean' | ||
end | ||
|
||
dispatch :greater_than do | ||
param 'Stdlib::IP::Address::V6', :first | ||
param 'Stdlib::IP::Address::V6', :second | ||
return_type 'Boolean' | ||
end | ||
|
||
# Refuse to handle addresses in different families. There isn't a clear precedence between the | ||
# two families; if you need to establish an order, you can use type comparison to handle this in | ||
# your Puppet code. | ||
argument_mismatch :mixed_families do | ||
param 'Stdlib::IP::Address::V4', :first | ||
param 'Stdlib::IP::Address::V6', :second | ||
end | ||
|
||
argument_mismatch :mixed_families do | ||
param 'Stdlib::IP::Address::V6', :first | ||
param 'Stdlib::IP::Address::V4', :second | ||
end | ||
|
||
def greater_than(first, second) | ||
first_addr = IPAddr.new(first) | ||
second_addr = IPAddr.new(second) | ||
|
||
first_addr > second_addr | ||
end | ||
|
||
def mixed_families(*) | ||
'both addresses must be in the same family' | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'ipaddr' | ||
|
||
Puppet::Functions.create_function(:"ipcalc::less_than") do | ||
# Compare two IP addresses and return a Boolean indicating whether the first operand is less than | ||
# the second. Contextually, this makes the most sense when using Puppet's dotted function | ||
# notation, because the function name sits where a comparison operator would normally go. This | ||
# will work with either plain addresses or CIDR-notation addresses; if a plain address is | ||
# supplied, a full-width netmask is assumed. That is, '127.0.0.1' and '127.0.0.1/32' are | ||
# equivalent, just as 'fe80::1' and 'fe80::1/128' are equivalent. The netmask IS assessed in the | ||
# comparison, but is only relevant if the remainder of the address is exactly equivalent down to | ||
# the start of the netmask. If addresses of mixed families are given, an error is raised and the | ||
# catalog will fail. There is no obvious implied relation between the two, and even the | ||
# underlying Ruby implementation will refuse to make comparisons between addresses of different | ||
# families. | ||
# @param first | ||
# The first address for comparison. If no netmask is given, full-width is assumed. | ||
# @param second | ||
# The second address for comparison. If no netmask is given, full-width is assumed. | ||
# @return [Boolean] | ||
# `true` if the first operand is less than the second, or `false` otherwise. | ||
# @example Use with dotted function notation | ||
# $first_ip.less_than($second_ip) ? { | ||
# true => { 'We did it, go team, first operand is smaller' }, | ||
# default => { 'I\'m afraid I have some bad news...' }, | ||
# } | ||
dispatch :less_than do | ||
param 'Stdlib::IP::Address::V4', :first | ||
param 'Stdlib::IP::Address::V4', :second | ||
return_type 'Boolean' | ||
end | ||
|
||
dispatch :less_than do | ||
param 'Stdlib::IP::Address::V6', :first | ||
param 'Stdlib::IP::Address::V6', :second | ||
return_type 'Boolean' | ||
end | ||
|
||
# Refuse to handle addresses in different families. There isn't a clear precedence between the | ||
# two families; if you need to establish an order, you can use type comparison to handle this in | ||
# your Puppet code. | ||
argument_mismatch :mixed_families do | ||
param 'Stdlib::IP::Address::V4', :first | ||
param 'Stdlib::IP::Address::V6', :second | ||
end | ||
|
||
argument_mismatch :mixed_families do | ||
param 'Stdlib::IP::Address::V6', :first | ||
param 'Stdlib::IP::Address::V4', :second | ||
end | ||
|
||
def less_than(first, second) | ||
first_addr = IPAddr.new(first) | ||
second_addr = IPAddr.new(second) | ||
|
||
first_addr < second_addr | ||
end | ||
|
||
def mixed_families(*) | ||
'both addresses must be in the same family' | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
describe 'ipcalc::equal_or_greater_than' do | ||
it { is_expected.to run.with_params('127.0.0.1', '127.0.0.2').and_return(false) } | ||
it { is_expected.to run.with_params('127.0.0.2', '127.0.0.1').and_return(true) } | ||
it { is_expected.to run.with_params('127.0.0.1', '127.0.0.1').and_return(true) } | ||
it { is_expected.to run.with_params('fe80::1', 'fe80::2').and_return(false) } | ||
it { is_expected.to run.with_params('fe80::2', 'fe80::1').and_return(true) } | ||
it { is_expected.to run.with_params('fe80::1', 'fe80::1').and_return(true) } | ||
it { is_expected.to run.with_params(nil).and_raise_error(StandardError) } | ||
it { is_expected.to run.with_params('127.0.0.1', 'fe80::1').and_raise_error(StandardError) } | ||
it { is_expected.to run.with_params('fe80::1', '127.0.0.1').and_raise_error(StandardError) } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
describe 'ipcalc::equal_or_less_than' do | ||
it { is_expected.to run.with_params('127.0.0.1', '127.0.0.2').and_return(true) } | ||
it { is_expected.to run.with_params('127.0.0.2', '127.0.0.1').and_return(false) } | ||
it { is_expected.to run.with_params('127.0.0.1', '127.0.0.1').and_return(true) } | ||
it { is_expected.to run.with_params('fe80::1', 'fe80::2').and_return(true) } | ||
it { is_expected.to run.with_params('fe80::2', 'fe80::1').and_return(false) } | ||
it { is_expected.to run.with_params('fe80::1', 'fe80::1').and_return(true) } | ||
it { is_expected.to run.with_params(nil).and_raise_error(StandardError) } | ||
it { is_expected.to run.with_params('127.0.0.1', 'fe80::1').and_raise_error(StandardError) } | ||
it { is_expected.to run.with_params('fe80::1', '127.0.0.1').and_raise_error(StandardError) } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
describe 'ipcalc::equal_to' do | ||
it { is_expected.to run.with_params('127.0.0.1', '127.0.0.2').and_return(false) } | ||
it { is_expected.to run.with_params('127.0.0.2', '127.0.0.1').and_return(false) } | ||
# Zero-padded values are rejected by type validation and by the underlying Ruby implementation | ||
it { is_expected.to run.with_params('127.00.0.1', '127.0.0.1').and_raise_error(StandardError) } | ||
it { is_expected.to run.with_params('127.0.0.1', '127.0.0.1').and_return(true) } | ||
it { is_expected.to run.with_params('fe80::1', 'fe80::2').and_return(false) } | ||
it { is_expected.to run.with_params('fe80::2', 'fe80::1').and_return(false) } | ||
it { is_expected.to run.with_params('fe80:0::001', 'fe80::1').and_return(true) } | ||
it { is_expected.to run.with_params('fe80::1', 'fe80::1').and_return(true) } | ||
it { is_expected.to run.with_params(nil).and_raise_error(StandardError) } | ||
it { is_expected.to run.with_params('127.0.0.1', 'fe80::1').and_return(false) } | ||
it { is_expected.to run.with_params('fe80::1', '127.0.0.1').and_return(false) } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
describe 'ipcalc::greater_than' do | ||
it { is_expected.to run.with_params('127.0.0.1', '127.0.0.2').and_return(false) } | ||
it { is_expected.to run.with_params('127.0.0.2', '127.0.0.1').and_return(true) } | ||
it { is_expected.to run.with_params('fe80::1', 'fe80::2').and_return(false) } | ||
it { is_expected.to run.with_params('fe80::2', 'fe80::1').and_return(true) } | ||
it { is_expected.to run.with_params(nil).and_raise_error(StandardError) } | ||
it { is_expected.to run.with_params('127.0.0.1', 'fe80::1').and_raise_error(StandardError) } | ||
it { is_expected.to run.with_params('fe80::1', '127.0.0.1').and_raise_error(StandardError) } | ||
end |
Oops, something went wrong.