diff --git a/.fixtures.yml b/.fixtures.yml index fda4720..da33c25 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -2,3 +2,4 @@ fixtures: repositories: augeas_core: 'https://github.com/puppetlabs/puppetlabs-augeas_core' stdlib: 'https://github.com/puppetlabs/puppetlabs-stdlib' + systemd: 'https://github.com/camptocamp/puppet-systemd' diff --git a/data/Amazon.yaml b/data/Amazon.yaml index e6f34a0..78d1acd 100644 --- a/data/Amazon.yaml +++ b/data/Amazon.yaml @@ -1,5 +1,5 @@ --- -tftp::package: tftp-server -tftp::root: "/var/lib/tftpboot" -tftp::service: tftp.socket -tftp::syslinux_package: syslinux +tftp::package: 'tftp-server' +tftp::root: '/var/lib/tftpboot' +tftp::service: 'tftp.socket' +tftp::syslinux_package: 'syslinux' diff --git a/data/Archlinux.yaml b/data/Archlinux.yaml index 1c424ca..680fe23 100644 --- a/data/Archlinux.yaml +++ b/data/Archlinux.yaml @@ -1,5 +1,7 @@ --- -tftp::package: tftp-hpa -tftp::root: "/srv/tftp" -tftp::service: tftpd.socket -tftp::syslinux_package: syslinux +tftp::package: 'tftp-hpa' +tftp::root: '/srv/tftp' +tftp::service: 'tftpd.service' +tftp::syslinux_package: 'syslinux' +tftp::username: 'nobody' +tftp::options: '--secure' diff --git a/data/Debian.yaml b/data/Debian.yaml index fe4556e..e50378f 100644 --- a/data/Debian.yaml +++ b/data/Debian.yaml @@ -1,7 +1,9 @@ --- -tftp::package: tftpd-hpa -tftp::root: "/srv/tftp" -tftp::service: tftpd-hpa +tftp::package: 'tftpd-hpa' +tftp::root: '/srv/tftp' +tftp::service: 'tftpd-hpa' tftp::syslinux_package: -- syslinux-common -- pxelinux +- 'syslinux-common' +- 'pxelinux' +tftp::username: 'tftp' +tftp::options: '--secure' diff --git a/data/DragonFly.yaml b/data/DragonFly.yaml index 74584f7..7aa6a63 100644 --- a/data/DragonFly.yaml +++ b/data/DragonFly.yaml @@ -1,5 +1,5 @@ --- -tftp::package: tftp-hpa -tftp::root: "/tftpboot" -tftp::service: tftpd -tftp::syslinux_package: syslinux +tftp::package: 'tftp-hpa' +tftp::root: '/tftpboot' +tftp::service: 'tftpd' +tftp::syslinux_package: 'syslinux' diff --git a/data/FreeBSD.yaml b/data/FreeBSD.yaml index 74584f7..7aa6a63 100644 --- a/data/FreeBSD.yaml +++ b/data/FreeBSD.yaml @@ -1,5 +1,5 @@ --- -tftp::package: tftp-hpa -tftp::root: "/tftpboot" -tftp::service: tftpd -tftp::syslinux_package: syslinux +tftp::package: 'tftp-hpa' +tftp::root: '/tftpboot' +tftp::service: 'tftpd' +tftp::syslinux_package: 'syslinux' diff --git a/data/RedHat.yaml b/data/RedHat.yaml index e79a507..5592fdb 100644 --- a/data/RedHat.yaml +++ b/data/RedHat.yaml @@ -1,5 +1,8 @@ --- -tftp::service: tftp.socket -tftp::package: tftp-server -tftp::root: "/var/lib/tftpboot" -tftp::syslinux_package: syslinux +tftp::service: +- 'tftp.socket' +- 'tftp.service' +tftp::package: 'tftp-server' +tftp::root: '/var/lib/tftpboot' +tftp::syslinux_package: 'syslinux' +tftp::options: '--secure' diff --git a/manifests/config.pp b/manifests/config.pp index d42c14a..7497ec1 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -5,10 +5,46 @@ ensure_resource('file', $tftp::root, { 'ensure' => 'directory' }) } - if $facts['os']['family'] =~ /^(FreeBSD|DragonFly)$/ { - augeas { 'set root directory': - context => '/files/etc/rc.conf', - changes => "set tftpd_flags '\"-s ${tftp::root}\"'", + case $facts['os']['family'] { + 'FreeBSD', 'DragonFly': { + augeas { 'set root directory': + context => '/files/etc/rc.conf', + changes => "set tftpd_flags '\"-s ${tftp::root}\"'", + } + } + 'Debian': { + file { '/etc/default/tftpd-hpa': + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => template('tftp/tftpd-hpa.erb'), + notify => Service[$tftp::service], + } + } + 'Archlinux': { + file { '/etc/conf.d/tftpd': + ensure => file, + owner => 'root', + group => 'root', + mode => '0644', + content => template('tftp/tftpd.erb'), + notify => Service[$tftp::service], + } + } + 'RedHat': { + systemd::dropin_file { 'tftp-socket-override.conf': + unit => 'tftp.socket', + content => epp('tftp/tftp.socket-override.epp'), + } + systemd::dropin_file { 'tftp-service-override.conf': + unit => 'tftp.service', + content => epp('tftp/tftp.service-override.epp'), + require => Systemd::Dropin_file['tftp-socket-override.conf'], + } + } + default: { + notify { "Unsupported platform: ${facts['os']['family']}, the tftp service will run with with default parameters": } } } } diff --git a/manifests/init.pp b/manifests/init.pp index cb463cb..3eafebf 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -18,16 +18,25 @@ # @param syslinux_package Name of the syslinux package, essential for pxe boot # @param manage_syslinux_package manages the syslinux package, defaults to true # @param manage_root_dir manages the root dir, which tftpd will serve, defaults to true -# @param service Name of the TFTP service, when daemon is true -# @param service_provider Override TFTP service provider, when daemon is true +# @param service Name of the TFTP service +# @param service_provider Override TFTP service provider +# @param username Configures the service user +# @param port Configures the Listen Port +# @param address Configures the Listen Address, if empty it will listen on IPv4 and IPv6 (only on tftpd-hpa) +# @param options Configures service options + class tftp ( Stdlib::Absolutepath $root, String $package, Variant[String, Array[String]] $syslinux_package, Boolean $manage_syslinux_package, Boolean $manage_root_dir, - Optional[String] $service = undef, + Variant[String, Array[String]] $service, Optional[String] $service_provider = undef, + String $username = 'root', + Stdlib::Port $port = 69, + Optional[Stdlib::IP::Address] $address = undef, + Optional[String] $options = undef, ) { contain tftp::install contain tftp::config diff --git a/manifests/service.pp b/manifests/service.pp index aa7a290..269f43f 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -4,7 +4,6 @@ service { $tftp::service: ensure => running, enable => true, - alias => 'tftpd', provider => $tftp::service_provider, } } diff --git a/spec/acceptance/tftp_port_spec.rb b/spec/acceptance/tftp_port_spec.rb new file mode 100644 index 0000000..91f777e --- /dev/null +++ b/spec/acceptance/tftp_port_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper_acceptance' + +describe 'tftp with default parameters' do + it_behaves_like 'an idempotent resource' do + let(:manifest) do + <<-EOS + class { 'tftp': + port => 1234, + } + + file { "${tftp::root}/test": + ensure => file, + content => 'running on a different port', + } + EOS + end + end + + service_name = case fact('osfamily') + when 'Archlinux' + 'tftpd.service' + when 'RedHat' + 'tftp.socket' + when 'Debian' + 'tftpd-hpa' + end + + describe service(service_name) do + it { is_expected.to be_enabled } + it { is_expected.to be_running } + end + + describe port(69) do + it { is_expected.not_to be_listening } + end + + describe port(1234) do + it { is_expected.to be_listening.with('udp').or be_listening.with('udp6') } + end + + describe command("echo get /test /tmp/downloaded_file | tftp #{fact('fqdn')} 1234") do + its(:exit_status) { should eq 0 } + end + + describe file('/tmp/downloaded_file') do + it { should be_file } + its(:content) { should eq 'running on a different port' } + end +end diff --git a/spec/acceptance/tftp_spec.rb b/spec/acceptance/tftp_spec.rb index 54a466b..f42a19e 100644 --- a/spec/acceptance/tftp_spec.rb +++ b/spec/acceptance/tftp_spec.rb @@ -16,7 +16,7 @@ class { 'tftp': } service_name = case fact('osfamily') when 'Archlinux' - 'tftpd.socket' + 'tftpd.service' when 'RedHat' 'tftp.socket' when 'Debian' @@ -28,8 +28,8 @@ class { 'tftp': } it { is_expected.to be_running } end - describe port(69), unless: service_name.end_with?('.socket') do - it { is_expected.to be_listening.with('udp') } + describe port(69) do + it { is_expected.to be_listening.with('udp').or be_listening.with('udp6') } end describe command("echo get /test /tmp/downloaded_file | tftp #{fact('fqdn')}") do diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 7a2bdea..1d7ec5e 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -46,23 +46,30 @@ should contain_service('tftp.socket') .with_ensure('running') .with_enable('true') - .with_alias('tftpd') .that_subscribes_to('Class[Tftp::Config]') end + + it 'should contain the service override' do + should contain_systemd__dropin_file('tftp-service-override.conf') + .with_content("[Service]\nExecStart=\nExecStart=/usr/sbin/in.tftpd --secure /var/lib/tftpboot\n") + end + + it 'should contain the socket override' do + should contain_systemd__dropin_file('tftp-socket-override.conf') + .with_content("[Socket]\nListenDatagram=\nListenDatagram=69\n") + end when 'FreeBSD' it 'should contain the service' do should contain_service('tftpd') .with_ensure('running') .with_enable('true') - .with_alias('tftpd') .that_subscribes_to('Class[Tftp::Config]') end when 'Archlinux' it 'should contain the service' do - should contain_service('tftpd.socket') + should contain_service('tftpd.service') .with_ensure('running') .with_enable('true') - .with_alias('tftpd') .that_subscribes_to('Class[Tftp::Config]') end else @@ -70,7 +77,6 @@ should contain_service('tftpd-hpa') .with_ensure('running') .with_enable('true') - .with_alias('tftpd') .that_subscribes_to('Class[Tftp::Config]') end end @@ -141,7 +147,6 @@ should contain_service('tftp.socket') .with_ensure('running') .with_enable('true') - .with_alias('tftpd') .that_subscribes_to('Class[Tftp::Config]') end end diff --git a/spec/setup_acceptance_node.pp b/spec/setup_acceptance_node.pp index 0551aad..00268c3 100644 --- a/spec/setup_acceptance_node.pp +++ b/spec/setup_acceptance_node.pp @@ -4,3 +4,10 @@ ensure => installed, } } + +# without it "ss" command is not found and "port listening" tests fail +if $facts['os']['name'] == 'Fedora' { + package { 'iproute': + ensure => installed, + } +} diff --git a/templates/tftp.service-override.epp b/templates/tftp.service-override.epp new file mode 100644 index 0000000..0484883 --- /dev/null +++ b/templates/tftp.service-override.epp @@ -0,0 +1,3 @@ +[Service] +ExecStart= +ExecStart=/usr/sbin/in.tftpd <%= $tftp::options %> <%= $tftp::root %> diff --git a/templates/tftp.socket-override.epp b/templates/tftp.socket-override.epp new file mode 100644 index 0000000..80698de --- /dev/null +++ b/templates/tftp.socket-override.epp @@ -0,0 +1,3 @@ +[Socket] +ListenDatagram= +ListenDatagram=<%= $tftp::port %> diff --git a/templates/tftpd-hpa.erb b/templates/tftpd-hpa.erb new file mode 100644 index 0000000..d293da7 --- /dev/null +++ b/templates/tftpd-hpa.erb @@ -0,0 +1,6 @@ +# /etc/default/tftpd-hpa + +TFTP_USERNAME="<%= scope['tftp::username'] %>" +TFTP_DIRECTORY="<%= scope['tftp::root'] %>" +TFTP_ADDRESS="<%= scope['tftp::address'] %>:<%= scope['tftp::port'] %>" +TFTP_OPTIONS="<%= scope['tftp::options'] %>" diff --git a/templates/tftpd.erb b/templates/tftpd.erb new file mode 100644 index 0000000..cdba169 --- /dev/null +++ b/templates/tftpd.erb @@ -0,0 +1,3 @@ +# /etc/conf.d/tftpd + +TFTPD_ARGS="<%= scope['tftp::options'] %> <%= scope['tftp::root'] %> --address <%= scope['tftp::address'] %>:<%= scope['tftp::port'] %> --user <%= scope['tftp::username'] %>"