summaryrefslogtreecommitdiff
path: root/lib/chef/knife/index_rebuild.rb
diff options
context:
space:
mode:
authorChristopher Maier <cm@opscode.com>2012-11-30 18:28:39 -0500
committerChristopher Maier <cm@opscode.com>2012-12-03 14:24:41 -0500
commitf0915359c07626d92690f6ace80fa9c60bdc8746 (patch)
tree5f80212b20ef6dc115b24a848be81f23b4090d95 /lib/chef/knife/index_rebuild.rb
parentaac1f8cf569d788f0345b1830c16b31b54e9c4d2 (diff)
downloadchef-f0915359c07626d92690f6ace80fa9c60bdc8746.tar.gz
Deprecate 'knife index rebuild'
Provide detailed feedback for commands to run to achieve the same functionality for users interacting with Chef 11 servers. Notify users of Chef 10 servers that the functionality will no longer be present on Chef 11, but still allow them to rebuild their older servers.
Diffstat (limited to 'lib/chef/knife/index_rebuild.rb')
-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