require 'chef/knife/joyent_base' class Chef class Knife class JoyentServerList < Knife include Knife::JoyentBase option :show, :long => '--show field1,field1,.', :description => 'Show additional fields. Supported: compute_node, tags', :proc => Proc.new {|key| Chef::Config[:knife][:show] = key.to_s.split(/,/).map(&:to_sym)} option :sort, :long => '--sort field', :description => 'Sort by field, default is name, supported also: compute_node, price', :proc => Proc.new {|key| Chef::Config[:knife][:sort] = key.to_sym} banner "knife joyent server list " ADDITIONAL_FIELDS = [:compute_node, :tags] PRICE_COLUMN_WIDTH = 11 def run sort_matrix = { :name => lambda do |a, b| (a.name || '') <=> (b.name || '') end, :compute_node => lambda do |a, b| if a.attributes && b.attributes (a.attributes["compute_node"]) <=> (b.attributes["compute_node"]) end end, :price => lambda do |a, b| if a.package && b.package pricing.monthly_price(a.package) <=> pricing.monthly_price(b.package) end end } columns = 10 + num_of_extra_keys servers = [ ui.color('ID', :bold), ui.color('Name', :bold), ui.color('State', :bold), ui.color('Type', :bold), ui.color('Image', :bold), ui.color('Flavor', :bold), ui.color('IPs', :bold), ui.color(' RAM', :bold), ui.color(' Disk', :bold), ui.color('Price $/Month') ] servers << ui.color('Compute Node', :bold) if show?(:compute_node) servers << ui.color('Tags', :bold) if show?(:tags) total_monthly_price = 0 prev_compute_node = nil # only needed if sorting by compute_node self.connection.servers.sort(&sort_by(sort_matrix, sort_field)).each do |s| compute_node = s.respond_to?(:attributes) ? s.attributes["compute_node"] : 'unknown' columns.times { servers << "" } if sort_field == :compute_node && prev_compute_node && prev_compute_node != compute_node prev_compute_node = compute_node servers << s.id.to_s servers << s.name servers << case s.state when 'running' ui.color(s.state, :green) when 'stopping', 'provisioning' ui.color(s.state, :yellow) when 'stopped' ui.color(s.state, :red) else ui.color('unknown', :red) end flavor = s.package || 'unknown' servers << s.type servers << s.dataset servers << flavor servers << s.ips.join(",") servers << "#{sprintf "%6.2f", s.memory/1024.0} GB" servers << "#{sprintf "%5.0f", s.disk/1024} GB" servers << pricing.format_monthly_price(flavor, PRICE_COLUMN_WIDTH) servers << compute_node if show?(:compute_node) servers << s.tags.map { |k, v| "#{k}:#{v}" }.join(' ') if (show?(:tags) && (s.tags rescue nil)) total_monthly_price += pricing.monthly_price(flavor) end add_total_price(servers, total_monthly_price) puts ui.list(servers, :uneven_columns_across, columns) rescue => e output_error(e) end def add_total_price(servers, total_monthly_price) 8.times { servers << "" } servers << " Total" servers << pricing.format_price(total_monthly_price, PRICE_COLUMN_WIDTH) end def show?(key) (Chef::Config[:knife][:show] || []).include?(key) end def num_of_extra_keys ADDITIONAL_FIELDS.select{|k| show?(k)}.size end def sort_field Chef::Config[:knife][:sort] || :name end def sort_by(matrix, field) matrix[field.to_sym] || matrix[:name] end def pricing @pricing ||= Joyent::Cloud::Pricing::Formatter.new(Joyent::Cloud::Pricing::Configuration.instance) end end end end