The chef systemd resource allows you to specify the service file via a content attribute (which takes a string or a hash). Both of these feel like an offensively bad idea; their example is:
systemd_unit 'sysstat-collect.timer' do
content <<-EOU.gsub(/^\s+/, '')
[Unit]
Description=Run system activity accounting tool every 10 minutes
[Timer]
OnCalendar=*:00/10
[Install]
WantedBy=sysstat.service
EOU
action [:create, :enable]
end
This feel so very wrong... mixing my chef recipe with what should just be a config file (or templated file). I've tried various permuations of trying to write the file to my target (using cookbook_file) and then reading that back in to pass to content, but that also feels unsatisfying and so far hasn't worked.
Edit to ask a hopefully better question:
Is there some mechanism to use the chef systemd resource such that I'm not embedded configuration files as strings in the recipe file itself?
I thought much the same when I first started using systemd_unit
, but now I look at it differently. I don't keep JSON, YAML, or TOML config files as templates, because they can be generated from attribute hashes. That ensures that they're syntactically correct and it's more flexible to change an attribute than a cookbook file. Units are INI-format files, so I treat them the same way.
Sometimes, though, you just need to read a text file and pass it to a resource. I'm sure that this method can be improved, but it does the job.
unit_temp_path = "#{Chef::Config[:file_cache_path]}/foo.service"
cookbook_file unit_temp_path do
action :create
end
systemd_unit 'foo.service' do
# delay reading until convergence phase
content lazy { ::File.read(unit_temp_path) }
action :create
end