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.
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
@@ -17,26 +17,17 @@ class Morpheus::Cli::Whoami
17
17
 
18
18
  # no subcommands, just show()
19
19
 
20
- def initialize()
21
- # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
22
- end
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
- show(args)
27
+ get(args)
37
28
  end
38
29
 
39
- def show(args)
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 (Feature Access)") do
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('-f','--feature-access', "Display Feature Access") do
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
- build_common_options(opts, options, [:json, :remote, :dry_run, :quiet])
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
- # check to see if they have credentials instead of just trying to connect (and prompting)
80
-
81
- if !@appliance_name
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 @api_client.whoami.setopts(options).dry.get(params)
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
- whoami_interface = @api_client.whoami.setopts(options)
115
- whoami_response = whoami_interface.get()
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.empty?
119
- print_red_alert "Unauthenticated. Please login."
120
- exit 1
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
- 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"
140
- return 0
141
- end
129
+ render_response(json_response, options) do
142
130
 
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"
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
- active_group = nil
158
- begin
159
- active_group = @active_group_id ? find_group_by_name_or_id(@active_group_id) : nil # via InfrastructureHelper mixin
160
- rescue => err
161
- if options[:debug]
162
- print red,"Unable to determine active group: #{err}\n",reset
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
- print_h1 "Current User", options
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
- "Account" => lambda {|it| (it['account'] ? it['account']['name'] : '') + (@is_master_account ? " (Master Account)" : '') },
180
- # "First Name" => 'firstName',
181
- # "Last Name" => 'lastName',
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: get_access_string(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: get_access_string(it['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
- print_h1 "Remote Appliance", options
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 "system: #{open_command}"
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
@@ -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
- seconds = seconds.floor
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
- "#{name} - #{url}"
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