summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/chef/knife/index_rebuild.rb103
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