morpheus-cli 4.2.8 → 4.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api.rb +1 -1
  4. data/lib/morpheus/api/activity_interface.rb +9 -0
  5. data/lib/morpheus/api/api_client.rb +83 -27
  6. data/lib/morpheus/api/apps_interface.rb +21 -0
  7. data/lib/morpheus/api/dashboard_interface.rb +5 -21
  8. data/lib/morpheus/api/instances_interface.rb +3 -10
  9. data/lib/morpheus/api/invoice_line_items_interface.rb +14 -0
  10. data/lib/morpheus/api/invoices_interface.rb +7 -12
  11. data/lib/morpheus/api/library_layouts_interface.rb +8 -0
  12. data/lib/morpheus/api/ping_interface.rb +20 -0
  13. data/lib/morpheus/api/projects_interface.rb +33 -0
  14. data/lib/morpheus/api/setup_interface.rb +19 -36
  15. data/lib/morpheus/api/user_settings_interface.rb +0 -6
  16. data/lib/morpheus/api/whoami_interface.rb +4 -8
  17. data/lib/morpheus/benchmarking.rb +16 -26
  18. data/lib/morpheus/cli.rb +10 -5
  19. data/lib/morpheus/cli/access_token_command.rb +5 -8
  20. data/lib/morpheus/cli/activity_command.rb +146 -0
  21. data/lib/morpheus/cli/apps.rb +312 -121
  22. data/lib/morpheus/cli/archives_command.rb +1 -1
  23. data/lib/morpheus/cli/auth_command.rb +4 -11
  24. data/lib/morpheus/cli/blueprints_command.rb +196 -137
  25. data/lib/morpheus/cli/change_password_command.rb +1 -1
  26. data/lib/morpheus/cli/cli_command.rb +225 -72
  27. data/lib/morpheus/cli/cli_registry.rb +2 -2
  28. data/lib/morpheus/cli/cloud_datastores_command.rb +1 -1
  29. data/lib/morpheus/cli/clouds.rb +5 -20
  30. data/lib/morpheus/cli/clusters.rb +4 -28
  31. data/lib/morpheus/cli/commands/standard/alias_command.rb +2 -9
  32. data/lib/morpheus/cli/commands/standard/benchmark_command.rb +2 -0
  33. data/lib/morpheus/cli/commands/standard/curl_command.rb +2 -3
  34. data/lib/morpheus/cli/commands/standard/history_command.rb +3 -6
  35. data/lib/morpheus/cli/commands/standard/man_command.rb +10 -7
  36. data/lib/morpheus/cli/commands/standard/ssl_verification_command.rb +10 -9
  37. data/lib/morpheus/cli/containers_command.rb +3 -3
  38. data/lib/morpheus/cli/credentials.rb +13 -16
  39. data/lib/morpheus/cli/error_handler.rb +18 -12
  40. data/lib/morpheus/cli/errors.rb +45 -0
  41. data/lib/morpheus/cli/execute_schedules_command.rb +1 -1
  42. data/lib/morpheus/cli/execution_request_command.rb +4 -4
  43. data/lib/morpheus/cli/groups.rb +84 -132
  44. data/lib/morpheus/cli/hosts.rb +6 -16
  45. data/lib/morpheus/cli/instances.rb +100 -183
  46. data/lib/morpheus/cli/invoices_command.rb +505 -71
  47. data/lib/morpheus/cli/library_layouts_command.rb +254 -166
  48. data/lib/morpheus/cli/library_option_lists_command.rb +0 -87
  49. data/lib/morpheus/cli/library_option_types_command.rb +0 -96
  50. data/lib/morpheus/cli/license.rb +3 -0
  51. data/lib/morpheus/cli/login.rb +17 -37
  52. data/lib/morpheus/cli/logout.rb +9 -5
  53. data/lib/morpheus/cli/mixins/accounts_helper.rb +83 -7
  54. data/lib/morpheus/cli/mixins/operations_helper.rb +41 -0
  55. data/lib/morpheus/cli/mixins/option_source_helper.rb +255 -0
  56. data/lib/morpheus/cli/mixins/print_helper.rb +18 -4
  57. data/lib/morpheus/cli/mixins/provisioning_helper.rb +222 -13
  58. data/lib/morpheus/cli/mixins/remote_helper.rb +139 -0
  59. data/lib/morpheus/cli/monitoring_checks_command.rb +11 -3
  60. data/lib/morpheus/cli/network_groups_command.rb +8 -2
  61. data/lib/morpheus/cli/option_types.rb +1 -1
  62. data/lib/morpheus/cli/ping.rb +252 -0
  63. data/lib/morpheus/cli/price_sets_command.rb +16 -27
  64. data/lib/morpheus/cli/prices_command.rb +34 -27
  65. data/lib/morpheus/cli/processes_command.rb +81 -7
  66. data/lib/morpheus/cli/projects_command.rb +607 -0
  67. data/lib/morpheus/cli/recent_activity_command.rb +87 -65
  68. data/lib/morpheus/cli/remote.rb +965 -974
  69. data/lib/morpheus/cli/reports_command.rb +3 -15
  70. data/lib/morpheus/cli/roles.rb +8 -31
  71. data/lib/morpheus/cli/service_plans_command.rb +25 -31
  72. data/lib/morpheus/cli/setup.rb +392 -0
  73. data/lib/morpheus/cli/shell.rb +144 -56
  74. data/lib/morpheus/cli/subnets_command.rb +71 -11
  75. data/lib/morpheus/cli/tasks.rb +3 -3
  76. data/lib/morpheus/cli/user_sources_command.rb +4 -4
  77. data/lib/morpheus/cli/users.rb +135 -109
  78. data/lib/morpheus/cli/version.rb +1 -1
  79. data/lib/morpheus/cli/whitelabel_settings_command.rb +7 -7
  80. data/lib/morpheus/cli/whoami.rb +90 -129
  81. data/lib/morpheus/cli/wiki_command.rb +2 -14
  82. data/lib/morpheus/ext/rest_client.rb +36 -0
  83. data/lib/morpheus/formatters.rb +42 -5
  84. data/lib/morpheus/rest_client.rb +0 -10
  85. data/lib/morpheus/terminal.rb +41 -1
  86. data/lib/morpheus/util.rb +24 -0
  87. metadata +16 -3
  88. data/lib/morpheus/cli/command_error.rb +0 -22
@@ -0,0 +1,139 @@
1
+ require 'morpheus/cli/mixins/print_helper'
2
+
3
+ # Mixin for Morpheus::Cli command classes
4
+ # Provides common methods for working with remotes
5
+ module Morpheus::Cli::RemoteHelper
6
+
7
+ def self.included(klass)
8
+ klass.send :include, Morpheus::Cli::PrintHelper
9
+ end
10
+
11
+ def format_appliance_name(appliance)
12
+ app_name = appliance[:name]
13
+ if app_name == 'remote-url'
14
+ "(remote-url)"
15
+ else
16
+ app_name
17
+ end
18
+ end
19
+
20
+ def format_appliance_slug(appliance)
21
+ "[#{format_appliance_name(appliance)}] #{appliance[:url]}"
22
+ end
23
+
24
+ def format_appliance_status(appliance, return_color=cyan, show_current=false)
25
+ return "" if !appliance
26
+ status_str = appliance[:status] || appliance['status'] || "unknown" # get_object_value(appliance, :status)
27
+ status_str = status_str.to_s # Symbols getting in here?
28
+ status_str = status_str.empty? ? "unknown" : status_str.to_s.downcase
29
+ status_str = status_str.gsub("-", " ") # change "http-error" to "http error"
30
+ out = ""
31
+ status_color = format_appliance_status_color(appliance)
32
+ out << "#{status_color}#{status_str.upcase}#{return_color}"
33
+ # meh, probably keep this separate
34
+ if show_current && appliance[:active]
35
+ out << " " + format_is_current() + return_color
36
+ end
37
+ out
38
+ end
39
+
40
+ def format_appliance_status_color(appliance)
41
+ status = appliance[:status].to_s.downcase
42
+ if status == 'ready'
43
+ green
44
+ elsif status == 'fresh'
45
+ magenta
46
+ elsif status == 'new'
47
+ cyan
48
+ elsif ['error', 'http-error', 'net-error', 'ssl-error', 'http-timeout', 'unreachable', 'unrecognized'].include?(status)
49
+ red
50
+ else
51
+ yellow
52
+ end
53
+ end
54
+
55
+ def format_is_current(return_color=cyan)
56
+ "#{cyan}#{bold}(current)#{reset}#{return_color}"
57
+ end
58
+
59
+ def format_appliance_secure(app_map, return_color=cyan)
60
+ return "" if !app_map
61
+ out = ""
62
+ app_url = (app_map[:url] || app_map[:host]).to_s
63
+ is_ssl = app_url =~ /^https/
64
+ if !is_ssl
65
+ # out << "No (no SSL)"
66
+ out << "No"
67
+ else
68
+ if app_map[:insecure]
69
+ # out << "No (Ignore SSL Errors)"
70
+ out << "No"
71
+ else
72
+ # should have a flag that gets set when everything actually looks good..
73
+ out << "Yes"
74
+ end
75
+ end
76
+ out
77
+ end
78
+
79
+ # get display info about the current and past sessions
80
+ #
81
+ def get_appliance_session_blurbs(app_map)
82
+ # app_map = OStruct.new(app_map)
83
+ blurbs = []
84
+ # Current User
85
+ #
86
+ username = app_map[:username]
87
+
88
+ # if app_map[:active]
89
+ # blurbs << "(current)"
90
+ # end
91
+ if app_map[:status] == 'ready'
92
+
93
+ if app_map[:authenticated]
94
+ #blurbs << app_map[:username] ? "Authenticated as #{app_map[:username]}" : "Authenticated"
95
+ # blurbs << "Authenticated."
96
+ if app_map[:last_login_at]
97
+ blurbs << "Logged in #{format_duration_ago(app_map[:last_login_at])}"
98
+ end
99
+ else
100
+ if app_map[:last_logout_at]
101
+ blurbs << "Logged out #{format_duration_ago(app_map[:last_logout_at])}"
102
+ else
103
+ #blurbs << "Logged out"
104
+ end
105
+ if app_map[:last_login_at]
106
+ blurbs << "Last login #{format_duration_ago(app_map[:last_login_at])}"
107
+ end
108
+ end
109
+
110
+ if app_map[:last_success_at]
111
+ blurbs << "Last success #{format_duration_ago(app_map[:last_success_at])}"
112
+ end
113
+
114
+ else
115
+
116
+ if app_map[:last_check]
117
+ if app_map[:last_check][:timestamp]
118
+ blurbs << "Last checked #{format_duration_ago(app_map[:last_check][:timestamp])}"
119
+ end
120
+ if app_map[:last_check][:error]
121
+ last_error_msg = truncate_string(app_map[:last_check][:error], 250)
122
+ blurbs << "Error: #{last_error_msg}"
123
+ end
124
+ if app_map[:last_check][:http_status]
125
+ blurbs << "HTTP #{app_map[:last_check][:http_status]}"
126
+ end
127
+ end
128
+
129
+ if app_map[:last_success_at]
130
+ blurbs << "Last Success: #{format_duration_ago(app_map[:last_success_at])}"
131
+ end
132
+
133
+ end
134
+
135
+ return blurbs
136
+ end
137
+
138
+
139
+ end
@@ -28,9 +28,10 @@ class Morpheus::Cli::MonitoringChecksCommand
28
28
  optparse = Morpheus::Cli::OptionParser.new do |opts|
29
29
  opts.banner = subcommand_usage()
30
30
  # todo: api to load type id by name
31
- # opts.on('--type VALUE', Array, "Filter by status. error,healthy,warning,muted") do |val|
32
- # params['checkType'] = val
33
- # end
31
+ opts.on('-t', '--type TYPE', String, "Filter by Check Type") do |val|
32
+ options[:type] ||= []
33
+ options[:type] << val
34
+ end
34
35
  opts.on('--status VALUE', Array, "Filter by status. error,healthy,warning,muted") do |val|
35
36
  params['status'] = val
36
37
  end
@@ -40,6 +41,10 @@ class Morpheus::Cli::MonitoringChecksCommand
40
41
  connect(options)
41
42
  begin
42
43
  params.merge!(parse_list_options(options))
44
+ if options[:type]
45
+ # API works with type code or name
46
+ params['type'] = options[:type]
47
+ end
43
48
  @monitoring_checks_interface.setopts(options)
44
49
  if options[:dry_run]
45
50
  print_dry_run @monitoring_checks_interface.dry.list(params)
@@ -59,6 +64,9 @@ class Morpheus::Cli::MonitoringChecksCommand
59
64
  checks = json_response['checks']
60
65
  title = "Morpheus Monitoring Checks"
61
66
  subtitles = []
67
+ if options[:type]
68
+ subtitles << "Type: #{options[:type].join(',')}"
69
+ end
62
70
  subtitles += parse_list_subtitles(options)
63
71
  print_h1 title, subtitles, options
64
72
  if checks.empty?
@@ -246,7 +246,7 @@ class Morpheus::Cli::NetworkGroupsCommand
246
246
  end
247
247
  end
248
248
  opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
249
- group_access_all = val.to_s == 'on' || val.to_s == 'true'
249
+ group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
250
250
  end
251
251
  opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list|
252
252
  if list.size == 1 && list[0] == 'null' # hacky way to clear it
@@ -442,7 +442,7 @@ class Morpheus::Cli::NetworkGroupsCommand
442
442
  end
443
443
  end
444
444
  opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
445
- group_access_all = val.to_s == 'on' || val.to_s == 'true'
445
+ group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
446
446
  end
447
447
  opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list|
448
448
  if list.size == 1 && list[0] == 'null' # hacky way to clear it
@@ -579,6 +579,12 @@ class Morpheus::Cli::NetworkGroupsCommand
579
579
  payload['networkGroup']['active'] = options['active']
580
580
  end
581
581
 
582
+ # pre 4.2.1, would error with data not found unless you pass something in here
583
+ # so pass foo=bar so you can update just resourcePermissions
584
+ if payload['networkGroup'] && payload['networkGroup'].empty? && payload['resourcePermissions']
585
+ payload['networkGroup']['foo'] = 'bar'
586
+ end
587
+
582
588
  end
583
589
  @network_groups_interface.setopts(options)
584
590
  if options[:dry_run]
@@ -320,7 +320,7 @@ module Morpheus
320
320
  select_options = load_source_options(option_type['optionSource'], api_client, grails_params(api_params || {}))
321
321
  end
322
322
  else
323
- raise "select_prompt() requires selectOptions or optionSource!"
323
+ raise "option '#{field_key}' is type: 'select' and missing selectOptions or optionSource!"
324
324
  end
325
325
 
326
326
  # ensure the preselected value (passed as an option) is in the dropdown
@@ -0,0 +1,252 @@
1
+ # require 'yaml'
2
+ require 'io/console'
3
+ require 'rest_client'
4
+ require 'optparse'
5
+ require 'morpheus/cli/cli_command'
6
+ require 'morpheus/cli/mixins/whoami_helper'
7
+ require 'morpheus/cli/mixins/accounts_helper'
8
+ require 'json'
9
+
10
+ class Morpheus::Cli::Ping
11
+ include Morpheus::Cli::CliCommand
12
+ include Morpheus::Cli::RemoteHelper
13
+
14
+ set_command_name :ping
15
+
16
+ def connect(options={})
17
+ @api_client = establish_remote_appliance_connection({:no_authorization => true}.merge(options))
18
+ @ping_interface = @api_client.ping
19
+ @setup_interface = @api_client.setup
20
+ end
21
+
22
+ def handle(args)
23
+ get(args)
24
+ end
25
+
26
+ def get(args)
27
+ exit_code, err = 0, nil
28
+ params, options = {}, {}
29
+ status_only, time_only, setup_check_only = false, false, false
30
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
31
+ opts.banner = usage
32
+ opts.on( '-s', '--status', "Print only the status." ) do
33
+ status_only = true
34
+ end
35
+ opts.on( '-t', '--time', "Print only the response time." ) do
36
+ time_only = true
37
+ end
38
+ opts.on( '--setup-needed?', "Print only if setup is needed or not, exit 1 if not." ) do
39
+ setup_check_only = true
40
+ end
41
+ # --timeout always works, this would just make it show up?
42
+ # opts.on( '--timeout SECONDS', "Timeout for api requests. Default is 5 seconds." ) do |val|
43
+ # options[:timeout] = val ? val.to_f : nil
44
+ # # note that setting :timeout works via interface.setopts(options)
45
+ # end
46
+ build_standard_get_options(opts, options, [:quiet])
47
+ opts.footer = <<-EOT
48
+ Ping the remote morpheus appliance.
49
+ Prints the remote version and status and the time it took to get a response.
50
+
51
+ EOT
52
+ end
53
+ optparse.parse!(args)
54
+ verify_args!(args:args, count:0, optparse:optparse)
55
+ connect(options)
56
+ took_sec = nil
57
+ begin
58
+ # construct parameters
59
+ params.merge!(parse_query_options(options))
60
+
61
+ # error if we could not determine a remote, this should happen by in connect()
62
+ # if !@remote_appliance
63
+ # raise_command_error "#{command_name} requires a remote to be specified, use -r [remote] or set the active remote with `remote use`"
64
+ # end
65
+ appliance = @remote_appliance
66
+
67
+ # set api client options
68
+ @ping_interface.setopts(options)
69
+ @setup_interface.setopts(options)
70
+
71
+ # dry run, print the would be request
72
+ if options[:dry_run]
73
+ print_dry_run @ping_interface.dry.get(params)
74
+ return 0
75
+ end
76
+ # execute the api request
77
+ # /api/ping is new in 4.2.1, so fallback to /api/setup/check, the data is the same-ish
78
+ api_exception = nil
79
+ json_response = nil
80
+ start_time = Time.now
81
+ begin
82
+ json_response = @ping_interface.get(params)
83
+ rescue RestClient::Exception => e
84
+ # api_exception = e
85
+ # fallback to older /api/setup/check, which is also public and looks just about the same
86
+ if e.response.code == 404
87
+ start_time = Time.now
88
+ begin
89
+ json_response = @setup_interface.check(params)
90
+ rescue RestClient::Exception => e2
91
+ begin
92
+ json_response = JSON.parse(e2.response.to_s)
93
+ rescue TypeError, JSON::ParserError => ex
94
+ #print_error red, "Failed to parse JSON response: #{ex}", reset, "\n"
95
+ json_response = nil
96
+ end
97
+ end
98
+ end
99
+ rescue => e
100
+ api_exception = e
101
+ ensure
102
+ took_sec = (Time.now - start_time)
103
+ end
104
+
105
+ # update appliance settings with /ping response (or /setup/check) ie. buildVersion
106
+ # this also happens in save_remote_last_check() but remote_url doesnt use that
107
+ if json_response
108
+ # update buildVersion
109
+ if json_response['buildVersion']
110
+ appliance[:build_version] = json_response['buildVersion']
111
+ end
112
+ # update applianceUrl
113
+ if json_response['applianceUrl']
114
+ appliance[:appliance_url] = json_response['applianceUrl']
115
+ end
116
+ # set status to ready if we have a version but no status yet for some reason
117
+ if appliance[:build_version] && appliance[:status].nil?
118
+ appliance[:status] = 'ready'
119
+ end
120
+ # update setupNeeded?
121
+ if json_response['setupNeeded'] == true
122
+ # appliance[:setup_needed] = true
123
+ appliance[:status] = 'fresh'
124
+ end
125
+ # if took_sec
126
+ # appliance[:last_check] ||= {}
127
+ # appliance[:last_check][:took] = took_sec
128
+ # end
129
+ else
130
+ # appliance[:status] = 'error'
131
+ end
132
+
133
+ # don't ever save with --remote-url
134
+ if options[:remote_url].nil?
135
+ # save response to appliance data
136
+ Morpheus::Cli::Remote.save_remote_last_check(appliance, json_response, api_exception, took_sec)
137
+ # reload needed?
138
+ # appliance = ::Morpheus::Cli::Remote.appliances[@appliance_name.to_sym]
139
+ appliance = ::Morpheus::Cli::Remote.load_remote(@appliance_name)
140
+ end
141
+
142
+ # determine exit status, 0 is good
143
+ exit_code, err = 0, nil
144
+ if appliance[:status] != 'ready' && appliance[:status] != 'fresh'
145
+ exit_code = 1
146
+ # err = appliance[:error]
147
+ end
148
+
149
+ # render
150
+ render_response(json_response, options) do
151
+ if json_response.nil?
152
+ json_response = {}
153
+ end
154
+ if false && json_response.nil?
155
+ print_error yellow, "No ping data returned.",reset,"\n"
156
+ else
157
+ # print output
158
+ if status_only
159
+ if exit_code == 0
160
+ print format_appliance_status(appliance, cyan), reset, "\n"
161
+ else
162
+ print_error format_appliance_status(appliance, cyan), reset, "\n"
163
+ end
164
+ return exit_code, err
165
+ elsif time_only
166
+ status_color = format_appliance_status_color(appliance)
167
+ if exit_code == 0
168
+ print status_color, format_duration_seconds(took_sec), reset, "\n"
169
+ else
170
+ print_error status_color, format_duration_seconds(took_sec), reset, "\n"
171
+ end
172
+ return exit_code, err
173
+ elsif setup_check_only
174
+ status_color = format_appliance_status_color(appliance)
175
+ remote_status_string = format_appliance_status(appliance, cyan)
176
+ if appliance[:status] != 'fresh'
177
+ exit_code = 1
178
+ end
179
+ if appliance[:status] == 'fresh'
180
+ print cyan, "Yes, remote #{appliance[:name]} status is #{remote_status_string}","\n"
181
+ elsif appliance[:status] == 'ready'
182
+ print cyan, "No, remote #{appliance[:name]} status is #{remote_status_string} (already setup)","\n"
183
+ else
184
+ print_error cyan,"Uh oh, remote #{appliance[:name]} status is #{remote_status_string}",reset,"\n"
185
+ end
186
+ return exit_code, err
187
+ else
188
+ title = "Morpheus Ping"
189
+ subtitles = []
190
+ print_h1 title, subtitles, options
191
+ #print_green_success "Completed ping of #{appliance[:name]} (#{format_duration_seconds(took_sec)})"
192
+ #print "\n"
193
+ error_string = appliance[:last_check] ? appliance[:last_check][:error] : nil
194
+ columns = {
195
+ "Name" => lambda {|it| appliance[:name] },
196
+ #"Name" => lambda {|it| appliance[:active] ? "#{appliance[:name]} #{bold}(current)#{reset}#{cyan}" : appliance[:name] },
197
+ "URL" => lambda {|it| appliance[:url] },
198
+ #"Appliance URL" => lambda {|it| it['applianceUrl'] },
199
+ "Version" => lambda {|it| appliance[:build_version] },
200
+ # "Active" => lambda {|it| it[:active] ? "Yes " + format_is_current() : "No" },
201
+ "Response Time" => lambda {|it| format_duration_seconds(took_sec) },
202
+ #"Response Time" => lambda {|it| format_sig_dig(took_sec, 3) + "s" rescue "" },
203
+ # "Error" => lambda {|it| error_string },
204
+ "Status" => lambda {|it| format_appliance_status(appliance, cyan) },
205
+ }
206
+ if error_string.to_s.empty?
207
+ columns.delete("Error")
208
+ end
209
+
210
+ print_description_list(columns, json_response, options)
211
+
212
+ if error_string.to_s != ""
213
+ #print_h2 "Error", options
214
+ print "\n"
215
+ print red, error_string, "\n",reset
216
+ end
217
+ end
218
+ print reset, "\n"
219
+ end
220
+ end
221
+ return exit_code, err
222
+
223
+
224
+ rescue RestClient::Exception => e
225
+ # don't ever save with --remote-url
226
+ if options[:remote_url].nil?
227
+ # save response to appliance data
228
+ Morpheus::Cli::Remote.save_remote_last_check(appliance, json_response, e, took_sec)
229
+ # reload?
230
+ appliance = ::Morpheus::Cli::Remote.load_remote(appliance[:name])
231
+ end
232
+ # print output
233
+ if status_only
234
+ print format_appliance_status(appliance, cyan), reset, "\n"
235
+ return exit_code, err
236
+ elsif time_only
237
+ status_color = format_appliance_status_color(appliance)
238
+ print status_color, format_duration_seconds(took_sec), reset, "\n"
239
+ return exit_code, err
240
+ else
241
+ if e.response
242
+ print_red_alert "ping failed in #{format_duration_seconds(took_sec)} (HTTP #{e.response.code})"
243
+ else
244
+ print_red_alert "ping failed in #{format_duration_seconds(took_sec)}"
245
+ end
246
+ end
247
+ print_rest_exception(e, options)
248
+ return 1, e.message
249
+ end
250
+ end
251
+
252
+ end