morpheus-cli 0.1.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/accounts_interface.rb +55 -0
  3. data/lib/morpheus/api/api_client.rb +48 -3
  4. data/lib/morpheus/api/apps_interface.rb +13 -13
  5. data/lib/morpheus/api/{zones_interface.rb → clouds_interface.rb} +10 -10
  6. data/lib/morpheus/api/deploy_interface.rb +4 -4
  7. data/lib/morpheus/api/groups_interface.rb +3 -3
  8. data/lib/morpheus/api/instance_types_interface.rb +2 -2
  9. data/lib/morpheus/api/instances_interface.rb +35 -19
  10. data/lib/morpheus/api/key_pairs_interface.rb +60 -0
  11. data/lib/morpheus/api/license_interface.rb +29 -0
  12. data/lib/morpheus/api/load_balancers_interface.rb +72 -0
  13. data/lib/morpheus/api/logs_interface.rb +37 -0
  14. data/lib/morpheus/api/options_interface.rb +20 -0
  15. data/lib/morpheus/api/provision_types_interface.rb +27 -0
  16. data/lib/morpheus/api/roles_interface.rb +73 -0
  17. data/lib/morpheus/api/security_group_rules_interface.rb +3 -3
  18. data/lib/morpheus/api/security_groups_interface.rb +5 -5
  19. data/lib/morpheus/api/servers_interface.rb +67 -3
  20. data/lib/morpheus/api/task_sets_interface.rb +46 -0
  21. data/lib/morpheus/api/tasks_interface.rb +72 -0
  22. data/lib/morpheus/api/users_interface.rb +72 -0
  23. data/lib/morpheus/cli.rb +27 -4
  24. data/lib/morpheus/cli/accounts.rb +306 -0
  25. data/lib/morpheus/cli/apps.rb +58 -1
  26. data/lib/morpheus/cli/cli_command.rb +87 -0
  27. data/lib/morpheus/cli/cli_registry.rb +6 -1
  28. data/lib/morpheus/cli/{zones.rb → clouds.rb} +99 -70
  29. data/lib/morpheus/cli/credentials.rb +23 -11
  30. data/lib/morpheus/cli/error_handler.rb +31 -11
  31. data/lib/morpheus/cli/groups.rb +1 -0
  32. data/lib/morpheus/cli/hosts.rb +567 -0
  33. data/lib/morpheus/cli/instances.rb +588 -292
  34. data/lib/morpheus/cli/key_pairs.rb +393 -0
  35. data/lib/morpheus/cli/license.rb +118 -0
  36. data/lib/morpheus/cli/load_balancers.rb +366 -0
  37. data/lib/morpheus/cli/mixins/accounts_helper.rb +193 -0
  38. data/lib/morpheus/cli/option_types.rb +260 -0
  39. data/lib/morpheus/cli/roles.rb +164 -0
  40. data/lib/morpheus/cli/security_group_rules.rb +4 -9
  41. data/lib/morpheus/cli/shell.rb +108 -0
  42. data/lib/morpheus/cli/tasks.rb +370 -0
  43. data/lib/morpheus/cli/users.rb +325 -0
  44. data/lib/morpheus/cli/version.rb +1 -1
  45. data/lib/morpheus/cli/workflows.rb +100 -0
  46. data/lib/morpheus/formatters.rb +43 -0
  47. data/morpheus-cli.gemspec +1 -1
  48. metadata +33 -10
  49. data/lib/morpheus/cli/servers.rb +0 -265
@@ -0,0 +1,393 @@
1
+ # require 'yaml'
2
+ require 'io/console'
3
+ require 'rest_client'
4
+ require 'term/ansicolor'
5
+ require 'optparse'
6
+ require 'morpheus/cli/cli_command'
7
+ require 'morpheus/cli/option_types'
8
+ require 'morpheus/cli/mixins/accounts_helper'
9
+ require 'json'
10
+
11
+ class Morpheus::Cli::KeyPairs
12
+ include Term::ANSIColor
13
+ include Morpheus::Cli::CliCommand
14
+ include Morpheus::Cli::AccountsHelper
15
+
16
+ def initialize()
17
+ @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
18
+ end
19
+
20
+ def connect(opts)
21
+ @access_token = Morpheus::Cli::Credentials.new(@appliance_name,@appliance_url).request_credentials()
22
+ if @access_token.empty?
23
+ print red,bold, "\nInvalid Credentials. Unable to acquire access token. Please verify your credentials and try again.\n\n",reset
24
+ exit 1
25
+ end
26
+ @api_client = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url)
27
+ @accounts_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).accounts
28
+ @key_pairs_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).key_pairs
29
+ end
30
+
31
+ def handle(args)
32
+ usage = "Usage: morpheus key-pairs [list,add,update,remove] [name]"
33
+ if args.empty?
34
+ puts "\n#{usage}\n\n"
35
+ exit 1
36
+ end
37
+
38
+ case args[0]
39
+ when 'list'
40
+ list(args[1..-1])
41
+ when 'details'
42
+ details(args[1..-1])
43
+ when 'add'
44
+ add(args[1..-1])
45
+ when 'update'
46
+ update(args[1..-1])
47
+ when 'remove'
48
+ remove(args[1..-1])
49
+ else
50
+ puts "\n#{usage}\n\n"
51
+ exit 127
52
+ end
53
+ end
54
+
55
+ def list(args)
56
+ options = {}
57
+ params = {}
58
+ account = nil
59
+ optparse = OptionParser.new do|opts|
60
+ Morpheus::Cli::CliCommand.accountScopeOptions(opts,options)
61
+ Morpheus::Cli::CliCommand.genericOptions(opts,options)
62
+ end
63
+ optparse.parse(args)
64
+ connect(options)
65
+ begin
66
+
67
+ account = find_account_from_options(options)
68
+ account_id = account ? account['id'] : nil
69
+
70
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
71
+ params[k] = options[k] unless options[k].nil?
72
+ end
73
+
74
+ json_response = @key_pairs_interface.list(account_id, params)
75
+ key_pairs = json_response['keyPairs']
76
+ if options[:json]
77
+ print JSON.pretty_generate(json_response)
78
+ print "\n"
79
+ else
80
+ print "\n" ,cyan, bold, "Morpheus Key Pairs\n","==================", reset, "\n\n"
81
+ if key_pairs.empty?
82
+ puts yellow,"No key pairs found.",reset
83
+ else
84
+ print_key_pairs_table(key_pairs)
85
+ end
86
+ print reset,"\n\n"
87
+ end
88
+ rescue RestClient::Exception => e
89
+ ::Morpheus::Cli::ErrorHandler.new.print_rest_exception(e)
90
+ exit 1
91
+ end
92
+ end
93
+
94
+ def details(args)
95
+ usage = "Usage: morpheus key-pairs details [name] [options]"
96
+ if args.count < 1
97
+ puts "\n#{usage}\n\n"
98
+ exit 1
99
+ end
100
+ account = nil
101
+ name = args[0]
102
+ options = {}
103
+ params = {}
104
+ optparse = OptionParser.new do|opts|
105
+ opts.banner = usage
106
+ Morpheus::Cli::CliCommand.accountScopeOptions(opts,options)
107
+ Morpheus::Cli::CliCommand.genericOptions(opts,options)
108
+ end
109
+ optparse.parse(args)
110
+ connect(options)
111
+ begin
112
+
113
+ account = find_account_from_options(options)
114
+ account_id = account ? account['id'] : nil
115
+
116
+ # todo: key_pairs_response = @key_pairs_interface.list(account_id, {name: name})
117
+ # there may be response data outside of account that needs to be displayed
118
+
119
+ # allow finding by ID since name is not unique!
120
+ key_pair = ((name.to_s =~ /\A\d{1,}\Z/) ? find_key_pair_by_id(account_id, name) : find_key_pair_by_name(account_id, name) )
121
+ exit 1 if key_pair.nil?
122
+
123
+ if options[:json]
124
+ print JSON.pretty_generate(key_pair)
125
+ print "\n"
126
+ else
127
+ print "\n" ,cyan, bold, "Key Pair Details\n","==================", reset, "\n\n"
128
+ print cyan
129
+ puts "ID: #{key_pair['id']}"
130
+ puts "Name: #{key_pair['name']}"
131
+ puts "MD5: #{key_pair['md5']}"
132
+ puts "Date Created: #{format_local_dt(key_pair['dateCreated'])}"
133
+ #puts "Last Updated: #{format_local_dt(key_pair['lastUpdated'])}"
134
+ print reset,"\n\n"
135
+
136
+ # todo: show public key
137
+
138
+ end
139
+ rescue RestClient::Exception => e
140
+ ::Morpheus::Cli::ErrorHandler.new.print_rest_exception(e)
141
+ exit 1
142
+ end
143
+ end
144
+
145
+ def add(args)
146
+ # if args.count > 0
147
+ # puts "\nUsage: morpheus hosts add [options]\n\n"
148
+ # exit 1
149
+ # end
150
+ account_name = nil
151
+ options = {}
152
+ optparse = OptionParser.new do|opts|
153
+ opts.banner = "Usage: morpheus key-pairs add [options]"
154
+
155
+ opts.on( '-a', '--account ACCOUNT', "Account Name" ) do |val|
156
+ account_name = val
157
+ end
158
+
159
+ opts.on( '', '--public-key-file FILENAME', "Public Key File" ) do |filename|
160
+ if File.exists?(filename)
161
+ options['publicKey'] = File.read(filename)
162
+ options[:options] ||= {}
163
+ options[:options]['publicKey'] = options['publicKey']
164
+ else
165
+ print_red_alert "File not found: #{filename}"
166
+ exit 1
167
+ end
168
+ end
169
+
170
+ opts.on( '', '--public-key TEXT', "Public Key Text" ) do |val|
171
+ options['publicKey'] = val
172
+ options[:options] ||= {}
173
+ options[:options]['publicKey'] = options['publicKey']
174
+ end
175
+
176
+ opts.on( '', '--private-key-file FILENAME', "Private Key File" ) do |filename|
177
+ if File.exists?(filename)
178
+ options['privateKey'] = File.read(filename)
179
+ options[:options] ||= {}
180
+ options[:options]['privateKey'] = options['privateKey']
181
+ else
182
+ print_red_alert "File not found: #{filename}"
183
+ exit 1
184
+ end
185
+ end
186
+
187
+ opts.on( '', '--private-key TEXT', "Private Key Text" ) do |val|
188
+ options['privateKey'] = val
189
+ options[:options] ||= {}
190
+ options[:options]['privateKey'] = options['privateKey']
191
+ end
192
+
193
+ Morpheus::Cli::CliCommand.genericOptions(opts,options)
194
+ end
195
+ optparse.parse(args)
196
+
197
+ connect(options)
198
+
199
+ begin
200
+
201
+ # current user account by default
202
+ account = nil
203
+ if !account_name.nil?
204
+ account = find_account_by_name(account_name)
205
+ exit 1 if account.nil?
206
+ end
207
+ account_id = account ? account['id'] : nil
208
+
209
+ params = Morpheus::Cli::OptionTypes.prompt(add_key_pair_option_types, options[:options], @api_client, options[:params]) # options[:params] is mysterious
210
+
211
+ if !params['publicKey']
212
+ print_red_alert "publicKey is required"
213
+ exit 1
214
+ elsif !params['privateKey']
215
+ print_red_alert "privateKey is required"
216
+ exit 1
217
+ end
218
+
219
+ key_pair_payload = params.select {|k,v| ['name', 'publicKey', 'privateKey'].include?(k) }
220
+
221
+ request_payload = {keyPair: key_pair_payload}
222
+ response = @key_pairs_interface.create(account_id, request_payload)
223
+ print "\n", cyan, "Account #{key_pair_payload['name']} added", reset, "\n\n"
224
+ rescue RestClient::Exception => e
225
+ ::Morpheus::Cli::ErrorHandler.new.print_rest_exception(e)
226
+ exit 1
227
+ end
228
+ end
229
+
230
+ def update(args)
231
+ usage = "Usage: morpheus hosts update [name] [options]"
232
+ if args.count < 1
233
+ puts "\n#{usage}\n\n"
234
+ exit 1
235
+ end
236
+ account_name = nil
237
+ name = args[0]
238
+ options = {}
239
+ optparse = OptionParser.new do|opts|
240
+ opts.banner = usage
241
+
242
+ opts.on( '-a', '--account ACCOUNT', "Account Name" ) do |val|
243
+ account_name = val
244
+ end
245
+
246
+ Morpheus::Cli::CliCommand.genericOptions(opts,options)
247
+ end
248
+ optparse.parse(args)
249
+
250
+ connect(options)
251
+
252
+ begin
253
+
254
+ account_id = nil
255
+ if !account_name.nil?
256
+ account = find_account_by_name(account_name)
257
+ exit 1 if account.nil?
258
+ account_id = account['id']
259
+ end
260
+
261
+ key_pair = ((name.to_s =~ /\A\d{1,}\Z/) ? find_key_pair_by_id(account_id, name) : find_key_pair_by_name(account_id, name) )
262
+ exit 1 if key_pair.nil?
263
+
264
+ #params = Morpheus::Cli::OptionTypes.prompt(update_key_pair_option_types, options[:options], @api_client, options[:params]) # options[:params] is mysterious
265
+ params = options[:options] || {}
266
+
267
+ if params.empty?
268
+ puts "\n#{usage}\n\n"
269
+ option_lines = update_key_pair_option_types.collect {|it| "\t-O #{it['fieldName']}=\"value\"" }.join("\n")
270
+ puts "\nAvailable Options:\n#{option_lines}\n\n"
271
+ exit 1
272
+ end
273
+
274
+ key_pair_payload = params.select {|k,v| ['name'].include?(k) }
275
+ request_payload = {keyPair: key_pair_payload}
276
+ response = @key_pairs_interface.update(account_id, key_pair['id'], request_payload)
277
+ print "\n", cyan, "Key Pair #{key_pair_payload['name'] || key_pair['name']} updated", reset, "\n\n"
278
+ rescue RestClient::Exception => e
279
+ ::Morpheus::Cli::ErrorHandler.new.print_rest_exception(e)
280
+ exit 1
281
+ end
282
+ end
283
+
284
+ def remove(args)
285
+ usage = "Usage: morpheus key-pairs remove [name]"
286
+ if args.count < 1
287
+ puts "\n#{usage}\n\n"
288
+ exit 1
289
+ end
290
+ account_name = nil
291
+ name = args[0]
292
+ options = {}
293
+ optparse = OptionParser.new do|opts|
294
+ opts.banner = usage
295
+
296
+ opts.on( '-a', '--account ACCOUNT', "Account Name or ID" ) do |val|
297
+ account_name = val
298
+ end
299
+
300
+ Morpheus::Cli::CliCommand.genericOptions(opts,options)
301
+ end
302
+ optparse.parse(args)
303
+ connect(options)
304
+ begin
305
+ # current user account by default
306
+ account = nil
307
+ if !account_name.nil?
308
+ account = find_account_by_name(account_name)
309
+ exit 1 if account.nil?
310
+ end
311
+ account_id = account ? account['id'] : nil
312
+ # allow finding by ID since name is not unique!
313
+ key_pair = ((name.to_s =~ /\A\d{1,}\Z/) ? find_key_pair_by_id(account_id, name) : find_key_pair_by_name(account_id, name) )
314
+ exit 1 if key_pair.nil?
315
+ exit unless Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the key pair #{key_pair['name']}?")
316
+ @key_pairs_interface.destroy(account_id, key_pair['id'])
317
+ # list([])
318
+ print "\n", cyan, "Key Pair #{key_pair['name']} removed", reset, "\n\n"
319
+ rescue RestClient::Exception => e
320
+ ::Morpheus::Cli::ErrorHandler.new.print_rest_exception(e)
321
+ exit 1
322
+ end
323
+ end
324
+
325
+ private
326
+
327
+ def find_key_pair_by_id(account_id, id)
328
+ raise "#{self.class} has not defined @key_pairs_interface" if @key_pairs_interface.nil?
329
+ begin
330
+ json_response = @key_pairs_interface.get(account_id, id.to_i)
331
+ return json_response['keyPair']
332
+ rescue RestClient::Exception => e
333
+ if e.response.code == 404
334
+ print_red_alert "Key Pair not found by id #{id}"
335
+ else
336
+ raise e
337
+ end
338
+ end
339
+ end
340
+
341
+ def find_key_pair_by_name(account_id, name)
342
+ raise "#{self.class} has not defined @key_pairs_interface" if @key_pairs_interface.nil?
343
+ key_pairs = @key_pairs_interface.list(account_id, {name: name.to_s})['keyPairs']
344
+ if key_pairs.empty?
345
+ print_red_alert "Key Pair not found by name #{name}"
346
+ return nil
347
+ elsif key_pairs.size > 1
348
+ print_red_alert "#{key_pairs.size} key_pairs by name #{name}"
349
+ print_key_pairs_table(key_pairs, {color: red})
350
+ print reset,"\n\n"
351
+ return nil
352
+ else
353
+ return key_pairs[0]
354
+ end
355
+ end
356
+
357
+ def print_key_pairs_table(key_pairs, opts={})
358
+ table_color = opts[:color] || cyan
359
+ rows = key_pairs.collect do |key_pair|
360
+ {
361
+ id: key_pair['id'],
362
+ name: key_pair['name'],
363
+ md5: key_pair['md5'],
364
+ dateCreated: format_local_dt(key_pair['dateCreated'])
365
+ }
366
+ end
367
+
368
+ print table_color
369
+ tp rows, [
370
+ :id,
371
+ :name,
372
+ :md5,
373
+ {:dateCreated => {:display_name => "Date Created"} }
374
+ ]
375
+ print reset
376
+ end
377
+
378
+
379
+ def add_key_pair_option_types
380
+ [
381
+ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
382
+ {'fieldName' => 'publicKey', 'fieldLabel' => 'Public Key', 'type' => 'text', 'required' => true, 'displayOrder' => 2},
383
+ {'fieldName' => 'privateKey', 'fieldLabel' => 'Private Key', 'type' => 'text', 'required' => true, 'displayOrder' => 3},
384
+ ]
385
+ end
386
+
387
+ def update_key_pair_option_types
388
+ [
389
+ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
390
+ ]
391
+ end
392
+
393
+ end
@@ -0,0 +1,118 @@
1
+ # require 'yaml'
2
+ require 'io/console'
3
+ require 'rest_client'
4
+ require 'term/ansicolor'
5
+ require 'optparse'
6
+ require 'table_print'
7
+ require 'morpheus/cli/cli_command'
8
+
9
+ class Morpheus::Cli::License
10
+ include Morpheus::Cli::CliCommand
11
+ include Term::ANSIColor
12
+ def initialize()
13
+ @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
14
+ end
15
+
16
+ def connect(opts)
17
+ if opts[:remote]
18
+ @appliance_url = opts[:remote]
19
+ @appliance_name = opts[:remote]
20
+ @access_token = Morpheus::Cli::Credentials.new(@appliance_name,@appliance_url).request_credentials(opts)
21
+ else
22
+ @access_token = Morpheus::Cli::Credentials.new(@appliance_name,@appliance_url).request_credentials(opts)
23
+ end
24
+ @api_client = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url)
25
+ @license_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).license
26
+
27
+ if @access_token.empty?
28
+ print red,bold, "\nInvalid Credentials. Unable to acquire access token. Please verify your credentials and try again.\n\n",reset
29
+ exit 1
30
+ end
31
+ end
32
+
33
+
34
+ def handle(args)
35
+ if args.empty?
36
+ puts "\nUsage: morpheus license [details, apply]\n\n"
37
+ return
38
+ end
39
+
40
+ case args[0]
41
+ when 'apply'
42
+ apply(args[1..-1])
43
+ when 'details'
44
+ details(args[1..-1])
45
+ else
46
+ puts "\nUsage: morpheus license [details, apply]\n\n"
47
+ exit 127
48
+ end
49
+ end
50
+
51
+
52
+ def details(args)
53
+ options = {}
54
+ optparse = OptionParser.new do|opts|
55
+ opts.banner = "Usage: morpheus license details"
56
+ Morpheus::Cli::CliCommand.genericOptions(opts,options)
57
+ end
58
+ optparse.parse(args)
59
+ connect(options)
60
+ begin
61
+ license = @license_interface.get()
62
+
63
+ if options[:json]
64
+ puts JSON.pretty_generate(license)
65
+ else
66
+ if license['license'].nil?
67
+ puts "No License Currently Applied to the appliance."
68
+ exit 1
69
+ else
70
+ print "\n", cyan, "License\n=======\n"
71
+ max_memory = Filesize.from("#{license['license']['maxMemory']} B").pretty
72
+ max_storage = Filesize.from("#{license['license']['maxStorage']} B").pretty
73
+ used_memory = Filesize.from("#{license['usedMemory']} B").pretty
74
+ puts "Account: #{license['license']['accountName']}"
75
+ puts "Start Date: #{license['license']['startDate']}"
76
+ puts "End Date: #{license['license']['endDate']}"
77
+ puts "Memory: #{used_memory} / #{max_memory}"
78
+ puts "Max Storage: #{max_storage}"
79
+ end
80
+ print reset,"\n\n"
81
+ end
82
+ rescue RestClient::Exception => e
83
+ ::Morpheus::Cli::ErrorHandler.new.print_rest_exception(e)
84
+ exit 1
85
+ end
86
+ end
87
+
88
+ def apply(args)
89
+ key = args[0]
90
+ options = {}
91
+ account_name = nil
92
+ optparse = OptionParser.new do|opts|
93
+ opts.banner = "Usage: morpheus license apply [key]"
94
+ Morpheus::Cli::CliCommand.genericOptions(opts,options)
95
+ end
96
+ if args.count < 1
97
+ puts "\n#{optparse.banner}\n\n"
98
+ exit 1
99
+ end
100
+ optparse.parse(args)
101
+
102
+ connect(options)
103
+
104
+ begin
105
+ license_results = @license_interface.apply(key)
106
+
107
+ if options[:json]
108
+ puts JSON.pretty_generate(license_results)
109
+ else
110
+ puts "License applied successfully!"
111
+ end
112
+ rescue RestClient::Exception => e
113
+ ::Morpheus::Cli::ErrorHandler.new.print_rest_exception(e)
114
+ exit 1
115
+ end
116
+ end
117
+
118
+ end