morpheus-cli 4.2.8 → 4.2.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api.rb +1 -1
- data/lib/morpheus/api/activity_interface.rb +9 -0
- data/lib/morpheus/api/api_client.rb +83 -27
- data/lib/morpheus/api/apps_interface.rb +21 -0
- data/lib/morpheus/api/dashboard_interface.rb +5 -21
- data/lib/morpheus/api/instances_interface.rb +3 -10
- data/lib/morpheus/api/invoice_line_items_interface.rb +14 -0
- data/lib/morpheus/api/invoices_interface.rb +7 -12
- data/lib/morpheus/api/library_layouts_interface.rb +8 -0
- data/lib/morpheus/api/ping_interface.rb +20 -0
- data/lib/morpheus/api/projects_interface.rb +33 -0
- data/lib/morpheus/api/setup_interface.rb +19 -36
- data/lib/morpheus/api/user_settings_interface.rb +0 -6
- data/lib/morpheus/api/whoami_interface.rb +4 -8
- data/lib/morpheus/benchmarking.rb +16 -26
- data/lib/morpheus/cli.rb +10 -5
- data/lib/morpheus/cli/access_token_command.rb +5 -8
- data/lib/morpheus/cli/activity_command.rb +146 -0
- data/lib/morpheus/cli/apps.rb +312 -121
- data/lib/morpheus/cli/archives_command.rb +1 -1
- data/lib/morpheus/cli/auth_command.rb +4 -11
- data/lib/morpheus/cli/blueprints_command.rb +196 -137
- data/lib/morpheus/cli/change_password_command.rb +1 -1
- data/lib/morpheus/cli/cli_command.rb +225 -72
- data/lib/morpheus/cli/cli_registry.rb +2 -2
- data/lib/morpheus/cli/cloud_datastores_command.rb +1 -1
- data/lib/morpheus/cli/clouds.rb +5 -20
- data/lib/morpheus/cli/clusters.rb +4 -28
- data/lib/morpheus/cli/commands/standard/alias_command.rb +2 -9
- data/lib/morpheus/cli/commands/standard/benchmark_command.rb +2 -0
- data/lib/morpheus/cli/commands/standard/curl_command.rb +2 -3
- data/lib/morpheus/cli/commands/standard/history_command.rb +3 -6
- data/lib/morpheus/cli/commands/standard/man_command.rb +10 -7
- data/lib/morpheus/cli/commands/standard/ssl_verification_command.rb +10 -9
- data/lib/morpheus/cli/containers_command.rb +3 -3
- data/lib/morpheus/cli/credentials.rb +13 -16
- data/lib/morpheus/cli/error_handler.rb +18 -12
- data/lib/morpheus/cli/errors.rb +45 -0
- data/lib/morpheus/cli/execute_schedules_command.rb +1 -1
- data/lib/morpheus/cli/execution_request_command.rb +4 -4
- data/lib/morpheus/cli/groups.rb +84 -132
- data/lib/morpheus/cli/hosts.rb +6 -16
- data/lib/morpheus/cli/instances.rb +100 -183
- data/lib/morpheus/cli/invoices_command.rb +505 -71
- data/lib/morpheus/cli/library_layouts_command.rb +254 -166
- data/lib/morpheus/cli/library_option_lists_command.rb +0 -87
- data/lib/morpheus/cli/library_option_types_command.rb +0 -96
- data/lib/morpheus/cli/license.rb +3 -0
- data/lib/morpheus/cli/login.rb +17 -37
- data/lib/morpheus/cli/logout.rb +9 -5
- data/lib/morpheus/cli/mixins/accounts_helper.rb +83 -7
- data/lib/morpheus/cli/mixins/operations_helper.rb +41 -0
- data/lib/morpheus/cli/mixins/option_source_helper.rb +255 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +18 -4
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +222 -13
- data/lib/morpheus/cli/mixins/remote_helper.rb +139 -0
- data/lib/morpheus/cli/monitoring_checks_command.rb +11 -3
- data/lib/morpheus/cli/network_groups_command.rb +8 -2
- data/lib/morpheus/cli/option_types.rb +1 -1
- data/lib/morpheus/cli/ping.rb +252 -0
- data/lib/morpheus/cli/price_sets_command.rb +16 -27
- data/lib/morpheus/cli/prices_command.rb +34 -27
- data/lib/morpheus/cli/processes_command.rb +81 -7
- data/lib/morpheus/cli/projects_command.rb +607 -0
- data/lib/morpheus/cli/recent_activity_command.rb +87 -65
- data/lib/morpheus/cli/remote.rb +965 -974
- data/lib/morpheus/cli/reports_command.rb +3 -15
- data/lib/morpheus/cli/roles.rb +8 -31
- data/lib/morpheus/cli/service_plans_command.rb +25 -31
- data/lib/morpheus/cli/setup.rb +392 -0
- data/lib/morpheus/cli/shell.rb +144 -56
- data/lib/morpheus/cli/subnets_command.rb +71 -11
- data/lib/morpheus/cli/tasks.rb +3 -3
- data/lib/morpheus/cli/user_sources_command.rb +4 -4
- data/lib/morpheus/cli/users.rb +135 -109
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/whitelabel_settings_command.rb +7 -7
- data/lib/morpheus/cli/whoami.rb +90 -129
- data/lib/morpheus/cli/wiki_command.rb +2 -14
- data/lib/morpheus/ext/rest_client.rb +36 -0
- data/lib/morpheus/formatters.rb +42 -5
- data/lib/morpheus/rest_client.rb +0 -10
- data/lib/morpheus/terminal.rb +41 -1
- data/lib/morpheus/util.rb +24 -0
- metadata +16 -3
- data/lib/morpheus/cli/command_error.rb +0 -22
data/lib/morpheus/cli/whoami.rb
CHANGED
@@ -17,26 +17,17 @@ class Morpheus::Cli::Whoami
|
|
17
17
|
|
18
18
|
# no subcommands, just show()
|
19
19
|
|
20
|
-
def
|
21
|
-
# @
|
22
|
-
|
23
|
-
|
24
|
-
def connect(opts)
|
25
|
-
#@api_client = establish_remote_appliance_connection(opts)
|
26
|
-
# begin
|
27
|
-
@api_client = establish_remote_appliance_connection(opts.merge({:no_prompt => true, :skip_verify_access_token => true}))
|
28
|
-
@groups_interface = @api_client.groups
|
29
|
-
@active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
|
30
|
-
# rescue Morpheus::Cli::CommandError => err
|
31
|
-
# puts_error err
|
32
|
-
# end
|
20
|
+
def connect(options)
|
21
|
+
# @api_client = establish_remote_appliance_connection(options)
|
22
|
+
@api_client = establish_remote_appliance_connection(options.merge({:skip_verify_access_token => true, :skip_login => true}))
|
23
|
+
@whoami_interface = @api_client.whoami
|
33
24
|
end
|
34
25
|
|
35
26
|
def handle(args)
|
36
|
-
|
27
|
+
get(args)
|
37
28
|
end
|
38
29
|
|
39
|
-
def
|
30
|
+
def get(args)
|
40
31
|
options = {}
|
41
32
|
params = {}
|
42
33
|
username_only = false
|
@@ -46,12 +37,22 @@ class Morpheus::Cli::Whoami
|
|
46
37
|
opts.on( '-n', '--name', "Print only your username." ) do
|
47
38
|
username_only = true
|
48
39
|
end
|
49
|
-
opts.on('-a','--all', "Display All Details
|
40
|
+
opts.on('-a','--all', "Display All Details") do
|
50
41
|
options[:include_feature_access] = true
|
42
|
+
options[:include_group_access] = true
|
43
|
+
options[:include_cloud_access] = true
|
44
|
+
options[:include_instance_type_access] = true
|
51
45
|
end
|
52
|
-
opts.on('-
|
46
|
+
opts.on('-p','--permissions', "Display Permissions") do
|
53
47
|
options[:include_feature_access] = true
|
48
|
+
# options[:include_group_access] = true
|
49
|
+
# options[:include_cloud_access] = true
|
50
|
+
# options[:include_instance_type_access] = true
|
54
51
|
end
|
52
|
+
# opts.on('-f','--feature-access', "Display Feature Access") do
|
53
|
+
# options[:include_feature_access] = true
|
54
|
+
# end
|
55
|
+
# opts.add_hidden_option('--feature-access')
|
55
56
|
# these are things that morpheus users get has to display...
|
56
57
|
# opts.on(nil,'--group-access', "Display Group Access") do
|
57
58
|
# options[:include_group_access] = true
|
@@ -62,63 +63,60 @@ class Morpheus::Cli::Whoami
|
|
62
63
|
# opts.on(nil,'--instance-type-access', "Display Instance Type Access") do
|
63
64
|
# options[:include_instance_type_access] = true
|
64
65
|
# end
|
65
|
-
opts.on('-a','--all-access', "Display All Access Lists") do
|
66
|
-
options[:include_feature_access] = true
|
67
|
-
options[:include_group_access] = true
|
68
|
-
options[:include_cloud_access] = true
|
69
|
-
options[:include_instance_type_access] = true
|
70
|
-
end
|
71
66
|
opts.on('-t','--token-only', "Print your access token only") do
|
72
67
|
access_token_only = true
|
73
68
|
end
|
74
|
-
|
69
|
+
opts.on('--offline', '--offline', "Do this offline without an api request to refresh the remote appliance status.") do
|
70
|
+
options[:do_offline] = true
|
71
|
+
end
|
72
|
+
build_standard_get_options(opts, options)
|
73
|
+
opts.footer = <<-EOT
|
74
|
+
View information about the current user.
|
75
|
+
EOT
|
75
76
|
end
|
76
77
|
optparse.parse!(args)
|
78
|
+
verify_args!(args:args, optparse:optparse, count:0)
|
77
79
|
connect(options)
|
78
80
|
begin
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
# never gets here..
|
83
|
-
#raise_command_error "Please specify a Morpheus Appliance with -r or see the command `remote use`"
|
84
|
-
print yellow,"Please specify a Morpheus Appliance with -r or see `remote use`.#{reset}\n"
|
85
|
-
return 1
|
81
|
+
if @access_token.nil?
|
82
|
+
print_error yellow,"You are not currently logged in",reset,"\n"
|
83
|
+
return 1, "no current user"
|
86
84
|
end
|
87
|
-
|
85
|
+
@whoami_interface.setopts(options)
|
88
86
|
if options[:dry_run]
|
89
|
-
print_dry_run @
|
87
|
+
print_dry_run @whoami_interface.dry.get(params)
|
90
88
|
return 0
|
91
89
|
end
|
92
90
|
|
93
|
-
# todo: fix potential issue here, should be able to use --remote-url or --username
|
94
|
-
# in which case you do not have to be logged in (saved credentials)...
|
95
|
-
# maybe just update connect() to do @api_client = establish_remote_appliance_connection(opts)
|
96
|
-
# wallet = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).request_credentials(options)
|
97
|
-
wallet = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).load_saved_credentials()
|
98
|
-
token = wallet ? wallet['access_token'] : nil
|
99
|
-
if !token
|
100
|
-
if options[:quiet]
|
101
|
-
return 1
|
102
|
-
elsif access_token_only
|
103
|
-
puts_error "(logged out)" # stderr probably
|
104
|
-
return 1
|
105
|
-
else
|
106
|
-
print yellow,"You are not currently logged in to #{display_appliance(@appliance_name, @appliance_url)}",reset,"\n"
|
107
|
-
print yellow,"Use the 'login' command.",reset,"\n"
|
108
|
-
return 1
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
91
|
#json_response = load_whoami()
|
113
|
-
|
114
|
-
|
115
|
-
|
92
|
+
whoami_response = nil
|
93
|
+
if options[:do_offline]
|
94
|
+
# if @remote_appliance && @remote_appliance[:username]
|
95
|
+
# exit_code = 0
|
96
|
+
# else
|
97
|
+
# exit_code = 1
|
98
|
+
# end
|
99
|
+
# no permissions, or even name stored atm, we should start storing that.
|
100
|
+
# then we can start checking permissions nd restricting command visibility.
|
101
|
+
whoami_response = {
|
102
|
+
"user": {
|
103
|
+
"username" => @remote_appliance ? @remote_appliance[:username] : nil
|
104
|
+
},
|
105
|
+
# "isMasterAccount" => true,
|
106
|
+
"permissions" => [],
|
107
|
+
"appliance" => {
|
108
|
+
"buildVersion" => @remote_appliance ? @remote_appliance[:build_version] : nil
|
109
|
+
}
|
110
|
+
}
|
111
|
+
else
|
112
|
+
whoami_response = @whoami_interface.get(params)
|
113
|
+
end
|
116
114
|
json_response = whoami_response
|
117
115
|
@current_user = whoami_response["user"]
|
118
|
-
if @current_user.
|
119
|
-
|
120
|
-
|
121
|
-
end
|
116
|
+
# if @current_user.nil?
|
117
|
+
# print_red_alert "Unauthenticated. Please login."
|
118
|
+
# exit 1
|
119
|
+
# end
|
122
120
|
@is_master_account = whoami_response["isMasterAccount"]
|
123
121
|
@user_permissions = whoami_response["permissions"]
|
124
122
|
|
@@ -128,62 +126,52 @@ class Morpheus::Cli::Whoami
|
|
128
126
|
@appliance_build_verison = nil
|
129
127
|
end
|
130
128
|
|
131
|
-
|
132
|
-
if options[:quiet]
|
133
|
-
return @current_user ? 0 : 1
|
134
|
-
end
|
135
|
-
if @access_token.nil?
|
136
|
-
print yellow,"\n","No access token. Please login",reset,"\n"
|
137
|
-
return false
|
138
|
-
end
|
139
|
-
print cyan,@access_token.to_s,reset,"\n"
|
140
|
-
return 0
|
141
|
-
end
|
129
|
+
render_response(json_response, options) do
|
142
130
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
print cyan,@
|
131
|
+
if access_token_only
|
132
|
+
if options[:quiet]
|
133
|
+
return @current_user ? 0 : 1
|
134
|
+
end
|
135
|
+
if @access_token.nil?
|
136
|
+
print yellow,"\n","No access token. Please login",reset,"\n"
|
137
|
+
return false
|
138
|
+
end
|
139
|
+
print cyan,@access_token.to_s,reset,"\n"
|
152
140
|
return 0
|
153
141
|
end
|
154
|
-
end
|
155
142
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
143
|
+
if username_only
|
144
|
+
if options[:quiet]
|
145
|
+
return @current_user ? 0 : 1
|
146
|
+
end
|
147
|
+
if @current_user.nil?
|
148
|
+
puts_error "(logged out)" # "(anonymous)" || ""
|
149
|
+
return 1
|
150
|
+
else
|
151
|
+
print cyan,@current_user['username'].to_s,reset,"\n"
|
152
|
+
return 0
|
153
|
+
end
|
163
154
|
end
|
164
|
-
end
|
165
155
|
|
166
|
-
if options[:json]
|
167
|
-
print JSON.pretty_generate(json_response)
|
168
|
-
print "\n"
|
169
|
-
else
|
170
156
|
if @current_user.nil?
|
171
157
|
print yellow,"\n","No active session. Please login",reset,"\n"
|
172
158
|
exit 1
|
173
159
|
end
|
174
|
-
|
175
|
-
|
160
|
+
subtitles = []
|
161
|
+
#subtitles << "#{display_appliance(@appliance_name, @appliance_url)}"
|
162
|
+
print_h1 "Current User", subtitles, options
|
176
163
|
print cyan
|
177
164
|
print_description_list({
|
178
165
|
"ID" => 'id',
|
179
|
-
"
|
180
|
-
|
181
|
-
|
166
|
+
"Tenant" => lambda {|it| (it['account'] ? it['account']['name'] : '') + (@is_master_account ? " (Master Account)" : '') },
|
167
|
+
"First Name" => 'firstName',
|
168
|
+
"Last Name" => 'lastName',
|
182
169
|
# "Name" => 'displayName',
|
183
|
-
"Name" => lambda {|it| it['firstName'] ? it['displayName'] : '' },
|
170
|
+
#"Name" => lambda {|it| it['firstName'] ? it['displayName'] : '' },
|
184
171
|
"Username" => 'username',
|
185
172
|
"Email" => 'email',
|
186
|
-
"Role" => lambda {|it| format_user_role_names(it) }
|
173
|
+
"Role" => lambda {|it| format_user_role_names(it) },
|
174
|
+
#"Remote" => lambda {|it| display_appliance(@appliance_name, @appliance_url) },
|
187
175
|
}, @current_user)
|
188
176
|
print cyan
|
189
177
|
|
@@ -196,12 +184,12 @@ class Morpheus::Cli::Whoami
|
|
196
184
|
if @user_permissions.is_a?(Hash)
|
197
185
|
# api used to return map like [code:access]
|
198
186
|
rows = @user_permissions.collect do |code, access|
|
199
|
-
{permission: code, access:
|
187
|
+
{permission: code, access: format_access_string(access) }
|
200
188
|
end
|
201
189
|
else
|
202
190
|
# api now returns an array of objects like [[name:"Foo",code:"foo",access:"full"], ...]
|
203
191
|
rows = @user_permissions.collect do |it|
|
204
|
-
{permission: (it['name'] || it['code']), access:
|
192
|
+
{permission: (it['name'] || it['code']), access: format_access_string(it['access']) }
|
205
193
|
end
|
206
194
|
end
|
207
195
|
# api sort sux right now
|
@@ -215,34 +203,7 @@ class Morpheus::Cli::Whoami
|
|
215
203
|
end
|
216
204
|
end
|
217
205
|
|
218
|
-
|
219
|
-
print cyan
|
220
|
-
appliance_data = {
|
221
|
-
'name' => @appliance_name,
|
222
|
-
'url' => @appliance_url,
|
223
|
-
'buildVersion' => @appliance_build_verison
|
224
|
-
}
|
225
|
-
print_description_list({
|
226
|
-
"Name" => 'name',
|
227
|
-
"URL" => 'url',
|
228
|
-
"Version" => 'buildVersion'
|
229
|
-
}, appliance_data)
|
230
|
-
|
231
|
-
if active_group
|
232
|
-
print cyan
|
233
|
-
# print_h1 "Active Group", options
|
234
|
-
# print cyan
|
235
|
-
# print_description_list({
|
236
|
-
# "ID" => 'id',
|
237
|
-
# "Name" => 'name'
|
238
|
-
# }, active_group)
|
239
|
-
print cyan, "\n# => Currently using group #{active_group['name']}\n", reset
|
240
|
-
print reset,"\n"
|
241
|
-
else
|
242
|
-
print "\n", reset
|
243
|
-
print cyan, "No active group. See `groups use`\n",reset
|
244
|
-
print reset,"\n"
|
245
|
-
end
|
206
|
+
print reset, "\n"
|
246
207
|
|
247
208
|
# save pertinent session info to the appliance
|
248
209
|
begin
|
@@ -173,23 +173,11 @@ class Morpheus::Cli::WikiCommand
|
|
173
173
|
|
174
174
|
link = "#{@appliance_url}/login/oauth-redirect?access_token=#{@access_token}\\&redirectUri=/operations/wiki/#{page['urlName']}"
|
175
175
|
|
176
|
-
open_command = nil
|
177
|
-
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
178
|
-
open_command = "start #{link}"
|
179
|
-
elsif RbConfig::CONFIG['host_os'] =~ /darwin/
|
180
|
-
open_command = "open #{link}"
|
181
|
-
elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
|
182
|
-
open_command = "xdg-open #{link}"
|
183
|
-
end
|
184
|
-
|
185
176
|
if options[:dry_run]
|
186
|
-
puts
|
177
|
+
puts Morpheus::Util.open_url_command(link)
|
187
178
|
return 0
|
188
179
|
end
|
189
|
-
|
190
|
-
system(open_command)
|
191
|
-
|
192
|
-
return 0
|
180
|
+
return Morpheus::Util.open_url(link)
|
193
181
|
rescue RestClient::Exception => e
|
194
182
|
print_rest_exception(e, options)
|
195
183
|
exit 1
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# this does some monkey patching of third party RestClient
|
2
|
+
# to modify the logging output a bit
|
3
|
+
require 'rest-client'
|
4
|
+
|
5
|
+
module RestClient
|
6
|
+
class Request
|
7
|
+
|
8
|
+
def log_request
|
9
|
+
begin
|
10
|
+
return unless RestClient.log
|
11
|
+
out = []
|
12
|
+
# out << "RestClient.#{method} #{redacted_url.inspect}"
|
13
|
+
out << "#{method.to_s.upcase} #{redacted_url.inspect}"
|
14
|
+
out << payload.short_inspect if payload
|
15
|
+
out << processed_headers.to_a.sort.map { |(k, v)| [k.inspect, v.inspect].join("=>") }.join(", ")
|
16
|
+
RestClient.log << out.join(', ') + "\n"
|
17
|
+
rescue => ex
|
18
|
+
# something went wrong, wrong gem version maybe...above is from rest-client 2.0.2
|
19
|
+
# do it the old way
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
=begin
|
24
|
+
def log_response res
|
25
|
+
return unless RestClient.log
|
26
|
+
size = if @raw_response
|
27
|
+
File.size(@tf.path)
|
28
|
+
else
|
29
|
+
res.body.nil? ? 0 : res.body.size
|
30
|
+
end
|
31
|
+
|
32
|
+
RestClient.log << "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes\n"
|
33
|
+
end
|
34
|
+
=end
|
35
|
+
end
|
36
|
+
end
|
data/lib/morpheus/formatters.rb
CHANGED
@@ -91,6 +91,20 @@ def format_duration(start_time, end_time=nil, format="human")
|
|
91
91
|
format_duration_seconds(seconds, format)
|
92
92
|
end
|
93
93
|
|
94
|
+
def format_duration_ago(start_time, end_time=nil)
|
95
|
+
if !start_time
|
96
|
+
return ""
|
97
|
+
end
|
98
|
+
start_time = parse_time(start_time)
|
99
|
+
if end_time
|
100
|
+
end_time = parse_time(end_time)
|
101
|
+
else
|
102
|
+
end_time = Time.now
|
103
|
+
end
|
104
|
+
seconds = (end_time - start_time).abs
|
105
|
+
format_human_duration(seconds, true)
|
106
|
+
end
|
107
|
+
|
94
108
|
def format_duration_seconds(seconds, format="human")
|
95
109
|
seconds = seconds.abs
|
96
110
|
out = ""
|
@@ -120,7 +134,7 @@ end
|
|
120
134
|
|
121
135
|
# returns a human readable time duration
|
122
136
|
# @param seconds - duration in seconds
|
123
|
-
def format_human_duration(seconds)
|
137
|
+
def format_human_duration(seconds, show_relative=false)
|
124
138
|
out = ""
|
125
139
|
#seconds = seconds.round
|
126
140
|
days, hours, minutes = (seconds / (60*60*24)).floor, (seconds / (60*60)).floor, (seconds / (60)).floor
|
@@ -152,18 +166,30 @@ def format_human_duration(seconds)
|
|
152
166
|
ms = (seconds.to_f * 1000).to_i
|
153
167
|
out << "#{ms}ms"
|
154
168
|
else
|
155
|
-
|
156
|
-
if seconds == 1
|
169
|
+
if seconds.floor == 1
|
157
170
|
out << "1 second"
|
158
171
|
else
|
159
|
-
out << "#{seconds} seconds"
|
172
|
+
out << "#{seconds.floor} seconds"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
if show_relative
|
176
|
+
if seconds < 1
|
177
|
+
out = "just now"
|
178
|
+
else
|
179
|
+
out << " ago"
|
160
180
|
end
|
161
181
|
end
|
162
182
|
out
|
163
183
|
end
|
164
184
|
|
165
185
|
def display_appliance(name, url)
|
166
|
-
"
|
186
|
+
if name.to_s == "" || name == 'remote-url'
|
187
|
+
# "#{url}"
|
188
|
+
"#{url}"
|
189
|
+
else
|
190
|
+
# "#{name} #{url}"
|
191
|
+
"[#{name}] #{url}"
|
192
|
+
end
|
167
193
|
end
|
168
194
|
|
169
195
|
def iso8601(dt)
|
@@ -321,6 +347,7 @@ def no_colors(str)
|
|
321
347
|
str.to_s.gsub /\e\[\d+m/, ""
|
322
348
|
end
|
323
349
|
|
350
|
+
|
324
351
|
def format_number(n, opts={})
|
325
352
|
delim = opts[:delimiter] || ','
|
326
353
|
out = ""
|
@@ -338,6 +365,16 @@ def format_number(n, opts={})
|
|
338
365
|
return out
|
339
366
|
end
|
340
367
|
|
368
|
+
def format_sig_dig(n, sig_dig=3)
|
369
|
+
out = ""
|
370
|
+
parts = n.to_f.round(sig_dig).to_s.split(".")
|
371
|
+
if parts.size > 1 && sig_dig
|
372
|
+
parts[1] = parts[1].ljust(sig_dig, "0")
|
373
|
+
end
|
374
|
+
out << parts.join(".")
|
375
|
+
return out
|
376
|
+
end
|
377
|
+
|
341
378
|
def currency_sym(currency)
|
342
379
|
Money::Currency.new((currency || 'usd').to_sym).symbol
|
343
380
|
end
|