morpheus-cli 3.5.2 → 3.5.3

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/api_client.rb +16 -0
  3. data/lib/morpheus/api/blueprints_interface.rb +84 -0
  4. data/lib/morpheus/api/execution_request_interface.rb +33 -0
  5. data/lib/morpheus/api/instances_interface.rb +21 -0
  6. data/lib/morpheus/api/packages_interface.rb +25 -5
  7. data/lib/morpheus/api/processes_interface.rb +34 -0
  8. data/lib/morpheus/api/roles_interface.rb +7 -0
  9. data/lib/morpheus/api/servers_interface.rb +8 -0
  10. data/lib/morpheus/api/user_settings_interface.rb +76 -0
  11. data/lib/morpheus/cli.rb +5 -1
  12. data/lib/morpheus/cli/alias_command.rb +1 -1
  13. data/lib/morpheus/cli/app_templates.rb +2 -1
  14. data/lib/morpheus/cli/apps.rb +173 -19
  15. data/lib/morpheus/cli/blueprints_command.rb +2134 -0
  16. data/lib/morpheus/cli/cli_command.rb +3 -1
  17. data/lib/morpheus/cli/clouds.rb +4 -10
  18. data/lib/morpheus/cli/coloring_command.rb +14 -8
  19. data/lib/morpheus/cli/containers_command.rb +92 -5
  20. data/lib/morpheus/cli/execution_request_command.rb +313 -0
  21. data/lib/morpheus/cli/hosts.rb +188 -7
  22. data/lib/morpheus/cli/instances.rb +472 -9
  23. data/lib/morpheus/cli/login.rb +1 -1
  24. data/lib/morpheus/cli/mixins/print_helper.rb +8 -0
  25. data/lib/morpheus/cli/mixins/processes_helper.rb +134 -0
  26. data/lib/morpheus/cli/option_types.rb +21 -16
  27. data/lib/morpheus/cli/packages_command.rb +469 -17
  28. data/lib/morpheus/cli/processes_command.rb +313 -0
  29. data/lib/morpheus/cli/remote.rb +20 -9
  30. data/lib/morpheus/cli/roles.rb +186 -6
  31. data/lib/morpheus/cli/shell.rb +10 -1
  32. data/lib/morpheus/cli/tasks.rb +4 -1
  33. data/lib/morpheus/cli/user_settings_command.rb +431 -0
  34. data/lib/morpheus/cli/version.rb +1 -1
  35. data/lib/morpheus/cli/whoami.rb +1 -1
  36. data/lib/morpheus/formatters.rb +14 -0
  37. data/lib/morpheus/morpkg.rb +119 -0
  38. data/morpheus-cli.gemspec +1 -0
  39. metadata +26 -2
@@ -530,7 +530,12 @@ class Morpheus::Cli::Shell
530
530
  return Morpheus::Cli::SourceCommand.new.handle(input.split[1..-1])
531
531
  end
532
532
  cmd_result = nil
533
- @return_to_log_level = Morpheus::Logging.log_level
533
+ unless input =~ /log-level/
534
+ @return_to_log_level = Morpheus::Logging.log_level
535
+ end
536
+ unless input =~ /coloring/
537
+ @return_to_coloring = Term::ANSIColor::coloring?
538
+ end
534
539
  begin
535
540
  argv = Shellwords.shellsplit(input)
536
541
  cmd_name = argv[0]
@@ -561,6 +566,10 @@ class Morpheus::Cli::Shell
561
566
  ::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
562
567
  @return_to_log_level = nil
563
568
  end
569
+ if @return_to_coloring != nil
570
+ Term::ANSIColor::coloring = @return_to_coloring
571
+ @return_to_coloring = nil
572
+ end
564
573
  end
565
574
 
566
575
  # commands should be a number or nil (treated as 0)
@@ -24,15 +24,18 @@ class Morpheus::Cli::Tasks
24
24
  end
25
25
 
26
26
  def list(args)
27
+ params = {}
27
28
  options = {}
28
29
  optparse = Morpheus::Cli::OptionParser.new do |opts|
29
30
  opts.banner = subcommand_usage()
31
+ opts.on('--types x,y,z', Array, "Filter by task type code(s)") do |val|
32
+ params['taskTypeCodes'] = val
33
+ end
30
34
  build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
31
35
  end
32
36
  optparse.parse!(args)
33
37
  connect(options)
34
38
  begin
35
- params = {}
36
39
  params.merge!(parse_list_options(options))
37
40
  if options[:dry_run]
38
41
  print_dry_run @tasks_interface.dry.get(params)
@@ -0,0 +1,431 @@
1
+ require 'morpheus/cli/cli_command'
2
+
3
+ class Morpheus::Cli::UserSettingsCommand
4
+ include Morpheus::Cli::CliCommand
5
+
6
+ set_command_name :'user-settings'
7
+
8
+ register_subcommands :get, :update, :'update-avatar', :'view-avatar', :'regenerate-access-token', :'clear-access-token', :'list-clients'
9
+
10
+ set_default_subcommand :get
11
+
12
+ def initialize()
13
+ # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
14
+ end
15
+
16
+ def connect(opts)
17
+ @api_client = establish_remote_appliance_connection(opts)
18
+ @user_settings_interface = @api_client.user_settings
19
+ end
20
+
21
+ def handle(args)
22
+ handle_subcommand(args)
23
+ end
24
+
25
+ def get(args)
26
+ raw_args = args
27
+ options = {}
28
+ params = {}
29
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
30
+ opts.banner = subcommand_usage()
31
+ build_common_options(opts, options, [:query, :json, :yaml, :csv, :fields, :dry_run, :remote])
32
+ opts.footer = "Get your user settings."
33
+ end
34
+ optparse.parse!(args)
35
+ connect(options)
36
+ if args.count != 0
37
+ print_error Morpheus::Terminal.angry_prompt
38
+ puts_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.inspect}\n#{optparse}"
39
+ return 1
40
+ end
41
+
42
+ begin
43
+ params.merge!(parse_list_options(options))
44
+ if options[:dry_run]
45
+ print_dry_run @user_settings_interface.dry.get(params)
46
+ return
47
+ end
48
+ json_response = @user_settings_interface.get(params)
49
+ if options[:json]
50
+ puts as_json(json_response, options, "user")
51
+ return 0
52
+ elsif options[:yaml]
53
+ puts as_yaml(json_response, options, "user")
54
+ return 0
55
+ elsif options[:csv]
56
+ puts records_as_csv([json_response['user']], options)
57
+ return 0
58
+ end
59
+
60
+ user_settings = json_response['user'] || json_response['userSettings']
61
+ access_tokens = user_settings['accessTokens'] || json_response['accessTokens'] || json_response['apiAccessTokens'] || []
62
+
63
+ print_h1 "User Settings"
64
+ print cyan
65
+ description_cols = {
66
+ #"ID" => lambda {|it| it['id'] },
67
+ "ID" => lambda {|it| it['id'] },
68
+ "Username" => lambda {|it| it['username'] },
69
+ "First Name" => lambda {|it| it['firstName'] },
70
+ "Last Name" => lambda {|it| it['lastName'] },
71
+ "Email" => lambda {|it| it['email'] },
72
+ "Avatar" => lambda {|it| it['avatar'] ? it['avatar'].split('/').last : '' },
73
+ "Notifications" => lambda {|it| format_boolean(it['receiveNotifications']) },
74
+ "Linux Username" => lambda {|it| it['linuxUsername'] },
75
+ "Linux Password" => lambda {|it| it['linuxPassword'] },
76
+ "Linux Key Pair" => lambda {|it| it['linuxKeyPairId'] },
77
+ "Windows Username" => lambda {|it| it['windowsUsername'] },
78
+ "Windows Password" => lambda {|it| it['windowsPassword'] },
79
+ }
80
+ print_description_list(description_cols, user_settings)
81
+
82
+ if access_tokens && !access_tokens.empty?
83
+ print_h2 "API Access Tokens"
84
+ cols = {
85
+ #"ID" => lambda {|it| it['id'] },
86
+ "Client ID" => lambda {|it| it['clientId'] },
87
+ "Username" => lambda {|it| it['username'] },
88
+ "Expiration" => lambda {|it| format_local_dt(it['expiration']) }
89
+ }
90
+ print cyan
91
+ puts as_pretty_table(access_tokens, cols)
92
+ end
93
+
94
+ print reset #, "\n"
95
+ return 0
96
+ rescue RestClient::Exception => e
97
+ print_rest_exception(e, options)
98
+ return 1
99
+ end
100
+ end
101
+
102
+
103
+ def update(args)
104
+ raw_args = args
105
+ options = {}
106
+ params = {}
107
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
108
+ opts.banner = subcommand_usage("[options]")
109
+ build_common_options(opts, options, [:payload, :options, :json, :dry_run, :quiet, :remote])
110
+ opts.footer = "Update your user settings."
111
+ end
112
+ optparse.parse!(args)
113
+ connect(options)
114
+ if args.count != 0
115
+ print_error Morpheus::Terminal.angry_prompt
116
+ puts_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.inspect}\n#{optparse}"
117
+ return 1
118
+ end
119
+
120
+ begin
121
+ payload = {}
122
+ if options[:payload]
123
+ payload = options[:payload]
124
+ else
125
+
126
+ end
127
+
128
+ if options[:options]
129
+ payload['user'] ||= {}
130
+ payload['user'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) })
131
+ end
132
+
133
+ if options[:dry_run]
134
+ print_dry_run @user_settings_interface.dry.update(params, payload)
135
+ return
136
+ end
137
+ json_response = @user_settings_interface.update(params, payload)
138
+ if options[:quiet]
139
+ return 0
140
+ elsif options[:json]
141
+ puts as_json(json_response, options)
142
+ return 0
143
+ end
144
+
145
+ print_green_success "Updated user settings"
146
+ get([])
147
+ return 0
148
+ rescue RestClient::Exception => e
149
+ print_rest_exception(e, options)
150
+ return 1
151
+ end
152
+ end
153
+
154
+ def update_avatar(args)
155
+ options = {}
156
+ params = {}
157
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
158
+ opts.banner = subcommand_usage("[file]")
159
+ build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
160
+ opts.footer = "Update your avatar profile image.\n" +
161
+ "[file] is required. This is the local path of a file to upload [png|jpg|svg]."
162
+ end
163
+ optparse.parse!(args)
164
+ connect(options)
165
+ if args.count != 1
166
+ print_error Morpheus::Terminal.angry_prompt
167
+ puts_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
168
+ return 1
169
+ end
170
+ filename = File.expand_path(args[0].to_s)
171
+ image_file = nil
172
+ if filename && File.file?(filename)
173
+ # maybe validate it's an image file? [.png|jpg|svg]
174
+ image_file = File.new(filename, 'rb')
175
+ else
176
+ # print_red_alert "File not found: #{filename}"
177
+ puts_error "#{Morpheus::Terminal.angry_prompt}File not found: #{filename}"
178
+ return 1
179
+ end
180
+
181
+ begin
182
+ if options[:dry_run]
183
+ print_dry_run @user_settings_interface.dry.update_avatar(image_file, params)
184
+ return
185
+ end
186
+ json_response = @user_settings_interface.update_avatar(image_file, params)
187
+ if options[:quiet]
188
+ return 0
189
+ elsif options[:json]
190
+ puts as_json(json_response, options)
191
+ return 0
192
+ end
193
+
194
+ print_green_success "Updated avatar"
195
+ get([])
196
+ return 0
197
+ rescue RestClient::Exception => e
198
+ print_rest_exception(e, options)
199
+ return 1
200
+ end
201
+ end
202
+
203
+ def remove_avatar(args)
204
+ options = {}
205
+ params = {}
206
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
207
+ opts.banner = subcommand_usage("[file]")
208
+ build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
209
+ opts.footer = "Remove your avatar profile image."
210
+ end
211
+ optparse.parse!(args)
212
+ connect(options)
213
+ if args.count != 0
214
+ print_error Morpheus::Terminal.angry_prompt
215
+ puts_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.inspect}\n#{optparse}"
216
+ return 1
217
+ end
218
+
219
+ begin
220
+ if options[:dry_run]
221
+ print_dry_run @user_settings_interface.dry.remove_avatar(params)
222
+ return
223
+ end
224
+ json_response = @user_settings_interface.remove_avatar(params)
225
+ if options[:quiet]
226
+ return 0
227
+ elsif options[:json]
228
+ puts as_json(json_response, options)
229
+ return 0
230
+ end
231
+
232
+ print_green_success "Removed avatar"
233
+ get([])
234
+ return 0
235
+ rescue RestClient::Exception => e
236
+ print_rest_exception(e, options)
237
+ return 1
238
+ end
239
+ end
240
+
241
+ def view_avatar(args)
242
+ raw_args = args
243
+ options = {}
244
+ params = {}
245
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
246
+ opts.banner = subcommand_usage()
247
+ build_common_options(opts, options, [:remote])
248
+ opts.footer = "View your avatar profile image.\n" +
249
+ "This opens the avatar image url with a web browser."
250
+ end
251
+ optparse.parse!(args)
252
+ connect(options)
253
+ if args.count != 0
254
+ print_error Morpheus::Terminal.angry_prompt
255
+ puts_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.inspect}\n#{optparse}"
256
+ return 1
257
+ end
258
+
259
+ begin
260
+
261
+ json_response = @user_settings_interface.get(params)
262
+ user_settings = json_response['user'] || json_response['userSettings']
263
+
264
+ if user_settings['avatar']
265
+ link = user_settings['avatar']
266
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
267
+ system "start #{link}"
268
+ elsif RbConfig::CONFIG['host_os'] =~ /darwin/
269
+ system "open #{link}"
270
+ elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
271
+ system "xdg-open #{link}"
272
+ end
273
+ return 0, nil
274
+ else
275
+ print_error red,"No avatar image found.",reset,"\n"
276
+ return 1
277
+ end
278
+
279
+ rescue RestClient::Exception => e
280
+ print_rest_exception(e, options)
281
+ return 1
282
+ end
283
+ end
284
+
285
+ def regenerate_access_token(args)
286
+ raw_args = args
287
+ options = {}
288
+ params = {}
289
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
290
+ opts.banner = subcommand_usage("[client-id]")
291
+ build_common_options(opts, options, [:payload, :options, :json, :dry_run, :quiet, :remote])
292
+ opts.footer = "Regenerate API access token for a specific client.\n" +
293
+ "[client-id] is required. This is the id of an api client."
294
+ end
295
+ optparse.parse!(args)
296
+ connect(options)
297
+ if args.count != 1
298
+ print_error Morpheus::Terminal.angry_prompt
299
+ puts_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
300
+ return 1
301
+ end
302
+ params['clientId'] = args[0]
303
+ begin
304
+ payload = {}
305
+ if options[:dry_run]
306
+ print_dry_run @user_settings_interface.dry.regenerate_access_token(params, payload)
307
+ return
308
+ end
309
+ json_response = @user_settings_interface.regenerate_access_token(params, payload)
310
+ new_access_token = json_response['token']
311
+ # update credentials if regenerating cli token
312
+ if params['clientId'] == 'morph-cli'
313
+ if new_access_token
314
+ login_opts = {:remote_token => new_access_token}
315
+ login_result = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).login(login_opts)
316
+ end
317
+ end
318
+ if options[:quiet]
319
+ return 0
320
+ elsif options[:json]
321
+ puts as_json(json_response, options)
322
+ return 0
323
+ end
324
+ print_green_success "Regenerated #{params['clientId']} access token: #{new_access_token}"
325
+ get([])
326
+ return 0
327
+ rescue RestClient::Exception => e
328
+ print_rest_exception(e, options)
329
+ return 1
330
+ end
331
+ end
332
+
333
+ def clear_access_token(args)
334
+ raw_args = args
335
+ options = {}
336
+ params = {}
337
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
338
+ opts.banner = subcommand_usage("[client-id]")
339
+ build_common_options(opts, options, [:payload, :options, :json, :dry_run, :quiet, :remote])
340
+ opts.footer = "Clear API access token for a specific client.\n" +
341
+ "[client-id] is required. This is the id of an api client."
342
+ end
343
+ optparse.parse!(args)
344
+ connect(options)
345
+ if args.count != 1
346
+ print_error Morpheus::Terminal.angry_prompt
347
+ puts_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
348
+ return 1
349
+ end
350
+ params['clientId'] = args[0]
351
+ begin
352
+ payload = {}
353
+ if options[:dry_run]
354
+ print_dry_run @user_settings_interface.dry.clear_access_token(params, payload)
355
+ return
356
+ end
357
+ json_response = @user_settings_interface.clear_access_token(params, payload)
358
+ if options[:quiet]
359
+ return 0
360
+ elsif options[:json]
361
+ puts as_json(json_response, options)
362
+ return 0
363
+ end
364
+ new_access_token = json_response['token']
365
+ # update credentials if regenerating cli token
366
+ # if params['clientId'] == 'morph-cli'
367
+ # logout_result = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).logout
368
+ # end
369
+ print_green_success "Cleared #{params['clientId']} access token"
370
+ if params['clientId'] == 'morph-cli'
371
+ print yellow,"Your current access token is no longer valid, you will need to login again.",reset,"\n"
372
+ end
373
+ #get([])
374
+ return 0
375
+ rescue RestClient::Exception => e
376
+ print_rest_exception(e, options)
377
+ return 1
378
+ end
379
+ end
380
+
381
+ def list_clients(args)
382
+ raw_args = args
383
+ options = {}
384
+ params = {}
385
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
386
+ opts.banner = subcommand_usage()
387
+ build_common_options(opts, options, [:query, :json, :yaml, :csv, :fields, :dry_run, :remote])
388
+ opts.footer = "List available api clients."
389
+ end
390
+ optparse.parse!(args)
391
+ connect(options)
392
+ if args.count != 0
393
+ print_error Morpheus::Terminal.angry_prompt
394
+ puts_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.inspect}\n#{optparse}"
395
+ return 1
396
+ end
397
+
398
+ begin
399
+ params.merge!(parse_list_options(options))
400
+ if options[:dry_run]
401
+ print_dry_run @user_settings_interface.dry.available_clients(params)
402
+ return
403
+ end
404
+ json_response = @user_settings_interface.available_clients(params)
405
+ if options[:json]
406
+ puts as_json(json_response, options, "clients")
407
+ return 0
408
+ elsif options[:yaml]
409
+ puts as_yaml(json_response, options, "clients")
410
+ return 0
411
+ elsif options[:csv]
412
+ puts records_as_csv(json_response['clients'], options)
413
+ return 0
414
+ end
415
+
416
+ clients = json_response['clients'] || json_response['apiClients']
417
+ print_h1 "Morpheus API Clients"
418
+ columns = {
419
+ "Client ID" => lambda {|it| it['clientId'] }
420
+ }
421
+ print cyan
422
+ puts as_pretty_table(clients, columns)
423
+ print reset #, "\n"
424
+ return 0
425
+ rescue RestClient::Exception => e
426
+ print_rest_exception(e, options)
427
+ return 1
428
+ end
429
+ end
430
+
431
+ end