Unable to utilize external gems with foreman-hooks

I’m trying to use ruby-kafka gem alongside foreman-hooks, but I’m unable to do so.

My hook script looks something like this:

#!/usr/local/rvm/rubies/ruby-2.7.1/bin/ruby

require 'kafka'
kafka = Kafka.new([ENV['KAFKA_BROKER']])

host_info = $stdin.read
hook_event = ARGV[0]

kafka.deliver_message(host_info, key: hook_event, topic: ENV['KAFKA_TOPIC'])

When trying to update the host using the API get the following response back:

"Hook: /usr/share/foreman/config/hooks/host/managed/postupdate/1000-post-update.rb task failed with the following error: Hook failure running/usr/share/foreman/config/hooks/host/managed/postupdate/1000-post-update.rb postupdate becky-lidstone.xxx.cloud: Ignoring bcrypt-3.1.12 because its extensions are not built. Try: gem pristine bcrypt --version 3.1.12\nIgnoring ffi-1.11.3 because its extensions are not built. Try: gem pristine ffi --version 1.11.3\nIgnoring nio4r-2.3.1 because its extensions are not built. Try: gem pristine nio4r --version 2.3.1\nIgnoring nokogiri-1.8.4 because its extensions are not built. Try: gem pristine nokogiri --version 1.8.4\nNOTE: Gem::Specification#rubyforge_project= is deprecated with no replacement. It will be removed on or after 2019-12-01.\nGem::Specification#rubyforge_project= called from /opt/theforeman/tfm/root/usr/share/gems/specifications/passenger-4.0.18.gemspec:19.\nIgnoring passenger-4.0.18 because its extensions are not built. Try: gem pristine passenger --version 4.0.18\nIgnoring pg-1.1.4 because its extensions are not built. Try: gem pristine pg --version 1.1.4\nIgnoring rkerberos-0.1.5 because its extensions are not built. Try: gem pristine rkerberos --version 0.1.5\nIgnoring unf_ext-0.0.7.2 because its extensions are not built. Try: gem pristine unf_ext --version 0.0.7.2\nIgnoring unicode-0.4.4.4 because its extensions are not built. Try: gem pristine unicode --version 0.4.4.4\nIgnoring websocket-driver-0.7.0 because its extensions are not built. Try: gem pristine websocket-driver --version 0.7.0\n/usr/local/rvm/rubies/ruby-2.7.1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in require’: cannot load such file – kafka (LoadError)\n\tfrom /usr/local/rvm/rubies/ruby-2.7.1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in require'\n\tfrom /usr/share/foreman/config/hooks/host/managed/postupdate/1000-post-update.rb:3:in '\n"`

I tried the steps mentioned in this post: Post but it doesn’t work.

Foreman is running ruby 2.0.0 while the script uses ruby 2.7.1 (since ruby-kaka requires ruby >= 2.2). I could update foreman to ruby 2.7.1 but I’m not sure how to do that, and I’m wary that I might break it.

Close, but not quite. Foreman itself runs using the the rh-ruby25 SCL on EL7. The “fun” that Ruby is, is it sets GEM_HOME and GEM_PATH as an environment variable. That is set to the rh-ruby25 path, which is why it can’t find all the native gems.

The typical solution to this is clean those variables. I don’t know if it works inside the script though. If it doesn’t you may need a small bash wrapper for your actual hook that does so.

A cleaner long term solution is to submit a patch to the plugin to do so.

You can also make sure the kafka gem is available in the rh-ruby25 SCL and use #!/usr/bin/env ruby (which will give you Ruby 2.5).

1 Like

Thanks! Just wondering, if I change those variables to point to the native gem path, will it interfere with Foreman?

Inside the script: no
Outside of the script: yes - this can break Foreman.

Here is a code sample how we clean the env in our installer:

Ahh, thanks. I’m pretty new to the Ruby (and Foreman) ecosystem, so I’m still getting used to it. Much appreciated. I’ll try your suggestions and see if they work.

FYI we are working on foreman_webhooks plugin which will make this kind of stuff much easeier. You could take your integration to a separate VM/container into a clean environment easily. Stay tuned for the next release!

1 Like