1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
require 'command_line_reporter'
module LeapCli; module Commands
desc 'List nodes and their classifications'
long_desc 'Prints out a listing of nodes, services, or tags. ' +
'If present, the FILTER can be a list of names of nodes, services, or tags. ' +
'If the name is prefixed with +, this acts like an AND condition. ' +
"For example:\n\n" +
"`leap list node1 node2` matches all nodes named \"node1\" OR \"node2\"\n\n" +
"`leap list openvpn +local` matches all nodes with service \"openvpn\" AND tag \"local\""
arg_name 'FILTER', :optional => true
command :list do |c|
c.flag 'print', :desc => 'What attributes to print (optional)'
c.switch 'disabled', :desc => 'Include disabled nodes in the list.', :negatable => false
c.action do |global_options,options,args|
# don't rely on default manager(), because we want to pass custom options to load()
manager = LeapCli::Config::Manager.new
if global_options[:color]
colors = ['cyan', 'white']
else
colors = [nil, nil]
end
puts
manager.load(:include_disabled => options['disabled'], :continue_on_error => true)
if options['print']
print_node_properties(manager.filter(args), options['print'])
else
if args.any?
NodeTable.new(manager.filter(args), colors).run
else
environment = LeapCli.leapfile.environment || '_all_'
TagTable.new('SERVICES', manager.env(environment).services, colors).run
TagTable.new('TAGS', manager.env(environment).tags, colors).run
NodeTable.new(manager.filter(), colors).run
end
end
end
end
private
def self.print_node_properties(nodes, properties)
properties = properties.split(',')
max_width = nodes.keys.inject(0) {|max,i| [i.size,max].max}
nodes.each_node do |node|
value = properties.collect{|prop|
if node[prop].nil?
"null"
elsif node[prop] == ""
"empty"
else
node[prop]
end
}.join(', ')
printf("%#{max_width}s %s\n", node.name, value)
end
puts
end
class TagTable
include CommandLineReporter
def initialize(heading, tag_list, colors)
@heading = heading
@tag_list = tag_list
@colors = colors
end
def run
tags = @tag_list.keys.select{|tag| tag !~ /^_/}.sort # sorted list of tags, excluding _partials
max_width = [20, (tags+[@heading]).inject(0) {|max,i| [i.size,max].max}].max
table :border => false do
row :color => @colors[0] do
column @heading, :align => 'right', :width => max_width
column "NODES", :width => HighLine::SystemExtensions.terminal_size.first - max_width - 2, :padding => 2
end
tags.each do |tag|
next if @tag_list[tag].node_list.empty?
row :color => @colors[1] do
column tag
column @tag_list[tag].node_list.keys.sort.join(', ')
end
end
end
vertical_spacing
end
end
#
# might be handy: HighLine::SystemExtensions.terminal_size.first
#
class NodeTable
include CommandLineReporter
def initialize(node_list, colors)
@node_list = node_list
@colors = colors
end
def run
rows = @node_list.keys.sort.collect do |node_name|
[node_name, @node_list[node_name].services.sort.join(', '), @node_list[node_name].tags.sort.join(', ')]
end
unless rows.any?
puts Paint["no results", :red]
puts
return
end
padding = 2
max_node_width = [20, (rows.map{|i|i[0]} + ["NODES"] ).inject(0) {|max,i| [i.size,max].max}].max
max_service_width = (rows.map{|i|i[1]} + ["SERVICES"]).inject(0) {|max,i| [i.size+padding+padding,max].max}
max_tag_width = (rows.map{|i|i[2]} + ["TAGS"] ).inject(0) {|max,i| [i.size,max].max}
table :border => false do
row :color => @colors[0] do
column "NODES", :align => 'right', :width => max_node_width
column "SERVICES", :width => max_service_width, :padding => 2
column "TAGS", :width => max_tag_width
end
rows.each do |r|
row :color => @colors[1] do
column r[0]
column r[1]
column r[2]
end
end
end
vertical_spacing
end
end
end; end
|