diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/knife/index_rebuild.rb | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/lib/chef/knife/index_rebuild.rb b/lib/chef/knife/index_rebuild.rb index b35da77619..a0bf96872a 100644 --- a/lib/chef/knife/index_rebuild.rb +++ b/lib/chef/knife/index_rebuild.rb @@ -30,12 +30,58 @@ class Chef :description => "don't bother to ask if I'm sure" def run + api_version_check nag output rest.post_rest("/search/reindex", {}) end + # Attempting to run 'knife index rebuild' on a Chef 11 (or + # above) server is an error, as that functionality now exists as + # a server-side utility. If such a request is made, we print + # out a helpful message to the user with further instructions, + # based on the server they are interacting with. + def api_version_check + # Since we don't yet have any endpoints that implement an + # OPTIONS handler, we need to get our version header + # information in a more roundabout way. We'll try to query + # for a node we know won't exist; the 404 response that comes + # back will give us what we want + dummy_node = "knife_index_rebuild_test_#{rand(1000000)}" + rest.get_rest("/nodes/#{dummy_node}") + rescue Net::HTTPServerException => exception + r = exception.response + + case r + when Net::HTTPNotFound + + api_info = parse_api_info(r) + version = api_info["version"] + + # version should always be present if we're on Chef 11+. If + # it's nil, we're on an earlier version which will still have + # a functional index rebuilding API endpoint, so we'll just + # exit. + if version + if parse_major(version) >= 11 + puts + puts "Sorry, but rebuilding the index is not available via knife for #{server_type(api_info)}s version 11.0.0 and above." + puts "Instead, run the '#{ctl_command(api_info)} reindex' command on the server itself." + exit 1 + end + # This should never execute, though, since no prior servers have API info headers + raise "Unexpected x-ops-api-info header information: version #{version} is < 11.0.0" + end + else + puts "Unexpected exception when checking server API version" + raise exception + end + end + def nag unless config[:yes] + puts + puts "NOTICE: 'knife index rebuild' has been removed for Chef 11+ servers. It will continue to work for prior versions, however." + puts yea_or_nay = ask_question("This operation is destructive. Rebuilding the index may take some time. You sure? (yes/no): ") unless yea_or_nay =~ /^y/i puts "aborting" @@ -44,6 +90,63 @@ class Chef end end + # Chef 11 (and above) servers return various pieces of + # information about the server in an +x-ops-api-info+ header. + # This is a +;+ delimited string of key / value pairs, separated + # by +=+. + # + # Given a Net::HTTPResponse object, this method extracts this + # information (if present), and returns it as a hash. If no + # such header is found, an empty hash is returned. + def parse_api_info(response) + value = response["x-ops-api-info"] + if value + kv = value.split(";") + kv.inject({}) do |acc, pair| + k, v = pair.split("=") + acc[k] = v + acc + end + else + {} + end + end + + # Given an API info hash (see +#parse_api_info(response)+), + # return a string describing the kind of server we're + # interacting with (based on the +flavor+ field) + def server_type(api_info) + case api_info["flavor"] + when "osc" + "Open Source Chef Server" + when "opc" + "Private Chef Server" + else + # Generic fallback + "Chef Server" + end + end + + # Given an API info hash (see +#parse_api_info(response)+), + # return the name of the "server-ctl" command for the kind of + # server we're interacting with (based on the +flavor+ field) + def ctl_command(api_info) + case api_info["flavor"] + when "osc" + "chef-server-ctl" + when "opc" + "private-chef-ctl" + else + # Generic fallback + "chef-server-ctl" + end + end + + # Given a semantic version string (e.g., +"1.0.0"+), return the + # major version number as an integer. + def parse_major(semver) + semver.split(".").first.to_i + end end end |