How to update grub with puppet?
For the quoting part, you could use augeasproviders
's shellvar
provider and force the quoting style:
shellvar { 'GRUB_CMDLINE_LINUX':
ensure => present,
target => '/etc/default/grub',
value => 'cgroup_enable=memory',
quoted => 'double',
}
This will use Augeas internaly (as a Ruby library) on the agent, only in a smarter way.
As for appending to existing values, there's two options:
- Get the current value using a fact (use for example
augeasfacter
to retrieve it), analyze it in your manifest and append to it using theshellvar
type; - Improve the
shellvar
provider so that it appends to the value instead of replacing it.
First option
The fact
The following file can be distributed in your module in ${modulepath}/${modulename}/lib/facter/grub_cmdline_linux.rb
and deployed using pluginsync
.
require 'augeas'
Facter.add(:grub_cmdline_linux) do
setcode do
Augeas.open(nil, '/', Augeas::NO_MODL_AUTOLOAD) do |aug|
aug.transform(
:lens => 'Shellvars.lns',
:name => 'Grub',
:incl => '/etc/default/grub',
:excl => []
)
aug.load!
aug.get('/files/etc/default/grub/GRUB_CMDLINE_LINUX').gsub(/['"]/, '')
end
end
end
This will return the current value of the fact as a string, and remove the quotes around the value. It requires the Augeas Ruby library on the agent, which I suppose you have if you use the augeas
type already.
Puppet code
The next step is to make use of this value to check if your target value is included. You can split the string and use the stlib
module functions for this:
$value = 'cgroup_enable=memory'
# Split string into an array
$grub_cmdline_linux_array = split($::grub_cmdline_linux, ' ')
# Check if $value is already there to determine new target value
$target = member($grub_cmdline_linux_array, $value) ? {
true => $grub_cmdline_linux_array,
false => flatten([$grub_cmdline_linux_array, $value]),
}
# Enforce new target value
# Use the array and force the 'string' array type
shellvar { 'GRUB_CMDLINE_LINUX':
ensure => present,
target => '/etc/default/grub',
value => $target,
array_type => string,
}
Run it
Notice: /Stage[main]//Shellvar[GRUB_CMDLINE_LINUX]/value: value changed ['quiet splash usbcore.old_scheme_first=1'] to 'quiet splash usbcore.old_scheme_first=1 cgroup_enable=memory'
Check idempotence:
Notice: Finished catalog run in 0.17 seconds
Second option
If you'd like to have a go at the second option, the best way would probably be to send a (nice) PR to augeasproviders
's shellvar
type adding an array_append
parameter (or a better name):
shellvar { 'GRUB_CMDLINE_LINUX':
ensure => present,
target => '/etc/default/grub',
value => 'cgroup_enable=memory',
array_append => true,
array_type => 'double',
}
This parameter would treat the value as an array, and append to the existing values if the value is not found already. This would require Ruby coding, but would be reusable in lots of other cases ;-)
Hint: this should happen here.
(for ubuntu users only)
As altering /etc/default/grub is not so nice ..
Just deploy /etc/default/grub.d/memory.cfg
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX cgroup_enable=memory"
Then update-grub
(see the /etc/default/grub.d/*.cfg feature )