1

I'm managing some scripts that can only be run on one server. I've decided the best way to single out one host that is assigned to a given role is by doing a search and then choosing the first element in the array returned.

Like this:

q = "roles:thumper"
arr = search(:node, q, filter_result: { fqdn: ['fqdn'] }).map { |n| n['fqdn'] }

 # => ["1.example", "2.example"]

arr.first 
# "1.example"

This works well in reality and chef-shell, but has difficulties in Test Kitchen where I am being returned an HTTP 500 on the search command.

     ================================================================================
     Recipe Compile Error in /tmp/kitchen/cache/cookbooks/test/recipes/full.rb
     ================================================================================

     Net::HTTPFatalError
     -------------------
     500 "Internal Server Error"

I am using chef_zero with the vagrant driver. Is there anything special that must be done to let search functionality work in this type of scenario?

Integration json:

{
  "id": "thumper",
  "environment": "food",
  "run_list": ["role["thumper]"],
  "automatic": {
    "fqdn": "thumper",
    "ipaddress": "10.10.10.10",
    "roles": ["thumper"],
    "environment": "food"
  }
}

Fixtures data is just calling the relevant cookbooks

include_recipe 'test_helpers'
include_recipe 'role_thumper'
Brando__
  • 365
  • 6
  • 24

1 Answers1

1

The underlying issue is probably that you aren't setting up the fixture node data correctly, or maybe some piece of the partial search API not working correctly under Zero. However this is mostly moot as this method for server election is unsafe and you shouldn't use it. At a minimum you need to sort the returned array in some way as search results in Chef are not stable to any external reference point (it sorts on a field called "object ID" but this is not exposed in the API). More to the point, this can easily result in a server being demoted but not realizing it until the next time Chef runs. Depending on how serious you are about the "only run in one place" rule you either need some slightly firmer code on the Chef side, or better yet use a tool actually designed for cluster coordination like Consul, ZooKeeper, or Etcd.

coderanger
  • 52,400
  • 4
  • 52
  • 75
  • The example code above is slightly oversimplified, in reality it does have some external sorting and a basic sanity check. Good call, though. Proper orchestration with Kubernetes is going to be a big hackathon project for me in 2 weeks and I'll take your advice at trying to integrate this type of thing in service discovery there. In the mean time though I would generally like to be able to use Search (not partial search)within TK. What were you alluding to with fixture node data? I'll put my json in the original question – Brando__ Jun 05 '17 at 01:06
  • You need to give the test instance a folder of Node objects as JSON, like you have there but it goes in `test/integration/nodes` unless you override the folder in your Kitchen config. That gets shipped up to the VM as part of the creation process. – coderanger Jun 05 '17 at 01:11