Module: ForemanHooks::Util

Extended by:
ActiveSupport::Concern
Included in:
CallbackHooks, OrchestrationHook
Defined in:
lib/foreman_hooks/util.rb

Defined Under Namespace

Classes: RablScope

Instance Method Summary collapse

Instance Method Details

#exec_hook(*args) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/foreman_hooks/util.rb', line 36

def exec_hook(*args)
  unless File.executable?(args.first)
    logger.warn("Hook #{args.first} no longer exists or isn't executable, so skipping execution of the hook. The server should be restarted after adding or removing hooks.")
    return true
  end

  logger.debug "Running hook: #{args.join(' ')}"
  success, output = if defined? Bundler && Bundler.responds_to(:with_clean_env)
                      Bundler.with_clean_env { exec_hook_int(render_hook_json, *args) }
                    else
                      exec_hook_int(render_hook_json, *args)
                    end
  # Raising here causes Foreman Orchestration to correctly show error bubble in GUI
  raise ForemanHooks::Error.new "Hook failure running `#{args.join(' ')}`: #{$?} #{output}" unless success
  success
end

#exec_hook_int(stdin_data, *args) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/foreman_hooks/util.rb', line 53

def exec_hook_int(stdin_data, *args)
  # Set environment vars available in hook scripts
  # Name of active Foreman user:
  ENV['FOREMAN_HOOKS_USER'] = User.current.

  args.map!(&:to_s)
  output, status = if Open3.respond_to? :capture2e
    Open3.capture2e(*args.push(:stdin_data => stdin_data))
  else  # 1.8
    Open3.popen3(*args) do |stdin,stdout,stderr|
      begin
        stdin.write(stdin_data)
        stdin.close
      rescue Errno::EPIPE
        logger.debug "Foreman hook input data skipped, closed pipe"
      end
      # we could still deadlock here, it'd ideally select() on stdout+err
      output = stderr.read
    end
    [output, $?]
  end
  logger.debug "Hook output: #{output}" if output && !output.empty?
  [status.success?, output]
end

#rabl_pathObject



19
20
21
# File 'lib/foreman_hooks/util.rb', line 19

def rabl_path
  "api/v2/#{render_hook_type.tableize}/show"
end

#render_hook_jsonObject



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/foreman_hooks/util.rb', line 23

def render_hook_json
  # APIv2 has some pretty good templates.  We could extend them later in special cases.
  # Wrap them in a root node for pre-1.4 compatibility
  view_path = ActionController::Base.view_paths.collect(&:to_path)
  json = Rabl.render(self, rabl_path,
                     view_path: view_path, format: :json, scope: RablScope.new)
  %Q|{"#{render_hook_type}":#{json}}|
rescue => e
  logger.warn "Unable to render #{self} (#{self.class}) using RABL: #{e.message}"
  logger.debug e.backtrace.join("\n")
  self.to_json
end

#render_hook_typeObject



6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/foreman_hooks/util.rb', line 6

def render_hook_type
  case self.class.name
    when "Host::Managed"
      'host'
    when "Host::Discovered"
      'discovered_host'
    when "Audited::Adapters::ActiveRecord::Audit", "Audited::Audit"
      'audit'
    else
      self.class.name.downcase
  end
end