diff options
-rw-r--r-- | lib/chef/knife/core/status_presenter.rb | 23 | ||||
-rw-r--r-- | lib/chef/knife/status.rb | 38 | ||||
-rw-r--r-- | spec/unit/knife/status_spec.rb | 72 |
3 files changed, 112 insertions, 21 deletions
diff --git a/lib/chef/knife/core/status_presenter.rb b/lib/chef/knife/core/status_presenter.rb index 3298d5e4ac..9cf839d3a6 100644 --- a/lib/chef/knife/core/status_presenter.rb +++ b/lib/chef/knife/core/status_presenter.rb @@ -66,16 +66,16 @@ class Chef list.each do |node| result = {} - result["name"] = node.name - result["chef_environment"] = node.chef_environment - ip = (node[:ec2] && node[:ec2][:public_ipv4]) || node[:ipaddress] - fqdn = (node[:ec2] && node[:ec2][:public_hostname]) || node[:fqdn] + result["name"] = node["name"] || node.name + result["chef_environment"] = node["chef_environment"] + ip = (node["ec2"] && node["ec2"]["public_ipv4"]) || node["ipaddress"] + fqdn = (node["ec2"] && node["ec2"]["public_hostname"]) || node["fqdn"] result["ip"] = ip if ip result["fqdn"] = fqdn if fqdn - result["run_list"] = node.run_list if config[:run_list] - result["ohai_time"] = node[:ohai_time] - result["platform"] = node[:platform] if node[:platform] - result["platform_version"] = node[:platform_version] if node[:platform_version] + result["run_list"] = node.run_list if config["run_list"] + result["ohai_time"] = node["ohai_time"] + result["platform"] = node["platform"] if node["platform"] + result["platform_version"] = node["platform_version"] if node["platform_version"] if config[:long_output] result["default"] = node.default_attrs @@ -99,11 +99,12 @@ class Chef # special case ec2 with their split horizon whatsis. ip = (node[:ec2] && node[:ec2][:public_ipv4]) || node[:ipaddress] fqdn = (node[:ec2] && node[:ec2][:public_hostname]) || node[:fqdn] + name = node['name'] || node.name - hours, minutes, seconds = time_difference_in_hms(node["ohai_time"]) + hours, minutes, _ = time_difference_in_hms(node["ohai_time"]) hours_text = "#{hours} hour#{hours == 1 ? ' ' : 's'}" minutes_text = "#{minutes} minute#{minutes == 1 ? ' ' : 's'}" - run_list = "#{node.run_list}" if config[:run_list] + run_list = "#{node['run_list']}" if config[:run_list] if hours > 24 color = :red text = hours_text @@ -116,7 +117,7 @@ class Chef end line_parts = Array.new - line_parts << @ui.color(text, color) + ' ago' << node.name + line_parts << @ui.color(text, color) + ' ago' << name line_parts << fqdn if fqdn line_parts << ip if ip line_parts << run_list if run_list diff --git a/lib/chef/knife/status.rb b/lib/chef/knife/status.rb index 93e81f8f03..35868b376f 100644 --- a/lib/chef/knife/status.rb +++ b/lib/chef/knife/status.rb @@ -22,6 +22,7 @@ require 'chef/knife/core/status_presenter' class Chef class Knife class Status < Knife + include Knife::Core::NodeFormattingOptions deps do require 'chef/search/query' @@ -44,20 +45,43 @@ class Chef :long => "--hide-healthy", :description => "Hide nodes that have run chef in the last hour" + def append_to_query(term) + @query << " AND " unless @query.empty? + @query << term + end + def run ui.use_presenter Knife::Core::StatusPresenter - all_nodes = [] - q = Chef::Search::Query.new - query = @name_args[0] ? @name_args[0].dup : '*:*' + + if config[:long_output] + opts = {} + else + opts = {filter_result: + { name: ["name"], ipaddress: ["ipaddress"], ohai_time: ["ohai_time"], + ec2: ["ec2"], run_list: ["run_list"], platform: ["platform"], + platform_version: ["platform_version"], chef_environment: ["chef_environment"]}} + end + + @query ||= "" + append_to_query(@name_args[0]) if @name_args[0] + append_to_query("chef_environment:#{config[:environment]}") if config[:environment] + if config[:hide_healthy] time = Time.now.to_i - query_unhealthy = "NOT ohai_time:[" << (time - 60*60).to_s << " TO " << time.to_s << "]" - query << ' AND ' << query_unhealthy << @name_args[0] if @name_args[0] - query = query_unhealthy unless @name_args[0] + # AND NOT is not valid lucene syntax, so don't use append_to_query + @query << " " unless @query.empty? + @query << "NOT ohai_time:[#{(time - 60*60).to_s} TO #{time.to_s}]" end - q.search(:node, query) do |node| + + @query = @query.empty? ? "*:*" : @query + + all_nodes = [] + q = Chef::Search::Query.new + Chef::Log.info("Sending query: #{@query}") + q.search(:node, @query, opts) do |node| all_nodes << node end + output(all_nodes.sort { |n1, n2| if (config[:sort_reverse] || Chef::Config[:knife][:sort_status_reverse]) (n2["ohai_time"] or 0) <=> (n1["ohai_time"] or 0) diff --git a/spec/unit/knife/status_spec.rb b/spec/unit/knife/status_spec.rb index 2522bc61b1..ee44f3b3fd 100644 --- a/spec/unit/knife/status_spec.rb +++ b/spec/unit/knife/status_spec.rb @@ -24,15 +24,81 @@ describe Chef::Knife::Status do n.automatic_attrs["fqdn"] = "foobar" n.automatic_attrs["ohai_time"] = 1343845969 end - query = double("Chef::Search::Query") - allow(query).to receive(:search).and_yield(node) - allow(Chef::Search::Query).to receive(:new).and_return(query) + allow(Time).to receive(:now).and_return(Time.at(1428573420)) + @query = double("Chef::Search::Query") + allow(@query).to receive(:search).and_yield(node) + allow(Chef::Search::Query).to receive(:new).and_return(@query) @knife = Chef::Knife::Status.new @stdout = StringIO.new allow(@knife.ui).to receive(:stdout).and_return(@stdout) end describe "run" do + let(:opts) {{filter_result: + { name: ["name"], ipaddress: ["ipaddress"], ohai_time: ["ohai_time"], + ec2: ["ec2"], run_list: ["run_list"], platform: ["platform"], + platform_version: ["platform_version"], chef_environment: ["chef_environment"]}}} + + it "should default to searching for everything" do + expect(@query).to receive(:search).with(:node, "*:*", opts) + @knife.run + end + + it "should filter healthy nodes" do + @knife.config[:hide_healthy] = true + expect(@query).to receive(:search).with(:node, "NOT ohai_time:[1428569820 TO 1428573420]", opts) + @knife.run + end + + it "should filter by environment" do + @knife.config[:environment] = "production" + expect(@query).to receive(:search).with(:node, "chef_environment:production", opts) + @knife.run + end + + it "should filter by environment and health" do + @knife.config[:environment] = "production" + @knife.config[:hide_healthy] = true + expect(@query).to receive(:search).with(:node, "chef_environment:production NOT ohai_time:[1428569820 TO 1428573420]", opts) + @knife.run + end + + it "should not use partial search with long output" do + @knife.config[:long_output] = true + expect(@query).to receive(:search).with(:node, "*:*", {}) + @knife.run + end + + context "with a custom query" do + before :each do + @knife.instance_variable_set(:@name_args, ["name:my_custom_name"]) + end + + it "should allow a custom query to be specified" do + expect(@query).to receive(:search).with(:node, "name:my_custom_name", opts) + @knife.run + end + + it "should filter healthy nodes" do + @knife.config[:hide_healthy] = true + expect(@query).to receive(:search).with(:node, "name:my_custom_name NOT ohai_time:[1428569820 TO 1428573420]", opts) + @knife.run + end + + it "should filter by environment" do + @knife.config[:environment] = "production" + expect(@query).to receive(:search).with(:node, "name:my_custom_name AND chef_environment:production", opts) + @knife.run + end + + it "should filter by environment and health" do + @knife.config[:environment] = "production" + @knife.config[:hide_healthy] = true + expect(@query).to receive(:search).with(:node, "name:my_custom_name AND chef_environment:production NOT ohai_time:[1428569820 TO 1428573420]", opts) + @knife.run + end + end + it "should not colorize output unless it's writing to a tty" do @knife.run expect(@stdout.string.match(/foobar/)).not_to be_nil |