Search code examples
rubychef-infrachef-recipe

How do I add multiline statement inside chef gaurd?


In my recipe I have following resource that restart the computer but I want to apply guard on this resource.

powershell_script "Restart Computer" do
code <<-EOH

    $computer_name=$env:COMPUTERNAME
    Restart-Computer -ComputerName $computer_name
    EOH
    guard_interpreter :powershell_script
    only_if reboot_pending?
end

I googled and found following ruby script for checking machine required reboot or not

def reboot_pending?

  # don't break when used as a mixin in contexts without #node (e.g. specs).
  if self.respond_to?(:node, true) && node.run_context.reboot_requested?
    true
  elsif platform?("windows")
    # PendingFileRenameOperations contains pairs (REG_MULTI_SZ) of filenames that cannot be updated
    # due to a file being in use (usually a temporary file and a system file)
    # \??\c:\temp\test.sys!\??\c:\winnt\system32\test.sys
    # http://technet.microsoft.com/en-us/library/cc960241.aspx
    registry_value_exists?('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager', { :name => 'PendingFileRenameOperations' }) ||

    # RebootRequired key contains Update IDs with a value of 1 if they require a reboot.
    # The existence of RebootRequired alone is sufficient on my Windows 8.1 workstation in Windows Update
    registry_key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired') ||

    # Vista + Server 2008 and newer may have reboots pending from CBS
    registry_key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootRequired') ||

    # The mere existence of the UpdateExeVolatile key should indicate a pending restart for certain updates
    # http://support.microsoft.com/kb/832475
    (registry_key_exists?('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile') &&
          !registry_get_values('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile').select { |v| v[:name] == "Flags" }[0].nil? &&
          [1,2,3].include?(registry_get_values('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile').select { |v| v[:name] == "Flags" }[0][:data]))
  elsif platform?("ubuntu")
    # This should work for Debian as well if update-notifier-common happens to be installed. We need an API for that.
    File.exists?('/var/run/reboot-required')
  else
    false
  end
end

I tried to add this method inside guard but its not working.Is there any way to write multiline statement inside chef guard?


Solution

  • Chef guards take in a block, like the first example here. Blocks can be multi line, but can't have methods declared inside of them. If you copy the contents of the method you found and put them inside the only_if that should work.

    powershell_script "Restart Computer" do
      ...
      only_if do
        <contents of method here>
      end
    end
    

    While this will work, the cleaner way to implement such an extensive guard is to put the reboot_pending method in a library and call that method from your recipe.