Skip to content

Commit

Permalink
Fix has_ip_address and has_ip_network functions
Browse files Browse the repository at this point in the history
The functions were using the old legacy function API.  This meant that
when they called `has_interface_with`, they were calling the legacy
implementation of that function and not the v4 API version introduced in
bc218f0.

Only in the v4 API implementation was the modern `networking` structured
fact being used.  The old `parser/functions/has_interface_with.rb`
version still used legacy facts that are now not included in Puppet 8 by
default.

In this commit, we replace the `has_ip_address` and `has_ip_network`
functions with namespaced Puppet language functions, (these functions
are simple enough to not need ruby). Non-namespaced versions are added
(but marked as deprecated) in `lib/puppet/functions`.

The old implementations are removed completely. This is _almost_
certainly not going to be a breaking change for anyone. (Only other
legacy functions which in turn call these functions could be affected).

Fixes #1447
  • Loading branch information
alexjfisher committed Feb 11, 2025
1 parent 52740b7 commit f2b8cbf
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 188 deletions.
109 changes: 56 additions & 53 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ environment.
* [`grep`](#grep): This function searches through an array and returns any elements that match
the provided regular expression.
* [`has_interface_with`](#has_interface_with): DEPRECATED. Use the namespaced function [`stdlib::has_interface_with`](#stdlibhas_interface_with) instead.
* [`has_interface_with`](#has_interface_with): Returns boolean based on kind and value.
* [`has_ip_address`](#has_ip_address): Returns true if the client has the requested IP address on some interface.
* [`has_ip_network`](#has_ip_network): Returns true if the client has an IP address within the requested network.
* [`has_ip_address`](#has_ip_address): DEPRECATED. Use the namespaced function [`stdlib::has_ip_address`](#stdlibhas_ip_address) instead.
* [`has_ip_network`](#has_ip_network): DEPRECATED. Use the namespaced function [`stdlib::has_ip_network`](#stdlibhas_ip_network) instead.
* [`intersection`](#intersection): This function returns an array of the intersection of two.
* [`is_a`](#is_a): Boolean check to determine whether a variable is of a given data type.
This is equivalent to the `=~` type checks.
Expand Down Expand Up @@ -126,6 +125,8 @@ optional seed for repeatable randomness.
* [`stdlib::fqdn_rotate`](#stdlib--fqdn_rotate): Rotates an array or string a random number of times, combining the `fqdn` fact and an optional seed for repeatable randomness.
* [`stdlib::has_function`](#stdlib--has_function): Returns whether the Puppet runtime has access to a given function.
* [`stdlib::has_interface_with`](#stdlib--has_interface_with): Returns boolean based on network interfaces present and their attribute values.
* [`stdlib::has_ip_address`](#stdlib--has_ip_address): Returns true if the client has the requested IP address on some interface.
* [`stdlib::has_ip_network`](#stdlib--has_ip_network): Returns true if the client has the requested IPv4 network on some interface.
* [`stdlib::ip_in_range`](#stdlib--ip_in_range): Returns true if the ipaddress is within the given CIDRs
* [`stdlib::merge`](#stdlib--merge): Merges two or more hashes together or hashes resulting from iteration, and returns
the resulting hash.
Expand Down Expand Up @@ -2052,75 +2053,41 @@ Data type: `Any`



### <a name="has_interface_with"></a>`has_interface_with`

Type: Ruby 3.x API

Valid kinds are `macaddress`, `netmask`, `ipaddress` and `network`.

#### Examples

##### **Usage**

```puppet
has_interface_with("macaddress", "x:x:x:x:x:x") # Returns `false`
has_interface_with("ipaddress", "127.0.0.1") # Returns `true`
```

##### If no "kind" is given, then the presence of the interface is checked:

```puppet
has_interface_with("lo") # Returns `true`
```
### <a name="has_ip_address"></a>`has_ip_address`

#### `has_interface_with()`
Type: Ruby 4.x API

Valid kinds are `macaddress`, `netmask`, `ipaddress` and `network`.
DEPRECATED. Use the namespaced function [`stdlib::has_ip_address`](#stdlibhas_ip_address) instead.

Returns: `Any` boolean values `true` or `false`
#### `has_ip_address(Any *$args)`

##### Examples
The has_ip_address function.

###### **Usage**

```puppet
has_interface_with("macaddress", "x:x:x:x:x:x") # Returns `false`
has_interface_with("ipaddress", "127.0.0.1") # Returns `true`
```
Returns: `Any`

###### If no "kind" is given, then the presence of the interface is checked:
##### `*args`

```puppet
has_interface_with("lo") # Returns `true`
```
Data type: `Any`

### <a name="has_ip_address"></a>`has_ip_address`

Type: Ruby 3.x API

This function iterates through the 'interfaces' fact and checks the
'ipaddress_IFACE' facts, performing a simple string comparison.
### <a name="has_ip_network"></a>`has_ip_network`

#### `has_ip_address()`
Type: Ruby 4.x API

This function iterates through the 'interfaces' fact and checks the
'ipaddress_IFACE' facts, performing a simple string comparison.
DEPRECATED. Use the namespaced function [`stdlib::has_ip_network`](#stdlibhas_ip_network) instead.

Returns: `Boolean` `true` or `false`
#### `has_ip_network(Any *$args)`

### <a name="has_ip_network"></a>`has_ip_network`
The has_ip_network function.

Type: Ruby 3.x API
Returns: `Any`

This function iterates through the 'interfaces' fact and checks the
'network_IFACE' facts, performing a simple string comparision.
##### `*args`

#### `has_ip_network()`
Data type: `Any`

This function iterates through the 'interfaces' fact and checks the
'network_IFACE' facts, performing a simple string comparision.

Returns: `Any` Boolean value, `true` if the client has an IP address within the requested network.

### <a name="intersection"></a>`intersection`

Expand Down Expand Up @@ -3575,6 +3542,42 @@ Data type: `String[1]`

The value of the attribute

### <a name="stdlib--has_ip_address"></a>`stdlib::has_ip_address`

Type: Puppet Language

Returns true if the client has the requested IP address on some interface.

#### `stdlib::has_ip_address(Stdlib::IP::Address::V4::Nosubnet $ip_address)`

The stdlib::has_ip_address function.

Returns: `Boolean` Returns `true` if the requested IP address exists on any interface.

##### `ip_address`

Data type: `Stdlib::IP::Address::V4::Nosubnet`

The IPv4 address you want to check the existence of

### <a name="stdlib--has_ip_network"></a>`stdlib::has_ip_network`

Type: Puppet Language

Returns true if the client has the requested IPv4 network on some interface.

#### `stdlib::has_ip_network(Stdlib::IP::Address::V4::Nosubnet $ip_network)`

The stdlib::has_ip_network function.

Returns: `Boolean` Returns `true` if the requested IP network exists on any interface.

##### `ip_network`

Data type: `Stdlib::IP::Address::V4::Nosubnet`

The IPv4 network you want to check the existence of

### <a name="stdlib--ip_in_range"></a>`stdlib::ip_in_range`

Type: Ruby 4.x API
Expand Down
10 changes: 10 additions & 0 deletions functions/has_ip_address.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# @summary Returns true if the client has the requested IP address on some interface.
#
# @param ip_address
# The IPv4 address you want to check the existence of
# @return [Boolean] Returns `true` if the requested IP address exists on any interface.
function stdlib::has_ip_address(
Stdlib::IP::Address::V4::Nosubnet $ip_address,
) >> Boolean {
stdlib::has_interface_with('ipaddress', $ip_address)
}
10 changes: 10 additions & 0 deletions functions/has_ip_network.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# @summary Returns true if the client has the requested IPv4 network on some interface.
#
# @param ip_network
# The IPv4 network you want to check the existence of
# @return [Boolean] Returns `true` if the requested IP network exists on any interface.
function stdlib::has_ip_network(
Stdlib::IP::Address::V4::Nosubnet $ip_network,
) >> Boolean {
stdlib::has_interface_with('network', $ip_network)
}
14 changes: 14 additions & 0 deletions lib/puppet/functions/has_ip_address.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`

# @summary DEPRECATED. Use the namespaced function [`stdlib::has_ip_address`](#stdlibhas_ip_address) instead.
Puppet::Functions.create_function(:has_ip_address) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'has_ip_address', 'This function is deprecated, please use stdlib::has_ip_address instead.', false)
call_function('stdlib::has_ip_address', *args)
end
end
14 changes: 14 additions & 0 deletions lib/puppet/functions/has_ip_network.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

# THIS FILE WAS GENERATED BY `rake regenerate_unamespaced_shims`

# @summary DEPRECATED. Use the namespaced function [`stdlib::has_ip_network`](#stdlibhas_ip_network) instead.
Puppet::Functions.create_function(:has_ip_network) do
dispatch :deprecation_gen do
repeated_param 'Any', :args
end
def deprecation_gen(*args)
call_function('deprecation', 'has_ip_network', 'This function is deprecated, please use stdlib::has_ip_network instead.', false)
call_function('stdlib::has_ip_network', *args)
end
end
68 changes: 0 additions & 68 deletions lib/puppet/parser/functions/has_interface_with.rb

This file was deleted.

27 changes: 0 additions & 27 deletions lib/puppet/parser/functions/has_ip_address.rb

This file was deleted.

27 changes: 0 additions & 27 deletions lib/puppet/parser/functions/has_ip_network.rb

This file was deleted.

21 changes: 14 additions & 7 deletions spec/functions/has_ip_address_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,29 @@

describe 'has_ip_address' do
it { is_expected.not_to be_nil }
it { is_expected.to run.with_params.and_raise_error(Puppet::ParseError, %r{wrong number of arguments}i) }
it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, %r{wrong number of arguments}i) }
it { is_expected.to run.with_params.and_raise_error(ArgumentError, %r{'stdlib::has_ip_address' expects 1 argument, got none}) }
it { is_expected.to run.with_params('one', 'two').and_raise_error(ArgumentError, %r{'stdlib::has_ip_address' expects 1 argument, got 2}) }

context 'when on Linux Systems' do
let(:facts) do
{
interfaces: 'eth0,lo',
ipaddress: '10.0.0.1',
ipaddress_lo: '127.0.0.1',
ipaddress_eth0: '10.0.0.1'
networking: {
'interfaces' => {
'eth0' => {
'ip' => '10.0.0.1',
},
'lo' => {
'ip' => '127.0.0.1',
},
},
'ip' => '10.0.0.1',
},
}
end

it { is_expected.to run.with_params('127.0.0.1').and_return(true) }
it { is_expected.to run.with_params('10.0.0.1').and_return(true) }
it { is_expected.to run.with_params('8.8.8.8').and_return(false) }
it { is_expected.to run.with_params('invalid').and_return(false) }
it { is_expected.to run.with_params('invalid').and_raise_error(ArgumentError, %r{parameter 'ip_address' expects a match}) }
end
end
Loading

0 comments on commit f2b8cbf

Please sign in to comment.