Foon
Foon

Reputation: 6488

Working around chef's systemd_unit resource

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?

Upvotes: 2

Views: 4908

Answers (3)

lkd
lkd

Reputation: 1

I'm not sure which of two problems the OP is facing:

  • Not put raw strings into systemd_unit
  • systemd_unit misbehaves when setting up units that aren't .service

I have experienced issues using the systemd_unit resource on Chef13 for non- .timer and non- .service units. Specifically it seems to hate .network and .netdev, which forced me to use template_file chained to something that would call systemctl daemon-reload after :/

As for not putting raw Strings into a systemd_unit, maybe the following sample can help?

systemd_unit 'portage-sync.timer' do
  verify true
  content(
    Unit: {
      Description: 'Timer to synchronize portage tree',
    },
    Timer: {
      OnCalendar: '*-*-* 12:00:00 UTC',
      Persistent: true,
      RemainAfterElapse: true,
      Unit: 'portage-sync.service',
    },
    Install: {
      WantedBy: 'multi-user.target',
    },
  )
end

Upvotes: 0

John Schnare
John Schnare

Reputation: 56

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

Upvotes: 4

coderanger
coderanger

Reputation: 54267

You can use something like template "/etc/systemd/system/#{unit_name}" do ... end and a notification for the daemon-reload.

Upvotes: 2

Related Questions