Chef http_request

Hello guys,

I’m trying to create a recipe that should check (using api calls) if a alert/notification/dashboard exists in our grafana server and if it does not exists, then is should POST it.

Until now I was using a bash script called by the chef-client after checking if grafana was up-and-running, using an API key. But I’ve discovered http_request resource and I thought that this should make my life easier and the code easily understood.

Checking the chef docs, I’ve discovered that there is not enough info about this resource. What I am looking for is to use json files built from erb templates and pass them as some attributes to the api calls.
Is this feasible? Is there a better method?

Any examples of success?

Thank you,
Gabriel

In the meantime I’ve discovered how to use http_request.
For anyone looking:
email.json.erb:

{
  "name": "<%= @notification_name %>",
  "type":  "email",
  "isDefault": <%= @isdefault %>,
  "settings": {
    "addresses": "<%= @notif_email %>"
  }
}

hipchat.json.erb:

{
  "name":"<%= @hichat_notification_name %>",
  "type":"hipchat",
  "isDefault":<%= @isdefault %>,
  "settings":{
    "apikey":"<%= @apikey %>",
    "roomid":"<%= @roomid %>",
    "url":"<%= @hipchat_url %>"
  }
}

recipe:

http_request 'post notification alert email' do
 action :post
 url "http://#{grafana_admin}:#{grafana_pass}@#{node['hostname']}:#{node['grafana']['http_port']}"
 message lazy { IO.read('/opt/email_notification.json') }
 headers({'AUTHORIZATION' => "Basic #{
 Base64.encode64('username:password')}",
          'Content-Type' => 'application/json'
         })
end

http_request 'post notification alert hipchat' do
  action :post
  url "http://#{grafana_admin}:#{grafana_pass}@#{node['hostname']}:#{node['grafana']['http_port']}"
  message lazy { IO.read('/opt/hipchat_notification.json') }
  headers({'AUTHORIZATION' => "Basic #{
  Base64.encode64('username:password')}",
           'Content-Type' => 'application/json'
          })
end

If anyone does it easier or better, please let me know, don’t be shy.

Gabriel

It seems as though you’ve figured out a way forward but I will note that the “better” way would involve writing your own Custom Resource. http_request is fairly generic and as such not geared toward all use cases, this is where writing your own resource might make more sense in the longer run depending on how API specific you get.

-cheeseplus

Thank you for the suggestion, but I’m not that skillfull yet. :slight_smile:

The only problem with the above code is that I don’t know how to check if the post request was already done. If so, if the notification is already there, I get an error.
Any thoughts, please?
Thanks.

This is precisely where writing a custom resource would be beneficial as it allows you to write arbitrary code that could determine whether the API already has a value. With just http_request, you have available the common resource functionality of guards in the form of the not_if and only_if properties. The catch with leveraging http_request is that the guard for what you are trying to check might be fairly complicated. This brings us back to a custom resource being the better solution because you have much more flexibility in terms of how you implement it.

Custom resources might seem daunting but they aren’t as hard as you might expect and also will give you the ability to do this much easier while also allowing the recipe code itself to be cleaner as the logic will be embedded in the resource itself.

While not written in the latest Custom Resource style, there are a few examples of API based resources out there that illustrate how this might work:

I’m not aware of any API based resources that have been written in the new style unfortunately (as it’s even easier) but what I am getting at is that doing so this way will be cleaner in the long run even if it requires some learning to get it working.

1 Like