View
@@ -0,0 +1,2 @@
---
tftp::syslinux_package: syslinux
View
@@ -0,0 +1,2 @@
---
tftp::syslinux_package: syslinux
View
@@ -0,0 +1,8 @@
---
tftp::daemon: true
tftp::package: tftpd-hpa
tftp::root: "/srv/tftp"
tftp::service: tftpd-hpa
tftp::syslinux_package:
- syslinux-common
- pxelinux
View
@@ -0,0 +1,6 @@
---
tftp::daemon: true
tftp::package: tftp-hpa
tftp::root: "/tftpboot"
tftp::service: tftpd
tftp::syslinux_package: syslinux
View
@@ -0,0 +1,6 @@
---
tftp::daemon: true
tftp::package: tftp-hpa
tftp::root: "/tftpboot"
tftp::service: tftpd
tftp::syslinux_package: syslinux
View
@@ -0,0 +1,2 @@
---
tftp::root: "/tftpboot"
View
@@ -0,0 +1,2 @@
---
tftp::root: "/tftpboot"
View
@@ -0,0 +1,6 @@
---
tftp::daemon: false
tftp::service: tftp.socket
tftp::package: tftp-server
tftp::root: "/var/lib/tftpboot"
tftp::syslinux_package: syslinux
View
@@ -0,0 +1,2 @@
---
tftp::syslinux_package: syslinux
View
@@ -0,0 +1,2 @@
---
tftp::syslinux_package: syslinux
View
@@ -0,0 +1,3 @@
---
# 16.04's Puppet package defaults to upstart (https://bugs.launchpad.net/ubuntu/+source/puppet/+bug/1570472)
tftp::service_provider: systemd
View
@@ -0,0 +1,2 @@
---
tftp::root: "/var/lib/tftpboot"
View
@@ -0,0 +1,2 @@
---
tftp::manage_root_dir: true
View
@@ -2,3 +2,4 @@
re ^bootmgr\.exe boot/bootmgr.exe
re ^\\Boot\\ boot/
rg \\ /
rg (.*)�$ \1
View
@@ -0,0 +1,22 @@
---
version: 5
defaults:
datadir: data
data_hash: 'yaml_data'
hierarchy:
- name: 'Full Version'
path: '%{facts.os.name}-%{facts.os.release.full}.yaml'
- name: 'Major Version'
path: '%{facts.os.name}-%{facts.os.release.major}.yaml'
- name: 'Distribution Name'
path: '%{facts.os.name}.yaml'
- name: 'Operating System Family'
path: '%{facts.os.family}.yaml'
- name: 'common'
path: 'common.yaml'
View
@@ -1,32 +1,40 @@
# Configure TFTP
class tftp::config {
case $::tftp::params::daemon {
default: { } # not needed for daemon-mode
false: {
include ::xinetd
if $::tftp::manage_root_dir {
ensure_resource('file', $::tftp::root, {'ensure' => 'directory'})
}
xinetd::service { 'tftp':
port => '69',
server => '/usr/sbin/in.tftpd',
server_args => "-v -s ${::tftp::root} -m /etc/tftpd.map",
socket_type => 'dgram',
protocol => 'udp',
cps => '100 2',
flags => 'IPv4',
per_source => '11',
if $::tftp::daemon {
if $::osfamily =~ /^(FreeBSD|DragonFly)$/ {
augeas { 'set root directory':
context => '/files/etc/rc.conf',
changes => "set tftpd_flags '\"-s ${::tftp::root}\"'",
}
}
} else {
include ::xinetd
file {'/etc/tftpd.map':
content => template('tftp/tftpd.map'),
mode => '0644',
notify => Class['xinetd'],
}
xinetd::service { 'tftp':
port => '69',
server => '/usr/sbin/in.tftpd',
server_args => "-v -s ${::tftp::root} -m /etc/tftpd.map",
socket_type => 'dgram',
protocol => 'udp',
cps => '100 2',
flags => 'IPv4',
per_source => '11',
}
file { $::tftp::root:
ensure => directory,
notify => Class['xinetd'],
}
file {'/etc/tftpd.map':
source => "puppet:///modules/${module_name}/tftpd.map",
mode => '0644',
show_diff => false, # Puppet explodes with 'Error: invalid byte sequence in UTF-8' when trying to display the diff
notify => Class['xinetd'],
}
if $::tftp::manage_root_dir {
File[$::tftp::root] ~> Class['xinetd']
}
}
}
View
@@ -1,31 +1,42 @@
# == Class: tftp
# TFTP server class
#
# This class installs and configures a TFTP server
# This class installs and configures a TFTP server, supporting both standalone
# daemons and xinetd-based TFTP servers.
#
# === Parameters
# @summary Installs and configures a TFTP server
#
# $root:: Configures the root directory for the TFTP server
# @example Simple usage
# include tftp
#
# === Usage
# @example Configure a TFTP server with a non-default root directory
# class { 'tftp':
# root => '/tftpboot',
# }
#
# * Simple usage:
#
# include tftp
#
# * Configure a TFTP server with a non-default root directory:
#
# class { 'tftp':
# root => '/tftpboot',
# }
# @example Configure a TFTP server with non-default package name
# class { 'tftp:'
# package => 'tftp-hpa-destruct',
# }
#
# @param root Configures the root directory for the TFTP server
# @param package Name of the TFTP server package
# @param syslinux_package Name of the syslinux package, essential for pxe boot
# @param daemon Runs a TFTP service when true, configures xinetd when false
# @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
class tftp (
$root = $tftp::params::root,
) inherits tftp::params {
validate_absolute_path($root)
Stdlib::Absolutepath $root,
String $package,
Variant[String, Array[String]] $syslinux_package,
Boolean $daemon,
Boolean $manage_root_dir,
Optional[String] $service = undef,
Optional[String] $service_provider = undef,
) {
class {'::tftp::install':} ->
class {'::tftp::config':} ~>
class {'::tftp::service':} ->
Class['::tftp']
class {'::tftp::install':}
-> class {'::tftp::config':}
~> class {'::tftp::service':}
-> Class['::tftp']
}
View
@@ -1,11 +1,14 @@
# Install TFTP
class tftp::install {
package { $::tftp::params::package:
class tftp::install (
$package = $::tftp::package,
$syslinux_package = $::tftp::syslinux_package,
) {
package { $package:
ensure => installed,
alias => 'tftp-server',
}
package { $::tftp::params::syslinux_package:
package { $syslinux_package:
ensure => installed,
}
}
View

This file was deleted.

Oops, something went wrong.
View
@@ -2,13 +2,14 @@
class tftp::service {
# No service needed if not daemonized
case $tftp::params::daemon {
case $tftp::daemon {
false: { }
default: {
service { $tftp::params::service:
service { $tftp::service:
ensure => running,
enable => true,
alias => 'tftpd',
provider => $::tftp::service_provider,
subscribe => Class['tftp::config'],
}
}
View
@@ -1,6 +1,6 @@
{
"name": "theforeman-tftp",
"version": "1.5.1",
"version": "4.2.1",
"author": "theforeman",
"summary": "TFTP server configuration",
"license": "GPL-3.0+",
@@ -16,17 +16,17 @@
"dependencies": [
{
"name": "puppetlabs/stdlib",
"version_requirement": ">= 2.3.0 < 5.0.0"
"version_requirement": ">= 4.13.1 < 6.0.0"
},
{
"name": "puppetlabs/xinetd",
"version_requirement": ">= 1.1.0 < 2.0.0"
"version_requirement": ">= 1.1.0 < 4.0.0"
}
],
"requirements": [
{
"name": "puppet",
"version_requirement": ">= 2.7.0 < 4.0.0"
"version_requirement": ">= 4.9.0 < 6.0.0"
}
],
"operatingsystem_support": [
@@ -54,23 +54,39 @@
{
"operatingsystem": "Fedora",
"operatingsystemrelease": [
"19"
"26"
]
},
{
"operatingsystem": "Debian",
"operatingsystemrelease": [
"6",
"7",
"8"
"8",
"9"
]
},
{
"operatingsystem": "Ubuntu",
"operatingsystemrelease": [
"12.04",
"14.04"
"14.04",
"16.04",
"18.04"
]
},
{
"operatingsystem": "FreeBSD",
"operatingsystemrelease": [
"10",
"11"
]
},
{
"operatingsystem": "DragonFly",
"operatingsystemrelease": [
"4"
]
},
{
"operatingsystem": "Archlinux"
}
]
}
View
@@ -0,0 +1,15 @@
---
# This file is managed via modulesync
# https://github.com/voxpupuli/modulesync
# https://github.com/theforeman/foreman-installer-modulesync
HOSTS:
centos-6-x64:
platform: centos-6-x86_64
box: centos/6
hypervisor: vagrant_libvirt
vagrant_memsize: 3072
CONFIG:
trace_limit: 200
masterless: true
...
# vim: syntax=yaml
View
@@ -0,0 +1,15 @@
---
# This file is managed via modulesync
# https://github.com/voxpupuli/modulesync
# https://github.com/theforeman/foreman-installer-modulesync
HOSTS:
centos-7-x64:
platform: centos-7-x86_64
box: centos/7
hypervisor: vagrant_libvirt
vagrant_memsize: 3072
CONFIG:
trace_limit: 200
masterless: true
...
# vim: syntax=yaml
View
@@ -0,0 +1,15 @@
---
# This file is managed via modulesync
# https://github.com/voxpupuli/modulesync
# https://github.com/theforeman/foreman-installer-modulesync
HOSTS:
debian-8-x64:
platform: debian-8-x86_64
box: debian/jessie64
hypervisor: vagrant_libvirt
vagrant_memsize: 3072
CONFIG:
trace_limit: 200
masterless: true
...
# vim: syntax=yaml
View
@@ -0,0 +1,15 @@
---
# This file is managed via modulesync
# https://github.com/voxpupuli/modulesync
# https://github.com/theforeman/foreman-installer-modulesync
HOSTS:
debian-9-x64:
platform: debian-9-x86_64
box: debian/stretch64
hypervisor: vagrant_libvirt
vagrant_memsize: 3072
CONFIG:
trace_limit: 200
masterless: true
...
# vim: syntax=yaml
View
@@ -0,0 +1,56 @@
require 'spec_helper_acceptance'
describe 'tftp with explicit daemon', :if => fact('osfamily') == 'RedHat' && fact('operatingsystemmajrelease') == '7' do
before(:all) do
on hosts, puppet('resource', 'service', 'xinetd', 'ensure=stopped', 'enable=false')
on hosts, puppet('resource', 'service', 'tftp.socket', 'ensure=stopped', 'enable=false')
end
after(:all) do
on hosts, puppet('resource', 'service', 'xinetd', 'ensure=stopped', 'enable=false')
on hosts, puppet('resource', 'service', 'tftp.socket', 'ensure=stopped', 'enable=false')
end
let(:pp) do
<<-EOS
class { '::tftp':
daemon => true,
}
file { "${::tftp::root}/test":
ensure => file,
content => 'clap your hands',
}
EOS
end
it_behaves_like 'a idempotent resource'
describe service('xinetd') do
it { is_expected.not_to be_enabled }
it { is_expected.not_to be_running }
end
describe service('tftp.socket') do
it { is_expected.to be_enabled }
it { is_expected.to be_running }
end
# This doesn't work on Travis - actual tftp testing is more reliable anyway
describe port(69), :unless => ENV['TRAVIS'] do
it { is_expected.to be_listening.with('udp') }
end
describe 'ensure tftp client is installed' do
on hosts, puppet('resource', 'package', 'tftp', 'ensure=installed')
end
describe command("echo get /test /tmp/downloaded_file | tftp #{fact('fqdn')}") do
its(:exit_status) { should eq 0 }
end
describe file('/tmp/downloaded_file') do
it { should be_file }
its(:content) { should eq 'clap your hands' }
end
end
View
@@ -0,0 +1,53 @@
require 'spec_helper_acceptance'
describe 'tftp with default parameters' do
before(:all) do
on hosts, puppet('resource', 'service', 'xinetd', 'ensure=stopped', 'enable=false')
end
after(:all) do
on hosts, puppet('resource', 'service', 'xinetd', 'ensure=stopped', 'enable=false')
end
let(:pp) do
<<-EOS
class { '::tftp': }
file { "${::tftp::root}/test":
ensure => file,
content => 'do the happy dance',
}
EOS
end
it_behaves_like 'a idempotent resource'
service_name = case fact('osfamily')
when 'RedHat'
'xinetd'
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.to be_listening.with('udp') }
end
describe 'ensure tftp client is installed' do
on hosts, puppet('resource', 'package', 'tftp', 'ensure=installed')
end
describe command("echo get /test /tmp/downloaded_file | tftp #{fact('fqdn')}") do
its(:exit_status) { should eq 0 }
end
describe file('/tmp/downloaded_file') do
it { should be_file }
its(:content) { should eq 'do the happy dance' }
end
end
View
@@ -1,116 +1,165 @@
require 'spec_helper'
describe 'tftp' do
context 'on RedHat' do
let :facts do
{
:osfamily => 'Redhat',
:operatingsystemrelease => '6.4',
}
end
it { should compile.with_all_deps }
it 'should include classes' do
should contain_class('tftp::install')
should contain_class('tftp::config')
should contain_class('tftp::service')
end
it 'should install packages' do
should contain_package('tftp-server').with({
:ensure => 'installed',
:alias => 'tftp-server',
})
should contain_package('syslinux').with_ensure('installed')
end
it 'should configure xinetd' do
should contain_class('xinetd')
should contain_xinetd__service('tftp').with({
:port => '69',
:server => '/usr/sbin/in.tftpd',
:server_args => '-v -s /var/lib/tftpboot/ -m /etc/tftpd.map',
:socket_type => 'dgram',
:protocol => 'udp',
:cps => '100 2',
:flags => 'IPv4',
:per_source => '11',
})
should contain_file('/etc/tftpd.map').
with_content(%r{^# Convert backslashes to slashes}).
with_mode('0644')
should contain_file('/var/lib/tftpboot/').with({
:ensure => 'directory',
:notify => 'Class[Xinetd]',
})
end
it 'should not contain the service' do
should_not contain_service('tftpd-hpa')
end
end
context 'on Debian' do
let :facts do
{
:osfamily => 'Debian',
:operatingsystem => 'Debian',
}
end
it 'should include classes' do
should contain_class('tftp::install')
should contain_class('tftp::config')
should contain_class('tftp::service')
end
it 'should install packages' do
should contain_package('tftpd-hpa').with({
:ensure => 'installed',
:alias => 'tftp-server',
})
should contain_package('syslinux').with_ensure('installed')
end
it 'should not configure xinetd' do
should_not contain_class('xinetd')
should_not contain_xinetd__service('tftp')
end
it 'should contain the service' do
should contain_service('tftpd-hpa').with({
:ensure => 'running',
:enable => true,
:alias => 'tftpd',
:subscribe => 'Class[Tftp::Config]',
})
end
end
context 'on Debian/jessie' do
let :facts do
{
:osfamily => 'Debian',
:operatingsystem => 'Debian',
:operatingsystemrelease => '8.0'
}
end
it 'should install Debian/jessie specific packages' do
should contain_package('pxelinux').with_ensure('installed')
should contain_package('syslinux-common').with_ensure('installed')
on_supported_os.each do |os, facts|
context "on #{os}" do
let(:facts) { facts }
it { should compile.with_all_deps }
it 'should include classes' do
should contain_class('tftp::install')
should contain_class('tftp::config')
should contain_class('tftp::service')
end
it 'should install default package' do
tftp_package = case facts[:osfamily]
when 'RedHat'
'tftp-server'
when 'Debian'
'tftpd-hpa'
else
'tftp-hpa'
end
should contain_package(tftp_package).with({
:ensure => 'installed',
:alias => 'tftp-server',
})
if facts[:operatingsystem] == 'Debian' ||
(facts[:operatingsystem] == 'Ubuntu' && facts[:operatingsystemrelease].to_i >= 16)
should contain_package('pxelinux').with_ensure('installed')
should contain_package('syslinux-common').with_ensure('installed')
else
should contain_package('syslinux').with_ensure('installed')
end
end
if facts[:osfamily] == 'RedHat'
it 'should configure xinetd' do
should contain_class('xinetd')
should contain_xinetd__service('tftp').with({
:port => '69',
:server => '/usr/sbin/in.tftpd',
:server_args => '-v -s /var/lib/tftpboot -m /etc/tftpd.map',
:socket_type => 'dgram',
:protocol => 'udp',
:cps => '100 2',
:flags => 'IPv4',
:per_source => '11',
})
should contain_file('/etc/tftpd.map').with({
:source => 'puppet:///modules/tftp/tftpd.map',
:mode => '0644',
})
should contain_file('/var/lib/tftpboot')
.with_ensure('directory')
.that_notifies('Class[Xinetd]')
end
it 'should not contain the service' do
should_not contain_service('tftpd-hpa')
end
elsif facts[:osfamily] == 'FreeBSD'
it 'should not configure xinetd' do
should_not contain_class('xinetd')
should_not contain_xinetd__service('tftp')
end
it 'should contain the service' do
should contain_service('tftpd').with({
:ensure => 'running',
:enable => true,
:alias => 'tftpd',
:subscribe => 'Class[Tftp::Config]',
})
end
elsif facts[:osfamily] == 'Archlinux'
it 'should not configure xinetd' do
should_not contain_class('xinetd')
should_not contain_xinetd__service('tftp')
end
it 'should contain the service' do
should contain_service('tftpd.socket').with({
:ensure => 'running',
:enable => true,
:alias => 'tftpd',
:subscribe => 'Class[Tftp::Config]',
})
end
else
it 'should not configure xinetd' do
should_not contain_class('xinetd')
should_not contain_xinetd__service('tftp')
end
it 'should contain the service' do
should contain_service('tftpd-hpa').with({
:ensure => 'running',
:enable => true,
:alias => 'tftpd',
:subscribe => 'Class[Tftp::Config]',
})
end
if facts[:operatingsystem] == 'Ubuntu' && facts[:operatingsystemrelease] == '16.04'
it { should contain_service('tftpd-hpa').with_provider('systemd') }
end
end
context 'with root set to /changed' do
let :params do {
:root => '/changed',
} end
if facts[:osfamily] == 'RedHat'
it 'should set root to non-default value in xinetd config' do
should contain_xinetd__service('tftp').with({
:server_args => '-v -s /changed -m /etc/tftpd.map',
})
end
else
# not supported
end
end
context 'with custom tftp package set to tftp-hpa-destruct' do
let :params do {
:package => 'tftp-hpa-destruct',
} end
it 'should install custom tftp package' do
should contain_package('tftp-hpa-destruct').with({
:ensure => 'installed',
:alias => 'tftp-server',
})
end
end
context 'with custom syslinux package set to my-own-syslinux' do
let :params do {
:syslinux_package => 'my-own-syslinux',
} end
it 'should install custom syslinux package' do
should contain_package('my-own-syslinux').with({:ensure => 'installed',})
end
end
end
end
context 'on Amazon Linux' do
let :facts do
{
:operatingsystem => 'Amazon',
:osfamily => 'Linux',
:osfamily => 'Linux',
:os => { :name => 'Amazon', :family => 'Linux' }
}
end
@@ -134,66 +183,26 @@
should contain_xinetd__service('tftp').with({
:port => '69',
:server => '/usr/sbin/in.tftpd',
:server_args => '-v -s /var/lib/tftpboot/ -m /etc/tftpd.map',
:server_args => '-v -s /var/lib/tftpboot -m /etc/tftpd.map',
:socket_type => 'dgram',
:protocol => 'udp',
:cps => '100 2',
:flags => 'IPv4',
:per_source => '11',
})
should contain_file('/etc/tftpd.map').
with_content(%r{^# Convert backslashes to slashes}).
with_mode('0644')
should contain_file('/var/lib/tftpboot/').with({
:ensure => 'directory',
:notify => 'Class[Xinetd]',
should contain_file('/etc/tftpd.map').with({
:source => 'puppet:///modules/tftp/tftpd.map',
:mode => '0644',
})
should contain_file('/var/lib/tftpboot')
.with_ensure('directory')
.that_notifies('Class[Xinetd]')
end
it 'should not contain the service' do
should_not contain_service('tftpd-hpa')
end
end
context 'on RedHat with root set to /tftpboot' do
let :facts do {
:osfamily => 'Redhat',
:operatingsystemrelease => '6.4',
} end
let :params do {
:root => '/tftpboot',
} end
it 'should set root to non-default value in xinetd config' do
should contain_xinetd__service('tftp').with({
:server_args => '-v -s /tftpboot -m /etc/tftpd.map',
})
end
end
context 'on unsupported Linux operatingsystem' do
let :facts do
{
:operatingsystem => 'unsupported',
:osfamily => 'Linux',
}
end
it 'should fail' do
should raise_error(Puppet::Error, /: This module does not support operatingsystem #{facts[:operatingsystem]}/)
end
end
context 'on unsupported osfamily' do
let :facts do
{:osfamily => 'unsupported'}
end
it 'should fail' do
should raise_error(Puppet::Error, /: This module does not support osfamily #{facts[:osfamily]}/)
end
end
end
View
@@ -1,6 +1,5 @@
--format
documentation
--colour
--loadby
mtime
--backtrace
View
@@ -6,7 +6,59 @@
require 'rspec-puppet-facts'
include RspecPuppetFacts
# Original fact sources:
add_custom_fact :puppet_environmentpath, '/etc/puppetlabs/code/environments' # puppetlabs-stdlib
add_custom_fact :root_home, '/root' # puppetlabs-stdlib
# Workaround for no method in rspec-puppet to pass undef through :params
class Undef
def inspect; 'undef'; end
end
# Running tests with the ONLY_OS environment variable set
# limits the tested platforms to the specified values.
# Example: ONLY_OS=centos-7-x86_64,ubuntu-14-x86_64
def only_test_os
if ENV.key?('ONLY_OS')
ENV['ONLY_OS'].split(',')
end
end
# Running tests with the EXCLUDE_OS environment variable set
# limits the tested platforms to all but the specified values.
# Example: EXCLUDE_OS=centos-7-x86_64,ubuntu-14-x86_64
def exclude_test_os
if ENV.key?('EXCLUDE_OS')
ENV['EXCLUDE_OS'].split(',')
end
end
# Use the above environment variables to limit the platforms under test
def on_os_under_test
on_supported_os.reject do |os, facts|
(only_test_os() && !only_test_os.include?(os)) ||
(exclude_test_os() && exclude_test_os.include?(os))
end
end
def get_content(subject, title)
is_expected.to contain_file(title)
content = subject.resource('file', title).send(:parameters)[:content]
content.split(/\n/).reject { |line| line =~ /(^#|^$|^\s+#)/ }
end
def verify_exact_contents(subject, title, expected_lines)
expect(get_content(subject, title)).to match_array(expected_lines)
end
def verify_concat_fragment_contents(subject, title, expected_lines)
is_expected.to contain_concat__fragment(title)
content = subject.resource('concat::fragment', title).send(:parameters)[:content]
expect(content.split("\n") & expected_lines).to match_array(expected_lines)
end
def verify_concat_fragment_exact_contents(subject, title, expected_lines)
is_expected.to contain_concat__fragment(title)
content = subject.resource('concat::fragment', title).send(:parameters)[:content]
expect(content.split(/\n/).reject { |line| line =~ /(^#|^$|^\s+#)/ }).to match_array(expected_lines)
end
View
@@ -0,0 +1,46 @@
require 'beaker-puppet'
require 'beaker-rspec'
require 'beaker/puppet_install_helper'
require 'beaker/module_install_helper'
run_puppet_install_helper unless ENV['BEAKER_provision'] == 'no'
install_module_on(hosts)
install_module_dependencies_on(hosts)
RSpec.configure do |c|
# Readable test descriptions
c.formatter = :documentation
# Configure all nodes in nodeset
c.before :suite do
# Install module and dependencies
hosts.each do |host|
if fact_on(host, 'osfamily') == 'RedHat'
# don't delete downloaded rpm for use with BEAKER_provision=no +
# BEAKER_destroy=no
on host, 'sed -i "s/keepcache=.*/keepcache=1/" /etc/yum.conf'
# refresh check if cache needs refresh on next yum command
on host, 'yum clean expire-cache'
end
end
end
end
shared_examples 'a idempotent resource' do
it 'applies with no errors' do
apply_manifest(pp, catch_failures: true)
end
it 'applies a second time without changes' do
apply_manifest(pp, catch_changes: true)
end
end
shared_examples 'the example' do |name|
let(:pp) do
path = File.join(File.dirname(File.dirname(__FILE__)), 'examples', name)
File.read(path)
end
include_examples 'a idempotent resource'
end