summaryrefslogtreecommitdiff
path: root/lib/chef
diff options
context:
space:
mode:
authorNicolas Dupeux <nicolas.dupeux@arkea.com>2014-10-06 16:06:28 +0200
committerNicolas Dupeux <nicolas.dupeux@arkea.com>2014-10-06 16:06:28 +0200
commitbd926141b079357c770b08dafb4dac4933ff3b3b (patch)
tree88134167cdee96f12967390ccad036ada945fb51 /lib/chef
parent2fa97c49f25e16c88373e2d084d8bacd46679bd9 (diff)
downloadchef-bd926141b079357c770b08dafb4dac4933ff3b3b.tar.gz
Add JSON output to knife status command
the status subcommand now honor the common option --format
Diffstat (limited to 'lib/chef')
-rw-r--r--lib/chef/knife/core/status_presenter.rb159
-rw-r--r--lib/chef/knife/status.rb69
2 files changed, 170 insertions, 58 deletions
diff --git a/lib/chef/knife/core/status_presenter.rb b/lib/chef/knife/core/status_presenter.rb
new file mode 100644
index 0000000000..2cd093d240
--- /dev/null
+++ b/lib/chef/knife/core/status_presenter.rb
@@ -0,0 +1,159 @@
+#
+# Author:: Nicolas DUPEUX (<nicolas.dupeux@arkea.com>)
+# Copyright:: Copyright (c) 2011 Opscode, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/knife/core/text_formatter'
+require 'chef/knife/core/generic_presenter'
+
+class Chef
+ class Knife
+ module Core
+
+ # This module may be included into a knife subcommand class to automatically
+ # add configuration options used by the StatusPresenter
+ module StatusFormattingOptions
+ # :nodoc:
+ # Would prefer to do this in a rational way, but can't be done b/c of
+ # Mixlib::CLI's design :(
+ def self.included(includer)
+ includer.class_eval do
+ option :medium_output,
+ :short => '-m',
+ :long => '--medium',
+ :boolean => true,
+ :default => false,
+ :description => 'Include normal attributes in the output'
+
+ option :long_output,
+ :short => '-l',
+ :long => '--long',
+ :boolean => true,
+ :default => false,
+ :description => 'Include all attributes in the output'
+ end
+ end
+ end
+
+ #==Chef::Knife::Core::StatusPresenter
+ # A customized presenter for Chef::Node objects. Supports variable-length
+ # output formats for displaying node data
+ class StatusPresenter < GenericPresenter
+
+ def format(data)
+ if parse_format_option == :json
+ summarize_json(data)
+ else
+ super
+ end
+ end
+
+ def summarize_json(list)
+ result_list = []
+ 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["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]
+
+ if config[:long_output]
+ result["default"] = node.default_attrs
+ result["override"] = node.override_attrs
+ result["automatic"] = node.automatic_attrs
+ end
+ result_list << result
+ end
+
+ Chef::JSONCompat.to_json_pretty(result_list)
+ end
+
+ # Converts a Chef::Node object to a string suitable for output to a
+ # terminal. If config[:medium_output] or config[:long_output] are set
+ # the volume of output is adjusted accordingly. Uses colors if enabled
+ # in the ui object.
+ def summarize(list)
+ summarized=''
+ list.each do |data|
+ #if data.kind_of?(Chef::Node)
+ node = data
+ # 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]
+
+ hours, minutes, seconds = 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]
+ if hours > 24
+ color = :red
+ text = hours_text
+ elsif hours >= 1
+ color = :yellow
+ text = hours_text
+ else
+ color = :green
+ text = minutes_text
+ end
+
+ line_parts = Array.new
+ line_parts << @ui.color(text, color) + ' ago' << node.name
+ line_parts << fqdn if fqdn
+ line_parts << ip if ip
+ line_parts << run_list if run_list
+
+ if node['platform']
+ platform = node['platform']
+ if node['platform_version']
+ platform << " #{node['platform_version']}"
+ end
+ line_parts << platform
+ end
+
+ summarized=summarized + line_parts.join(', ') + ".\n"
+ #else
+ # super
+ end
+ summarized
+ end
+
+ def key(key_text)
+ ui.color(key_text, :cyan)
+ end
+
+ # :nodoc:
+ # TODO: this is duplicated from StatusHelper in the Webui. dedup.
+ def time_difference_in_hms(unix_time)
+ now = Time.now.to_i
+ difference = now - unix_time.to_i
+ hours = (difference / 3600).to_i
+ difference = difference % 3600
+ minutes = (difference / 60).to_i
+ seconds = (difference % 60)
+ return [hours, minutes, seconds]
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/chef/knife/status.rb b/lib/chef/knife/status.rb
index 5906a4a624..93e81f8f03 100644
--- a/lib/chef/knife/status.rb
+++ b/lib/chef/knife/status.rb
@@ -17,13 +17,13 @@
#
require 'chef/knife'
+require 'chef/knife/core/status_presenter'
class Chef
class Knife
class Status < Knife
deps do
- require 'highline'
require 'chef/search/query'
end
@@ -44,74 +44,27 @@ class Chef
:long => "--hide-healthy",
:description => "Hide nodes that have run chef in the last hour"
- def highline
- @h ||= HighLine.new
- end
-
def run
+ ui.use_presenter Knife::Core::StatusPresenter
all_nodes = []
q = Chef::Search::Query.new
- query = @name_args[0] || "*:*"
+ query = @name_args[0] ? @name_args[0].dup : '*:*'
+ 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]
+ end
q.search(:node, query) do |node|
all_nodes << node
end
- all_nodes.sort { |n1, n2|
+ 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)
else
(n1["ohai_time"] or 0) <=> (n2["ohai_time"] or 0)
end
- }.each do |node|
- if node.has_key?("ec2")
- fqdn = node['ec2']['public_hostname']
- ipaddress = node['ec2']['public_ipv4']
- else
- fqdn = node['fqdn']
- ipaddress = node['ipaddress']
- end
- hours, minutes, seconds = 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]
- if hours > 24
- color = :red
- text = hours_text
- elsif hours >= 1
- color = :yellow
- text = hours_text
- else
- color = :green
- text = minutes_text
- end
-
- line_parts = Array.new
- line_parts << @ui.color(text, color) + " ago" << node.name
- line_parts << fqdn if fqdn
- line_parts << ipaddress if ipaddress
- line_parts << run_list if run_list
-
- if node['platform']
- platform = node['platform']
- if node['platform_version']
- platform << " #{node['platform_version']}"
- end
- line_parts << platform
- end
- highline.say(line_parts.join(', ') + '.') unless (config[:hide_healthy] && hours < 1)
- end
-
- end
-
- # :nodoc:
- # TODO: this is duplicated from StatusHelper in the Webui. dedup.
- def time_difference_in_hms(unix_time)
- now = Time.now.to_i
- difference = now - unix_time.to_i
- hours = (difference / 3600).to_i
- difference = difference % 3600
- minutes = (difference / 60).to_i
- seconds = (difference % 60)
- return [hours, minutes, seconds]
+ })
end
end