Sensu-install missing on docker image

Yes this:

sure looks like it will help. I’m still unclear as to whether you guys are going to build the sensu-plugins-plivo under @aaronsachs, or if I should begin trying to get it to build for me.

I can’t speak for @aaronsachs but i would imagine he’ll respin the asset with the one-liner fix when he’s got a few minutes.

But you mentioned that you had a local ruby script that you started with. Can you share that? I might have found a simple pattern for generating assets from pure ruby scripts (that do not require native extension libraries) So if you can share the original ruby script you were trying to get working on alpine I may be able to use it a test to build simplified instructions for this sort of thing.

yeah here’s the simple plivo.rb we were using with sensu-classic

#!/usr/bin/env ruby
require 'sensu-handler'
require 'timeout'
require 'net/http'
require 'open-uri'

class Plivo < Sensu::Handler
  def short_name
    @event['client']['name'] + '/' + @event['check']['name']
  end

  def action_to_string
    @event['action'].eql?('resolve') ? 'RESOLVED' : 'ALERT'
  end

  def status_to_string
    case @event['check']['status']
    when 0
      'OK'
    when 1
      'WARNING'
    when 2
      'CRITICAL'
    else
      'UNKNOWN'
    end
  end

  def handle
    url = URI.parse("https://api.plivo.com/v1/Account/#{settings['plivo']['auth_id']}/Message/")
    txt = "#{action_to_string} #{short_name}: "
    num_chars = 160 - txt.length - 1
    txt += (@event['check']['output'] || '')[0..num_chars]
    params = {
      src: ENV["FROM"],
      dst: ENV["TO"].join('<'),
      text: txt
    }

    req = Net::HTTP::Post.new(url.path)
    req.basic_auth(ENV["AUTH_ID"], ENV["AUTH_TOKEN"])
    req.set_content_type 'application/json'
    req.body = params.to_json
    begin
      timeout(10) do
        resp = Net::HTTP.start(url.host, url.port, use_ssl: true) { |http| http.request(req) }
        puts "plivo -- sent alert for #{short_name} to #{settings['plivo']['to'].join(',')}."
      end
    rescue Timeout::Error
      puts 'plivo -- timed out while attempting to ' + @event['action'] + ' a incident -- ' + short_name
    end
  end
end

cool,
I’ll use that to test a possible asset build pattern using bundler/inline to generate local build assets quickly.

I’m going to spin up a couple of new branchers in the helper repository:

To prototype some new on-ramps for people working with ruby outside of the sensu-plugins github org.

  1. I’m going to prototype a way to use bundler/inline pattern for simple ruby like your script, for people who don’t want to build a full ruby gem…contrary to sensu-plugins github org practice…but a valid use of ruby.

  2. Document a simple patterns to follow if you just want to build and test locally, without the complexity of using TravisCI to manage the build/deploy. The one thing about CI automation is its perhaps not great for learning as the automation abstractions complicate the ‘required’ steps…but its great for automating long term.

This should help people like yourself understand the process and be able to start building assets for your own private use.

Well ok I can get travis to build but I’m still unclear about thses steps:

  1. Create Github release conforming to semver pre-release (ex: 4.0.0-bonsai.0.1 is a pre-release for a 4.0.0 release)
  2. TravisCI should now populate the Github release with binary assets
  3. Optional: Register your forked repository with Bonsai and tag your asset as Experimental.

The travis build completes but says:

Skipping a deployment with the script provider because this is not a tagged commit
Done. Your build exited with 0.

Okay sorry the plugin you found on github is just broken… it was written against a very old Plivo ruby SDK. The methods its using to interact with plivo module no longer exist in latest version of the Plivo ruby sdk as per Plivo SDK documentation.

This is a rabbithole of pain. So here’s a lesson here for sure… gotta make sure the plugin works before you try to create an asset… else tons of problems.

Let me circle back and get you a pattern that will work for the thing you wrote. The 4 year old unmaintained plugin you found on github needs some love just to get working.

ok thanks. That’s such a bummer.

yes right now the travis scripting i put together for sensu-plugins did all the asset build stuff as a deployment step that only happens on tagged releases…because part of its work has to populate a release (hence the need for a tag).

for now to get the deploy section to fire, you have to make a release in github UI, and travis will set the necessary environment variables to trigger the deployment portion of the travis config.

Hey @billm,
Thanks for hanging in. Sorry for the frustration over this. I didn’t anticipate this sort of one-off ruby script, and the asset building process I put together to help ease migration was centered around the sensu-plugins org pattern that packaged all operational checks as ruby gems. Being published gems… is was what made sensu-install work, as it was essentially wrapper around gem.

Looking at your script, the only thing that is really hanging you up is the fact that you depend on the sensu-plugin gem (which provides the sensu-handler library) all the rest of your requirements are in fact provided by the ruby install. Naively I would see we need to include that in the ruby-runtime…but thinking about it… I’m not so sure that’s a good idea…because I expect the sensu-plugin to have a major version jump soon that potentially breaks compatibility with classic…now that clasic is EOL… and I don’t want to encourage users like you to depend on something implicitly and have it break under you.

So there’s a couple of ways forward here for you right now that will work better for you in the long run.

Option 1: Make your script a proper gem

You can turn your script into a proper gem by adding a gemspec file that captures the gem dependencies and other information. It doesn’t have to be as feature complete as the gemspec files in the repositories maintained sensu-plugins org on your first go. But once you are able to turn your script into a gem, then you would be able to create a sharable asset that depends on the ruby-runtime asset in a reliable manner.

You don’t even have to official publish it in the rubygems listing. Just making it a proper gem with a gemspec that works to locally build and install your script is enough to make it possible to reliably build an asset from it.

Now this is the best option for you as well, as you’ll be able to encode exactly the sensu-plugin version dependency that your script relies on in such a way to avoid unnecessary breakage. Right now you are just sort of assuming the sensu-plugin version that is already in the existing ruby environment, but if that had a major version bump and changed its methods… your script would stop working…because you didn’t pin your dependency. gem has a very robust dependencie rules langauge so you can express semver compliant dep rules so that you can do things like pin to a specific patch version or allow for patch updates or even really complicated filtering. In your case you’d want to pin to the sensu-plugin 4.x.y series to get sensu Go event mapping support, but a bump to 5.x.y may break compatibility.

Option 2: Build a custom Docker image

You can make your own docker image based on the official sensu docker image, that includes the ruby version you need and load it up with whatever gems your in-house scripts depend on. You could them package up your script easily as an asset, that only worked in your special environment. You wouldn’t share that asset in Bonsai, because its tailored to your environment and would break for other people. But this gives you maximum flexibility as an operator to call the shots and get the ruby environment you need.

This isn’t actually that hard to do… building a new Docker image from an existing image is quite easy. In fact the ruby-runtime we’ve spun up does exactly this to produce Docker iamges for assets to build against. But instead of starting with the official sensu image it starts with the base images of target distributions (like the official alpine docker image). And its perfectly okay to have these sort of one-off in-house scripts…but the trade-off is the environment has to be tailored a bit to ensure the scripts have what they need to operate.

My thoughts on containers + ruby plugins
iI you migrating from a more traditional VM workload… you’ll probably have a much easier time starting with a debian or centos VM and installing Sensu packages for those environments…unless you are prepared to spin up your own customized Sensu containers.

I look at it this way, containers are really lightweight virtual machines that are tasked to run exactly one command (with some guardrails to keep them from interacting with each other). You have the freedom to prepare exactly what that environment looks like. The official docker image Sensu provides is intended as a starting point to help people who are moving into containerized workloads… so users don’t have to roll their own container from scratch. And in that environment golang staticly build Sensu assets are preferred…because it keeps the container small…very small. Adding things like perl or python or ruby quickly bloats the container…and it starts looking like a tradition linux VM very quickly…defeating the point of being a container to some extent.

So I’m not really sure the alpine containerized Sensu is the right Sensu install for you if you need to rely on plugins that cannot be statically compiled. It’s a bit of a rabbithole of pain… even with bash scripts…because the alpine based container is stripped back so far that you can’t be sure you have all the normal things you come to expect from a “linux distribution” out of the box.

We are able to provide a ruby runtime for the sensu-plugins org primarily because sensu-plugins org is very structured in what is allowed. But even then there are caveats that just don’t translate into a containerize workflow that requires you as the operator to tweak the container environment a little bit.

For example, just ran across a sensu-plugins check today that calls python from inside ruby with no way to capture that dependency in gem’s rules. That’s crazy pants sort of stuff in a container, but in a VM… easy fix for an operator to just make sure the python packages are installed…by tweaking the running environment. And that’s okay…its just not a workflow that makes sense for containers.

1 Like

Option 3: Roll a custom ruby-runtime asset for you to use locally

Middle ground here, if you still want to use the official sensu docker image…
you can create a custom ruby-runtime asset based on the official one that includes additional gems. Now you are controlling the ruby environment for your private stuff…but still using the vendor provided Sensu container image. As long as your runtime matches the same ruby major.minor version as the one sensu-plugins assets build against… should work for you.

Hey @billm!

You might be interested in this. I found a possible way forward for streamlining the creation of Sensu assets for simple one-file ruby plugins like your example using bundler/inline

This is definitely not a good option for all situations, as it depends on runtime access to rubygems to install any gem dependencies needed the first time the sensu-backend or sensu-agent runs the plugin command. It’s bound to fall over if your ruby script depends on native extension libraries or if your target host doesn’t have access to the internet to download a from rubygem. But it gets around having to create a proper gem for a single ruby script that you are using in-house.

Take a look at this github repo branch:
https://github.com/jspaleta/sensu-asset-playground/tree/bundler-inline-asset/bundler-inline-asset

I have a simple handler plugin example that makes use of bundle/inline to pull the missing sensu-plugins gem the first time its run if its needed. The build.sh in the example directory will generate a Sensu asset that should work on any platform supported by the sensu-ruby-runtime asset (including the official sensu docker container)…as long as the host/container has access to the internet and can pull the required gems.

It uses a little bit of shell wrapper magic to ensure that the bundler is installed, so you’ll want to read over the ruby files in the example asset bin/ and rubyexec/ directory. They are the same name,but they are not the same file.

Hey @jspaleta-

Just wanted to follow up on this quickly. I ended up re-writing the handler for plivo in go. Much easier in the long run. Had I known a bit more about sensu-go ( or go itself for that matter) before embarking on this migration, I probably would have skipped directly to doing that.

Truth is this migration was my first task at a new gig and I wanted to make sure all of the stuff they’re using was supported before I continued on. In hindsight I should have just skipped over this handler, gotten all of the checks working, then come back to it. I just didn’t want to quit at my FIRST task! Anyway, all up and running now. I’m no go expert but it took all of a morning to get it working, even given the fact that plivo’s go SDK was a bit broken.