Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add possibility to manage network interfaces with a template #497

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,071 changes: 2,071 additions & 0 deletions REFERENCE.md

Large diffs are not rendered by default.

74 changes: 74 additions & 0 deletions manifests/networkd.pp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,53 @@
# @param ensure The state that the ``networkd`` service should be in
# @param path path where all networkd files are placed in
# @param manage_all_network_files if enabled, all networkd files that aren't managed by puppet will be purged
# @param link_profiles
# Hash of network link profiles that can be referenced by its key on an interface
# The structure is equal to the 'link' parameter of an interface.
# @param netdev_profiles
# Hash of netdev profiles that can be referenced by its key on an interface
# The structure is equal to the 'netdev' parameter of an interface.
# @param network_profiles
# Hash of network profiles that can be referenced by its key on an interface
# The structure is equal to the 'network' parameter of an interface.
# @param interfaces
# Hash of interfaces to configure on a node.
# The link, netdev and network parameters are deep merged with the respective profile
# (referenced by the key of the interface).
# With the profiles you can set the default values for a network.
# Hint: to remove a profile setting for an interface you can either overwrite or
# set it to `~` for removal.
# Example (hiera yaml notation):
trefzer marked this conversation as resolved.
Show resolved Hide resolved
# systemd::networkd::network_profiles:
# mynet:
# Network:
# Gateway: '192.168.0.1'
#
# systemd::networkd
# mynet:
# filename: '50-static'
# network:
# Match:
# Name: 'eno0'
# Network:
# Address: '192.168.0.15/24'
#
# Gives you a file /etc/systemd/network/50-static.network
# with content:
# [Match]
# Name=enp2s0
# [Network]
# Address=192.168.0.15/24
# Gateway=192.168.0.1
#
kenyon marked this conversation as resolved.
Show resolved Hide resolved
class systemd::networkd (
Enum['stopped','running'] $ensure = $systemd::networkd_ensure,
Stdlib::Absolutepath $path = $systemd::network_path,
Boolean $manage_all_network_files = $systemd::manage_all_network_files,
Hash[String[1],Systemd::Interface::Link] $link_profiles = {},
Hash[String[1],Systemd::Interface::Netdev] $netdev_profiles = {},
Hash[String[1],Systemd::Interface::Network] $network_profiles = {},
Hash[String[1],Systemd::Interface] $interfaces = {},
) {
assert_private()

Expand All @@ -32,4 +75,35 @@
notify => Service['systemd-networkd'],
}
}

$interfaces.each | String[1] $interface_name, Systemd::Interface $interface | {
$_filename=pick($interface['filename'], $interface_name)
if 'link' in $interface.keys() {
systemd::network { "${_filename}.link":
path => $path,
content => epp('systemd/network.epp', {
fname => "${_filename}.link",
config => deep_merge(pick($link_profiles[$interface_name], {}), $interface['link']),
}),
Comment on lines +85 to +87
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to put the closing braces on separate lines to avoid the need for double indentation:

Suggested change
fname => "${_filename}.link",
config => deep_merge(pick($link_profiles[$interface_name], {}), $interface['link']),
}),
fname => "${_filename}.link",
config => deep_merge(pick($link_profiles[$interface_name], {}), $interface['link']),
},
),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that this makes the code better readable. I will not change that for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does. The double indentation that you have to do currently is really just a bug in puppet-lint, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no the double intentation is correct since there are to brackets to intent.
to clarify:
my solution:

epp('template, {
    var => val,
})

your solution:

epp('template,
 {
    var => val,
 }
)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, IMO it is easier to follow the indentation when there is only at most one level of change between each line (your example has var => val, indented one level too far in my solution), easier to match up the opening and closing braces, and reduces diffs when adding and removing items to the comma-separated lists by already having separate lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a test commit with your suggestion. I expect it to fail on validation test ! let's see

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok validatio now fails, the it needs 12 spaces, no way to lower that.
I will remove the last commit tomorrow. Think we can resolv this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, it's clearly not correct to have the closing brace on the same line as the content inside of the brace. You'd have to also move the opening brace and fix the indentation.

}
}
if 'netdev' in $interface.keys() {
systemd::network { "${_filename}.netdev":
path => $path,
content => epp('systemd/network.epp', {
fname => "${_filename}.netdev",
config => deep_merge(pick($netdev_profiles[$interface_name], {}), $interface['netdev']),
}),
}
}
if 'network' in $interface.keys() {
systemd::network { "${_filename}.network":
path => $path,
content => epp('systemd/network.epp', {
fname => "${_filename}.network",
config => deep_merge(pick($network_profiles[$interface_name], {}), $interface['network']),
}),
}
}
}
}
20 changes: 20 additions & 0 deletions spec/classes/networkd_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'systemd::networkd' do
on_supported_os.each do |os, os_facts|
context "on #{os}" do
let(:facts) { os_facts }
let(:pre_condition) do
[
'include systemd',
# Fake assert_private function from stdlib to not fail within this test
'function assert_private () { }',
]
end

it { is_expected.to compile.with_all_deps }
end
end
end
34 changes: 34 additions & 0 deletions spec/type_aliases/interface/link_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'Systemd::Interface::Link' do
describe 'valid types' do
context 'with valid types' do
[
{},
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
end
end
end

describe 'invalid types' do
context 'with garbage inputs' do
[
true,
false,
:keyword,
nil,
{ 'foo' => 'bar' },
'42',
].each do |value|
describe value.inspect do
it { is_expected.not_to allow_value(value) }
end
end
end
end
end
34 changes: 34 additions & 0 deletions spec/type_aliases/interface/netdev_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'Systemd::Interface::Netdev' do
describe 'valid types' do
context 'with valid types' do
[
{},
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
end
end
end

describe 'invalid types' do
context 'with garbage inputs' do
[
true,
false,
:keyword,
nil,
{ 'foo' => 'bar' },
'42',
].each do |value|
describe value.inspect do
it { is_expected.not_to allow_value(value) }
end
end
end
end
end
34 changes: 34 additions & 0 deletions spec/type_aliases/interface/network_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'Systemd::Interface::Network' do
describe 'valid types' do
context 'with valid types' do
[
{},
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
end
end
end

describe 'invalid types' do
context 'with garbage inputs' do
[
true,
false,
:keyword,
nil,
{ 'foo' => 'bar' },
'42',
].each do |value|
describe value.inspect do
it { is_expected.not_to allow_value(value) }
end
end
end
end
end
34 changes: 34 additions & 0 deletions spec/type_aliases/systemd_interface_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'Systemd::Interface' do
describe 'valid types' do
context 'with valid types' do
[
{},
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
end
end
end

describe 'invalid types' do
context 'with garbage inputs' do
[
true,
false,
:keyword,
nil,
{ 'foo' => 'bar' },
'42',
].each do |value|
describe value.inspect do
it { is_expected.not_to allow_value(value) }
end
end
end
end
end
26 changes: 26 additions & 0 deletions templates/network.epp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<%- | String[1] $fname = {},
Hash $config = {},
| -%>
#
# This file is managed with puppet
#
# File name: <%= $fname %>
#
<% $config.each |String $head, Variant[Hash,Array] $vals| { -%>
<%- if $vals =~ Array { $_loop= $vals } else { $_loop = [ $vals ] } -%>
<%- $_loop.each | Hash $vals | { -%>

<%- %>[<%= $head %>]
<%- $vals.each() | String $key, Any $value | { -%>
<%- if $value =~ Array[String] { -%>
<%- $value.each() | String $val | { -%>
<%- %><%= $key %>=<%= $val %>
<%- } -%>
<%- } else { -%>
<%- if $value !~ Undef { -%>
<%- %><%= $key %>=<%= $value %>
<%- } -%>
<%- } -%>
<%- } -%>
<%- } -%>
<% } -%>
7 changes: 7 additions & 0 deletions types/interface.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# network interface definition
type Systemd::Interface = Struct[{
filename => Optional[String[1]],
network => Optional[Systemd::Interface::Network],
netdev => Optional[Systemd::Interface::Netdev],
link => Optional[Systemd::Interface::Link],
}]
6 changes: 6 additions & 0 deletions types/interface/link.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# interface definition
type Systemd::Interface::Link = Struct[{
'Match' => Optional[Systemd::Interface::Link::Match],
'Link' => Optional[Systemd::Interface::Link::Link],
'SR-IOV' => Optional[Systemd::Interface::Link::Sr_iov],
}]
84 changes: 84 additions & 0 deletions types/interface/link/link.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# interface definition
type Systemd::Interface::Link::Link = Struct[{
'Description' => Optional[String[1]],
'Property' => Optional[String[1]],
'ImportProperty' => Optional[String[1]],
'UnsetProperty' => Optional[String[1]],
'Alias' => Optional[String[1]],
'MACAddressPolicy' => Optional[Enum['persistent', 'random', 'none', '']],
'MACAddress' => Optional[String[1]],
'NamePolicy' => Optional[Enum[
'kernel', 'database', 'onboard', 'slot',
'path', 'mac', 'keep'
]],
'Name' => Optional[String[1]],
'AlternativeNamesPolicy' => Optional[String[1]],
'AlternativeName' => Optional[String[1]],
'TransmitQueues' => Optional[Integer[1,4096]],
'ReceiveQueues' => Optional[Integer[1,4096]],
'TransmitQueueLength' => Optional[Integer[0, 4294967294]],
'MTUBytes' => Optional[Integer[1280]],
'BitsPerSecond' => Optional[String[1]],
'Duplex' => Optional[String[1]],
'AutoNegotiation' => Optional[Enum['yes','no']],
'WakeOnLan' => Optional[Enum[
'phy', 'unicast', 'multicast', 'broadcast',
'arp', 'magic', 'secureon'
]],
'WakeOnLanPassword' => Optional[String[1]],
'Port' => Optional[Enum['tp', 'aui', 'bnc', 'mii', 'fibre']],
'Advertise' => Optional[Variant[
Systemd::Interface::Link::Link_advertise,
Array[Systemd::Interface::Link::Link_advertise]
]],
'ReceiveChecksumOffload' => Optional[Enum['yes','no']],
'TransmitChecksumOffload' => Optional[Enum['yes','no']],
'TCPSegmentationOffload' => Optional[Enum['yes','no']],
'TCP6SegmentationOffload' => Optional[Enum['yes','no']],
'GenericSegmentationOffload' => Optional[Enum['yes','no']],
'GenericReceiveOffload' => Optional[Enum['yes','no']],
'LargeReceiveOffload' => Optional[Enum['yes','no']],
'ReceivePacketSteeringCPUMask' => Optional[String[1]],
'ReceiveVLANCTAGHardwareAcceleration' => Optional[Enum['yes','no']],
'TransmitVLANCTAGHardwareAcceleration'=> Optional[Enum['yes','no']],
'ReceiveVLANCTAGFilter' => Optional[Enum['yes','no']],
'TransmitVLANSTAGHardwareAcceleration'=> Optional[Enum['yes','no']],
'NTupleFilter' => Optional[Enum['yes','no']],
'RxChannels' => Optional[Variant[Enum['max'],Integer[1,4294967295]]],
'TxChannels' => Optional[Variant[Enum['max'],Integer[1,4294967295]]],
'OtherChannels' => Optional[Variant[Enum['max'],Integer[1,4294967295]]],
'CombinedChannels' => Optional[Variant[Enum['max'],Integer[1,4294967295]]],
'RxBufferSize' => Optional[Variant[Enum['max'],Integer[1,4294967295]]],
'RxMiniBufferSize' => Optional[Variant[Enum['max'],Integer[1,4294967295]]],
'RxJumboBufferSize' => Optional[Variant[Enum['max'],Integer[1,4294967295]]],
'TxBufferSize' => Optional[Variant[Enum['max'],Integer[1,4294967295]]],
'RxFlowControl' => Optional[Enum['yes','no']],
'TxFlowControl' => Optional[Enum['yes','no']],
'AutoNegotiationFlowControl' => Optional[Enum['yes','no']],
'GenericSegmentOffloadMaxBytes' => Optional[String[1]],
'GenericSegmentOffloadMaxSegments' => Optional[Integer[1, 65535]],
'UseAdaptiveRxCoalesce' => Optional[Enum['yes','no']],
'UseAdaptiveTxCoalesce' => Optional[Enum['yes','no']],
'RxCoalesceSec' => Optional[Integer],
'RxCoalesceIrqSec' => Optional[Integer],
'RxCoalesceLowSec' => Optional[Integer],
'RxCoalesceHighSec' => Optional[Integer],
'TxCoalesceSec' => Optional[Integer],
'TxCoalesceIrqSec' => Optional[Integer],
'TxCoalesceLowSec' => Optional[Integer],
'TxCoalesceHighSec' => Optional[Integer],
'RxMaxCoalescedFrames' => Optional[Integer],
'RxMaxCoalescedIrqFrames' => Optional[Integer],
'RxMaxCoalescedLowFrames' => Optional[Integer],
'RxMaxCoalescedHighFrames' => Optional[Integer],
'TxMaxCoalescedFrames' => Optional[Integer],
'TxMaxCoalescedIrqFrames' => Optional[Integer],
'TxMaxCoalescedLowFrames' => Optional[Integer],
'TxMaxCoalescedHighFrames' => Optional[Integer],
'CoalescePacketRateLow' => Optional[Integer],
'CoalescePacketRateHigh' => Optional[Integer],
'CoalescePacketRateSampleIntervalSec' => Optional[Integer],
'StatisticsBlockCoalesceSec' => Optional[Integer[1]],
'MDI' => Optional[Enum['straight', 'mdi', 'crossover', 'mdi-x', 'mdix', 'auto']],
'SR_IOVVirtualFunctions' => Optional[Integer[0, 2147483647]],
}]
Loading
Loading