morpheus-cli 2.10.0 → 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/bin/morpheus +27 -32
  3. data/lib/morpheus/api/accounts_interface.rb +36 -47
  4. data/lib/morpheus/api/api_client.rb +141 -110
  5. data/lib/morpheus/api/app_templates_interface.rb +56 -72
  6. data/lib/morpheus/api/apps_interface.rb +111 -132
  7. data/lib/morpheus/api/auth_interface.rb +30 -0
  8. data/lib/morpheus/api/clouds_interface.rb +71 -76
  9. data/lib/morpheus/api/custom_instance_types_interface.rb +21 -46
  10. data/lib/morpheus/api/dashboard_interface.rb +10 -17
  11. data/lib/morpheus/api/deploy_interface.rb +60 -72
  12. data/lib/morpheus/api/deployments_interface.rb +53 -71
  13. data/lib/morpheus/api/groups_interface.rb +55 -45
  14. data/lib/morpheus/api/instance_types_interface.rb +19 -23
  15. data/lib/morpheus/api/instances_interface.rb +179 -177
  16. data/lib/morpheus/api/key_pairs_interface.rb +11 -17
  17. data/lib/morpheus/api/license_interface.rb +18 -23
  18. data/lib/morpheus/api/load_balancers_interface.rb +54 -69
  19. data/lib/morpheus/api/logs_interface.rb +25 -29
  20. data/lib/morpheus/api/options_interface.rb +13 -17
  21. data/lib/morpheus/api/provision_types_interface.rb +19 -22
  22. data/lib/morpheus/api/roles_interface.rb +75 -94
  23. data/lib/morpheus/api/security_group_rules_interface.rb +28 -37
  24. data/lib/morpheus/api/security_groups_interface.rb +39 -51
  25. data/lib/morpheus/api/servers_interface.rb +113 -115
  26. data/lib/morpheus/api/setup_interface.rb +31 -0
  27. data/lib/morpheus/api/task_sets_interface.rb +36 -38
  28. data/lib/morpheus/api/tasks_interface.rb +56 -69
  29. data/lib/morpheus/api/users_interface.rb +67 -76
  30. data/lib/morpheus/api/virtual_images_interface.rb +61 -61
  31. data/lib/morpheus/api/whoami_interface.rb +12 -15
  32. data/lib/morpheus/cli.rb +71 -60
  33. data/lib/morpheus/cli/accounts.rb +254 -315
  34. data/lib/morpheus/cli/alias_command.rb +219 -0
  35. data/lib/morpheus/cli/app_templates.rb +264 -272
  36. data/lib/morpheus/cli/apps.rb +608 -671
  37. data/lib/morpheus/cli/cli_command.rb +259 -21
  38. data/lib/morpheus/cli/cli_registry.rb +99 -14
  39. data/lib/morpheus/cli/clouds.rb +599 -372
  40. data/lib/morpheus/cli/config_file.rb +126 -0
  41. data/lib/morpheus/cli/credentials.rb +141 -117
  42. data/lib/morpheus/cli/dashboard_command.rb +48 -56
  43. data/lib/morpheus/cli/deployments.rb +254 -268
  44. data/lib/morpheus/cli/deploys.rb +150 -142
  45. data/lib/morpheus/cli/error_handler.rb +38 -0
  46. data/lib/morpheus/cli/groups.rb +551 -179
  47. data/lib/morpheus/cli/hosts.rb +862 -617
  48. data/lib/morpheus/cli/instance_types.rb +103 -95
  49. data/lib/morpheus/cli/instances.rb +1335 -1009
  50. data/lib/morpheus/cli/key_pairs.rb +82 -90
  51. data/lib/morpheus/cli/library.rb +498 -499
  52. data/lib/morpheus/cli/license.rb +83 -101
  53. data/lib/morpheus/cli/load_balancers.rb +314 -300
  54. data/lib/morpheus/cli/login.rb +66 -44
  55. data/lib/morpheus/cli/logout.rb +47 -46
  56. data/lib/morpheus/cli/mixins/accounts_helper.rb +69 -31
  57. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +106 -0
  58. data/lib/morpheus/cli/mixins/print_helper.rb +181 -17
  59. data/lib/morpheus/cli/mixins/provisioning_helper.rb +535 -458
  60. data/lib/morpheus/cli/mixins/whoami_helper.rb +2 -2
  61. data/lib/morpheus/cli/option_parser.rb +35 -0
  62. data/lib/morpheus/cli/option_types.rb +232 -192
  63. data/lib/morpheus/cli/recent_activity_command.rb +61 -65
  64. data/lib/morpheus/cli/remote.rb +446 -199
  65. data/lib/morpheus/cli/roles.rb +884 -906
  66. data/lib/morpheus/cli/security_group_rules.rb +213 -203
  67. data/lib/morpheus/cli/security_groups.rb +237 -192
  68. data/lib/morpheus/cli/shell.rb +338 -231
  69. data/lib/morpheus/cli/tasks.rb +326 -308
  70. data/lib/morpheus/cli/users.rb +457 -462
  71. data/lib/morpheus/cli/version.rb +1 -1
  72. data/lib/morpheus/cli/version_command.rb +16 -18
  73. data/lib/morpheus/cli/virtual_images.rb +526 -345
  74. data/lib/morpheus/cli/whoami.rb +125 -111
  75. data/lib/morpheus/cli/workflows.rb +338 -185
  76. data/lib/morpheus/formatters.rb +8 -1
  77. data/lib/morpheus/logging.rb +1 -1
  78. data/lib/morpheus/rest_client.rb +17 -8
  79. metadata +9 -3
  80. data/lib/morpheus/api/custom_instance_types.rb +0 -55
@@ -1,5 +1,9 @@
1
+ require 'morpheus/cli/option_parser'
1
2
  require 'morpheus/cli/cli_registry'
2
3
  require 'morpheus/cli/mixins/print_helper'
4
+ require 'morpheus/cli/credentials'
5
+ require 'morpheus/api/api_client'
6
+ require 'morpheus/cli/remote'
3
7
 
4
8
  module Morpheus
5
9
  module Cli
@@ -7,9 +11,9 @@ module Morpheus
7
11
  module CliCommand
8
12
 
9
13
  def self.included(klass)
10
- Morpheus::Cli::CliRegistry.add(klass)
11
14
  klass.send :include, Morpheus::Cli::PrintHelper
12
15
  klass.extend ClassMethods
16
+ Morpheus::Cli::CliRegistry.add(klass, klass.command_name)
13
17
  end
14
18
 
15
19
  def build_common_options(opts, options, includes=[])
@@ -26,9 +30,10 @@ module Morpheus
26
30
  end
27
31
 
28
32
  when :options
29
- opts.on( '-O', '--option OPTION', "Option" ) do |option|
33
+ options[:options] ||= {}
34
+ opts.on( '-O', '--option OPTION', "Option in the format var=\"value\"" ) do |option|
30
35
  custom_option_args = option.split('=')
31
- custom_options = options[:options] || {}
36
+ custom_options = options[:options]
32
37
  option_name_args = custom_option_args[0].split('.')
33
38
  if option_name_args.count > 1
34
39
  nested_options = custom_options
@@ -43,7 +48,6 @@ module Morpheus
43
48
  else
44
49
  custom_options[custom_option_args[0]] = custom_option_args[1]
45
50
  end
46
-
47
51
  options[:options] = custom_options
48
52
  end
49
53
  opts.on('-N','--no-prompt', "Skip prompts. Use default values for all optional fields.") do |val|
@@ -52,8 +56,8 @@ module Morpheus
52
56
  options[:options] ||= {}
53
57
  options[:options][:no_prompt] = true
54
58
  end
59
+
55
60
  when :list
56
-
57
61
  opts.on( '-m', '--max MAX', "Max Results" ) do |max|
58
62
  options[:max] = max.to_i
59
63
  end
@@ -75,10 +79,26 @@ module Morpheus
75
79
  end
76
80
 
77
81
  when :remote
78
- opts.on( '-r', '--remote REMOTE', "Remote Appliance" ) do |remote|
79
- options[:remote] = remote
82
+
83
+ # this is the only option now...
84
+ # first, you must do `remote use [appliance]`
85
+ opts.on( '-r', '--remote REMOTE', "Remote Appliance Name to use for this command. The active appliance is used by default." ) do |val|
86
+ options[:remote] = val
87
+ end
88
+
89
+ # todo: also require this for talking to plain old HTTP
90
+ opts.on('-I','--insecure', "Allow for insecure HTTPS communication i.e. bad SSL certificate") do |val|
91
+ Morpheus::RestClient.enable_ssl_verification = false
80
92
  end
81
93
 
94
+ # skipping the rest of this for now..
95
+
96
+ next
97
+
98
+ # opts.on( '-r', '--remote REMOTE', "Remote Appliance" ) do |remote|
99
+ # options[:remote] = remote
100
+ # end
101
+
82
102
  opts.on( '-U', '--url REMOTE', "API Url" ) do |remote|
83
103
  options[:remote_url] = remote
84
104
  end
@@ -94,36 +114,39 @@ module Morpheus
94
114
  opts.on( '-T', '--token ACCESS_TOKEN', "Access Token" ) do |remote|
95
115
  options[:remote_token] = remote
96
116
  end
97
-
98
- when :auto_confirm
117
+ when :auto_confirm
99
118
  opts.on( '-y', '--yes', "Auto Confirm" ) do
100
119
  options[:yes] = true
101
120
  end
102
-
103
- when :json
121
+ when :json
104
122
  opts.on('-j','--json', "JSON Output") do |json|
105
123
  options[:json] = true
106
124
  end
107
125
 
108
126
  when :dry_run
109
- opts.on('-d','--dry-run', "Dry Run, print json without making the actual request.") do |json|
127
+ opts.on('-d','--dry-run', "Dry Run, print the API request instead of executing it") do |json|
110
128
  options[:dry_run] = true
111
129
  end
112
-
130
+ when :quiet
131
+ opts.on('-q','--quiet', "No Output, when successful") do |json|
132
+ options[:quiet] = true
133
+ end
134
+
113
135
  else
114
136
  raise "Unknown common_option key: #{option_key}"
115
137
  end
116
138
  end
117
139
 
118
140
  # options that are always included
119
- opts.on('-C','--nocolor', "ANSI") do
141
+
142
+ # disable ANSI coloring
143
+ opts.on('-C','--nocolor', "Disable ANSI coloring") do
120
144
  Term::ANSIColor::coloring = false
121
145
  end
122
146
 
123
147
  opts.on('-V','--debug', "Print extra output for debugging. ") do |json|
124
148
  options[:debug] = true
125
- # this is handled upstream for now...
126
- # Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::DEBUG)
149
+ Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::DEBUG)
127
150
  # perhaps...
128
151
  # create a new logger instance just for this command instance
129
152
  # this way we don't elevate the global level for subsequent commands in a shell
@@ -132,21 +155,166 @@ module Morpheus
132
155
  # @logger.log_level = Morpheus::Logging::Logger::DEBUG
133
156
  # end
134
157
  end
135
-
158
+
136
159
  opts.on('-h', '--help', "Prints this help" ) do
137
160
  puts opts
138
161
  exit
139
162
  end
140
163
 
141
164
  end
142
-
165
+
166
+ def command_name
167
+ self.class.command_name
168
+ end
169
+
170
+ def subcommands
171
+ self.class.subcommands
172
+ end
173
+
174
+ def subcommand_aliases
175
+ self.class.subcommand_aliases
176
+ end
177
+
178
+ def default_subcommand
179
+ self.class.default_subcommand
180
+ end
181
+
182
+ def usage
183
+ if !subcommands.empty?
184
+ "Usage: morpheus #{command_name} [command] [options]"
185
+ else
186
+ "Usage: morpheus #{command_name} [options]"
187
+ end
188
+ end
189
+
190
+ def subcommand_usage(*extra)
191
+ calling_method = caller[0][/`([^']*)'/, 1].to_s.sub('block in ', '')
192
+ subcommand_name = subcommands.key(calling_method)
193
+ extra = extra.flatten
194
+ if !subcommand_name.empty? && extra.first == subcommand_name
195
+ extra.shift
196
+ end
197
+ #extra = ["[options]"] if extra.empty?
198
+ "Usage: morpheus #{command_name} #{subcommand_name} #{extra.join(' ')}".squeeze(' ').strip
199
+ end
200
+
201
+ def print_usage()
202
+ puts usage
203
+ if !subcommands.empty?
204
+ puts "Commands:"
205
+ subcommands.sort.each {|cmd, method|
206
+ puts "\t#{cmd.to_s}"
207
+ }
208
+ end
209
+ end
210
+
211
+ # a default handler
212
+ def handle_subcommand(args)
213
+ commands = subcommands
214
+ if subcommands.empty?
215
+ raise "#{self.class} has no available subcommands"
216
+ end
217
+ # meh, could deprecate and make subcommand define handle() itself
218
+ if args.count == 0 && default_subcommand
219
+ # p "using default subcommand #{default_subcommand}"
220
+ return self.send(default_subcommand, args || [])
221
+ end
222
+ cmd_name = args[0]
223
+ if subcommand_aliases[cmd_name]
224
+ cmd_name = subcommand_aliases[cmd_name]
225
+ end
226
+ cmd_method = subcommands[cmd_name]
227
+ if cmd_name && !cmd_method
228
+ #puts "unknown command '#{cmd_name}'"
229
+ end
230
+ if !cmd_method
231
+ print_usage
232
+ exit 127
233
+ end
234
+ self.send(cmd_method, args[1..-1])
235
+ end
236
+
237
+ def handle(args)
238
+ raise "#{self} has not defined handle()!"
239
+ end
240
+
241
+ # This supports the simple remote option eg. `instances add --remote "qa"`
242
+ # It will establish a connection to the pre-configured appliance named "qa"
243
+ # The calling command needs to populate @appliances and/or @appliance_name
244
+ # This returns a new instance of Morpheus::APIClient (and sets @access_token, and @appliance)
245
+ # Your command should be ready to make api requests after this.
246
+ # todo: probably don't exit here, just return nil or raise
247
+ def establish_remote_appliance_connection(options)
248
+ @appliances ||= ::Morpheus::Cli::Remote.appliances
249
+ if !@appliance_name
250
+ @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
251
+ end
252
+
253
+ # todo: support old way of accepting --username and --password on the command line
254
+ # it's probably better not to do that tho, just so it stays out of history files
255
+
256
+ # use a specific remote appliance by name
257
+ if options[:remote]
258
+ @appliance_name = options[:remote].to_sym rescue nil
259
+ if !@appliances
260
+ print_red_alert "You have no appliances configured. See the `remote add` command."
261
+ exit 1
262
+ end
263
+ found_appliance = @appliances[@appliance_name.to_sym]
264
+ if !found_appliance
265
+ print_red_alert "You have no appliance named '#{@appliance_name}' configured. See the `remote add` command."
266
+ exit 1
267
+ end
268
+ @appliance = found_appliance
269
+ @appliance_name = @appliance_name
270
+ @appliance_url = @appliance[:host]
271
+ if options[:debug]
272
+ print dark,"# => Using remote appliance [#{@appliance_name}] #{@appliance_url}",reset,"\n" if !options[:quiet]
273
+ end
274
+ else
275
+ #@appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
276
+ end
277
+
278
+ if !@appliance_name
279
+ print_red_alert "You must specify a remote appliance with --remote, or see the `remote use` command."
280
+ exit 1
281
+ end
282
+
283
+ puts "#{dark} #=> establishing connection to [#{@appliance_name}] #{@appliance_url}#{reset}\n" if options[:debug]
284
+
285
+ # ok, get some credentials.
286
+ # this prompts for username, password without options[:no_prompt]
287
+ @access_token = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).request_credentials(options)
288
+
289
+ # bail if we got nothing
290
+ if @access_token.empty?
291
+ print_red_alert "Invalid Credentials. Unable to acquire access token. Please verify your credentials and try again."
292
+ exit 1
293
+ end
294
+
295
+ # ok, connect to the appliance.. actually this just instantiates an ApiClient
296
+ # setup our api client for all including commands to use.
297
+ @api_client = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url)
298
+ return @api_client
299
+ end
143
300
 
144
301
  module ClassMethods
145
- def cli_command_name(cmd_name)
146
- Morpheus::Cli::CliRegistry.add(self, cmd_name)
302
+
303
+ def set_command_name(cmd_name)
304
+ @command_name = cmd_name
305
+ Morpheus::Cli::CliRegistry.add(self, self.command_name)
306
+ end
307
+
308
+ def default_command_name
309
+ Morpheus::Cli::CliRegistry.cli_ize(self.name.split('::')[-1])
310
+ end
311
+
312
+ def command_name
313
+ @command_name ||= default_command_name
314
+ @command_name
147
315
  end
148
316
 
149
- def cli_command_hidden(val=true)
317
+ def set_command_hidden(val=true)
150
318
  @hidden_command = val
151
319
  end
152
320
 
@@ -154,6 +322,76 @@ module Morpheus
154
322
  !!@hidden_command
155
323
  end
156
324
 
325
+ # construct map of command name => instance method
326
+ def register_subcommands(*cmds)
327
+ @subcommands ||= {}
328
+ cmds.flatten.each {|cmd|
329
+ if cmd.is_a?(Hash)
330
+ cmd.each {|k,v|
331
+ # @subcommands[k] = v
332
+ add_subcommand(k.to_s, v.to_s)
333
+ }
334
+ elsif cmd.is_a?(Array)
335
+ cmd.each {|it| register_subcommands(it) }
336
+ elsif cmd.is_a?(String) || cmd.is_a?(Symbol)
337
+ #k = Morpheus::Cli::CliRegistry.cli_ize(cmd)
338
+ k = cmd.to_s.gsub('_', '-')
339
+ v = cmd.to_s.gsub('-', '_')
340
+ register_subcommands({(k) => v})
341
+ else
342
+ raise "Unable to register command of type: #{cmd.class} #{cmd}"
343
+ end
344
+ }
345
+ return
346
+ end
347
+
348
+ def set_default_subcommand(cmd)
349
+ @default_subcommand = cmd
350
+ end
351
+
352
+ def default_subcommand
353
+ @default_subcommand
354
+ end
355
+
356
+ def subcommands
357
+ @subcommands ||= {}
358
+ end
359
+
360
+ def has_subcommand?(cmd_name)
361
+ return false if cmd_name.empty?
362
+ @subcommands && @subcommands[cmd_name.to_s]
363
+ end
364
+
365
+ def add_subcommand(cmd_name, method)
366
+ @subcommands ||= {}
367
+ @subcommands[cmd_name.to_s] = method
368
+ end
369
+
370
+ def remove_subcommand(cmd_name)
371
+ @subcommands ||= {}
372
+ @subcommands.delete(cmd_name.to_s)
373
+ end
374
+
375
+ # register an alias for a command
376
+ def alias_subcommand(alias_cmd_name, cmd_name)
377
+ add_subcommand_alias(alias_cmd_name.to_s, cmd_name.to_s.gsub('_', '-'))
378
+ return
379
+ end
380
+
381
+ def subcommand_aliases
382
+ @subcommand_aliases ||= {}
383
+ end
384
+
385
+ def add_subcommand_alias(alias_cmd_name, cmd_name)
386
+ @subcommand_aliases ||= {}
387
+ @subcommand_aliases[alias_cmd_name.to_s] = cmd_name
388
+ end
389
+
390
+ def remove_subcommand_alias(alias_cmd_name)
391
+ @subcommand_aliases ||= {}
392
+ @subcommand_aliases.delete(alias_cmd_name.to_s)
393
+ end
394
+
157
395
  end
158
396
  end
159
397
  end
@@ -1,36 +1,76 @@
1
-
1
+ require 'term/ansicolor'
2
2
  module Morpheus
3
3
  module Cli
4
4
  class CliRegistry
5
5
 
6
6
  def initialize
7
- @commands = {}
7
+ @commands = {} # this is command => Class that includes ::CliCommand
8
+ @aliases = {} # this is alias => String full input string
8
9
  end
9
-
10
+
10
11
  class << self
12
+ include Term::ANSIColor
11
13
 
14
+ ALIAS_SPLIT_REGEX=/(\;)(?=(?:[^"']|"[^'"]*")*$)/
15
+
12
16
  def instance
13
17
  @instance ||= CliRegistry.new
14
18
  end
15
19
 
20
+ #todo: move execution out of the CliRegistry
16
21
  def exec(command_name, args)
17
- # begin
18
- Term::ANSIColor::coloring = STDOUT.isatty
22
+ exec_command(command_name, args)
23
+ end
24
+
25
+ def exec_command(command_name, args)
26
+ #puts "exec_command(#{command_name}, #{args})"
27
+ found_alias_command = instance.get_alias(command_name)
28
+ if found_alias_command
29
+ exec_alias(command_name, args)
30
+ else
31
+ #puts "running regular command #{command_name} with arguments #{args.join(' ')}"
19
32
  instance.get(command_name).new.handle(args)
20
- # rescue SystemExit, Interrupt
21
- # puts "Interrupted..."
22
- # end
33
+ end
34
+ end
35
+
36
+ def exec_alias(alias_name, args)
37
+ #puts "exec_alias(#{alias_name}, #{args})"
38
+ found_alias_command = instance.get_alias(alias_name)
39
+ # support aliases of multiple commands, semicolon delimiter
40
+ # todo:
41
+ all_commands = found_alias_command.gsub(ALIAS_SPLIT_REGEX, '__ALIAS_SPLIT_REGEX__').split('__ALIAS_SPLIT_REGEX__').collect {|it| it.to_s.strip }.select {|it| !it.empty? }.compact
42
+ print "#{dark} #=> executing alias #{alias_name} as #{all_commands.join('; ')}#{reset}\n" if Morpheus::Logging.debug?
43
+ all_commands.each do |a_command_string|
44
+ alias_args = a_command_string.to_s.split(/\s+/) # or just ' '
45
+ command_name = alias_args.shift
46
+ command_args = alias_args + args
47
+ if command_name == alias_name
48
+ # needs to be better than this
49
+ print Term::ANSIColor.red,"alias '#{alias_name}' is calling itself? '#{found_alias_command}'", Term::ANSIColor.reset, "\n"
50
+ exit 1
51
+ end
52
+ # this allows aliases to use other aliases
53
+ # todo: prevent recursion infinite loop
54
+ if has_alias?(command_name)
55
+ exec_alias(command_name, command_args)
56
+ elsif has_command?(command_name)
57
+ #puts "executing alias #{found_alias_command} as #{command_name} with args #{args.join(' ')}"
58
+ instance.get(command_name).new.handle(alias_args + args)
59
+ else
60
+ # raise UnrecognizedCommandError.new(command_name)
61
+ print Term::ANSIColor.red,"alias '#{alias_name}' uses and unknown command: '#{command_name}'", Term::ANSIColor.reset, "\n"
62
+ exit 1
63
+ end
64
+ end
23
65
  end
24
66
 
25
67
  def add(klass, command_name=nil)
26
68
  klass_command_name = cli_ize(klass.name.split('::')[-1])
27
-
28
- if has_command?(klass_command_name) && !command_name.nil?
69
+ if has_command?(klass_command_name)
29
70
  instance.remove(klass_command_name)
30
- instance.add(command_name, klass)
31
- else
32
- instance.add(klass_command_name, klass)
33
71
  end
72
+ command_name ||= klass_command_name
73
+ instance.add(command_name, klass)
34
74
  end
35
75
 
36
76
  def has_command?(command_name)
@@ -41,11 +81,21 @@ module Morpheus
41
81
  end
42
82
  end
43
83
 
84
+ def has_alias?(alias_name)
85
+ if alias_name.nil? || alias_name == ''
86
+ false
87
+ else
88
+ !instance.get_alias(alias_name).nil?
89
+ end
90
+ end
91
+
44
92
  def all
45
93
  instance.all
46
94
  end
47
95
 
48
- private
96
+ def all_aliases
97
+ instance.all_aliases
98
+ end
49
99
 
50
100
  def cli_ize(klass_name)
51
101
  # borrowed from ActiveSupport
@@ -58,6 +108,18 @@ module Morpheus
58
108
  word.downcase!
59
109
  word.chop.tr('_', '-')
60
110
  end
111
+
112
+ def parse_alias_definition(input)
113
+ # todo: one multi group regex would work
114
+ alias_name, command_string = nil, nil
115
+ chunks = input.to_s.sub(/^alias\s+/, "").split('=')
116
+ alias_name = chunks.shift
117
+ command_string = chunks.compact.reject {|it| it.empty? }.join('=')
118
+ command_string = command_string.strip.sub(/^'/, "").sub(/'\Z/, "").strip
119
+ return alias_name, command_string
120
+ end
121
+
122
+
61
123
  end
62
124
 
63
125
  def all
@@ -75,6 +137,29 @@ module Morpheus
75
137
  def remove(cmd_name)
76
138
  @commands.delete(cmd_name.to_sym)
77
139
  end
140
+
141
+ def all_aliases
142
+ @aliases
143
+ end
144
+
145
+ def get_alias(alias_name)
146
+ @aliases[alias_name.to_sym]
147
+ end
148
+
149
+ def add_alias(alias_name, command_string)
150
+ #return @commands[alias_name.to_sym]
151
+ if self.class.has_command?(alias_name)
152
+ raise "alias name '#{alias_name}' is invalid. That is the name of a morpheus command."
153
+ elsif alias_name.to_s.downcase.strip == command_string.to_s.downcase.strip
154
+ raise "alias #{alias_name}=#{command_string} is invalid..."
155
+ end
156
+ @aliases[alias_name.to_sym] = command_string
157
+ end
158
+
159
+ def remove_alias(alias_name)
160
+ @aliases.delete(alias_name.to_sym)
161
+ end
162
+
78
163
  end
79
164
  end
80
165
  end