morpheus-cli 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/bin/morpheus +24 -16
- data/lib/morpheus/api/api_client.rb +8 -0
- data/lib/morpheus/api/apps_interface.rb +50 -17
- data/lib/morpheus/api/deploy_interface.rb +7 -7
- data/lib/morpheus/api/groups_interface.rb +5 -5
- data/lib/morpheus/api/instance_types_interface.rb +4 -4
- data/lib/morpheus/api/instances_interface.rb +46 -12
- data/lib/morpheus/api/security_group_rules_interface.rb +45 -0
- data/lib/morpheus/api/security_groups_interface.rb +59 -0
- data/lib/morpheus/api/servers_interface.rb +4 -4
- data/lib/morpheus/api/zones_interface.rb +38 -5
- data/lib/morpheus/cli.rb +5 -0
- data/lib/morpheus/cli/apps.rb +153 -7
- data/lib/morpheus/cli/cli_command.rb +20 -0
- data/lib/morpheus/cli/cli_registry.rb +75 -0
- data/lib/morpheus/cli/credentials.rb +4 -3
- data/lib/morpheus/cli/deploys.rb +7 -2
- data/lib/morpheus/cli/groups.rb +4 -2
- data/lib/morpheus/cli/instance_types.rb +3 -1
- data/lib/morpheus/cli/instances.rb +151 -2
- data/lib/morpheus/cli/remote.rb +2 -1
- data/lib/morpheus/cli/security_group_rules.rb +243 -0
- data/lib/morpheus/cli/security_groups.rb +192 -0
- data/lib/morpheus/cli/servers.rb +4 -1
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/zones.rb +152 -4
- data/lib/morpheus/rest_client.rb +50 -0
- data/morpheus-cli.gemspec +2 -2
- metadata +13 -4
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'morpheus/rest_client'
|
3
|
+
|
4
|
+
class Morpheus::SecurityGroupRulesInterface < Morpheus::APIClient
|
5
|
+
def initialize(access_token, refresh_token,expires_at = nil, base_url=nil)
|
6
|
+
@access_token = access_token
|
7
|
+
@refresh_token = refresh_token
|
8
|
+
@base_url = base_url
|
9
|
+
@expires_at = expires_at
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def get(security_group_id, options=nil)
|
14
|
+
url = "#{@base_url}/api/security-groups/#{security_group_id}/rules"
|
15
|
+
headers = { params: {}, authorization: "Bearer #{@access_token}" }
|
16
|
+
|
17
|
+
if options.is_a?(Hash)
|
18
|
+
headers[:params].merge!(options)
|
19
|
+
elsif options.is_a?(Numeric)
|
20
|
+
url = "#{@base_url}/api/security-groups/#{security_group_id}/rules/#{options}"
|
21
|
+
end
|
22
|
+
response = Morpheus::RestClient.execute(method: :get, url: url,
|
23
|
+
timeout: 10, headers: headers)
|
24
|
+
JSON.parse(response.to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
def create(security_group_id, options)
|
28
|
+
url = "#{@base_url}/api/security-groups/#{security_group_id}/rules"
|
29
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
30
|
+
|
31
|
+
payload = options
|
32
|
+
response = Morpheus::RestClient.execute(method: :post, url: url,
|
33
|
+
timeout: 10, headers: headers, payload: payload.to_json)
|
34
|
+
JSON.parse(response.to_s)
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete(security_group_id, id)
|
38
|
+
url = "#{@base_url}/api/security-groups/#{security_group_id}/rules/#{id}"
|
39
|
+
print "url #{url}"
|
40
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
41
|
+
response = Morpheus::RestClient.execute(method: :delete, url: url,
|
42
|
+
timeout: 10, headers: headers)
|
43
|
+
JSON.parse(response.to_s)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rest-client'
|
3
|
+
|
4
|
+
class Morpheus::SecurityGroupsInterface < Morpheus::APIClient
|
5
|
+
def initialize(access_token, refresh_token,expires_at = nil, base_url=nil)
|
6
|
+
@access_token = access_token
|
7
|
+
@refresh_token = refresh_token
|
8
|
+
@base_url = base_url
|
9
|
+
@expires_at = expires_at
|
10
|
+
end
|
11
|
+
|
12
|
+
def list(options=nil)
|
13
|
+
url = "#{@base_url}/api/security-groups"
|
14
|
+
headers = { params: {}, authorization: "Bearer #{@access_token}" }
|
15
|
+
if options.is_a?(Hash)
|
16
|
+
headers[:params].merge!(options)
|
17
|
+
end
|
18
|
+
response = Morpheus::RestClient.execute(method: :get, url: url,
|
19
|
+
timeout: 10, headers: headers)
|
20
|
+
JSON.parse(response.to_s)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get(options)
|
24
|
+
url = "#{@base_url}/api/security-groups/#{options[:id]}"
|
25
|
+
headers = { params: {}, authorization: "Bearer #{@access_token}" }
|
26
|
+
if options.is_a?(Hash)
|
27
|
+
headers[:params].merge!(options)
|
28
|
+
end
|
29
|
+
response = Morpheus::RestClient.execute(method: :get, url: url,
|
30
|
+
timeout: 10, headers: headers)
|
31
|
+
JSON.parse(response.to_s)
|
32
|
+
end
|
33
|
+
|
34
|
+
def create(options)
|
35
|
+
url = "#{@base_url}/api/security-groups"
|
36
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
37
|
+
|
38
|
+
payload = options
|
39
|
+
response = Morpheus::RestClient.execute(method: :post, url: url,
|
40
|
+
timeout: 10, headers: headers, payload: payload.to_json)
|
41
|
+
JSON.parse(response.to_s)
|
42
|
+
end
|
43
|
+
|
44
|
+
def update(id)
|
45
|
+
url = "#{@base_url}/api/security-groups/#{id}"
|
46
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
47
|
+
response = Morpheus::RestClient.execute(method: :put, url: url,
|
48
|
+
timeout: 10, headers: headers)
|
49
|
+
JSON.parse(response.to_s)
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete(id)
|
53
|
+
url = "#{@base_url}/api/security-groups/#{id}"
|
54
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
55
|
+
response = Morpheus::RestClient.execute(method: :delete, url: url,
|
56
|
+
timeout: 10, headers: headers)
|
57
|
+
JSON.parse(response.to_s)
|
58
|
+
end
|
59
|
+
end
|
@@ -20,7 +20,7 @@ class Morpheus::ServersInterface < Morpheus::APIClient
|
|
20
20
|
elsif options.is_a?(String)
|
21
21
|
headers[:params]['name'] = options
|
22
22
|
end
|
23
|
-
response = RestClient
|
23
|
+
response = Morpheus::RestClient.execute(method: :get, url: url,
|
24
24
|
timeout: 10, headers: headers)
|
25
25
|
JSON.parse(response.to_s)
|
26
26
|
end
|
@@ -31,7 +31,7 @@ class Morpheus::ServersInterface < Morpheus::APIClient
|
|
31
31
|
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
32
32
|
|
33
33
|
payload = options
|
34
|
-
response = RestClient
|
34
|
+
response = Morpheus::RestClient.execute(method: :post, url: url,
|
35
35
|
timeout: 10, headers: headers, payload: payload.to_json)
|
36
36
|
JSON.parse(response.to_s)
|
37
37
|
end
|
@@ -39,8 +39,8 @@ class Morpheus::ServersInterface < Morpheus::APIClient
|
|
39
39
|
def destroy(id)
|
40
40
|
url = "#{@base_url}/api/servers/#{id}"
|
41
41
|
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
42
|
-
response = RestClient
|
42
|
+
response = Morpheus::RestClient.execute(method: :delete, url: url,
|
43
43
|
timeout: 10, headers: headers)
|
44
44
|
JSON.parse(response.to_s)
|
45
45
|
end
|
46
|
-
end
|
46
|
+
end
|
@@ -13,7 +13,7 @@ class Morpheus::ZonesInterface < Morpheus::APIClient
|
|
13
13
|
url = "#{@base_url}/api/zone-types"
|
14
14
|
headers = { params: {}, authorization: "Bearer #{@access_token}" }
|
15
15
|
|
16
|
-
response = RestClient
|
16
|
+
response = Morpheus::RestClient.execute(method: :get, url: url,
|
17
17
|
timeout: 10, headers: headers)
|
18
18
|
JSON.parse(response.to_s)
|
19
19
|
end
|
@@ -30,7 +30,7 @@ class Morpheus::ZonesInterface < Morpheus::APIClient
|
|
30
30
|
elsif options.is_a?(String)
|
31
31
|
headers[:params]['name'] = options
|
32
32
|
end
|
33
|
-
response = RestClient
|
33
|
+
response = Morpheus::RestClient.execute(method: :get, url: url,
|
34
34
|
timeout: 10, headers: headers)
|
35
35
|
JSON.parse(response.to_s)
|
36
36
|
end
|
@@ -41,7 +41,7 @@ class Morpheus::ZonesInterface < Morpheus::APIClient
|
|
41
41
|
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
42
42
|
|
43
43
|
payload = {zone: options}
|
44
|
-
response = RestClient
|
44
|
+
response = Morpheus::RestClient.execute(method: :post, url: url,
|
45
45
|
timeout: 10, headers: headers, payload: payload.to_json)
|
46
46
|
JSON.parse(response.to_s)
|
47
47
|
end
|
@@ -49,8 +49,41 @@ class Morpheus::ZonesInterface < Morpheus::APIClient
|
|
49
49
|
def destroy(id)
|
50
50
|
url = "#{@base_url}/api/zones/#{id}"
|
51
51
|
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
52
|
-
response = RestClient
|
52
|
+
response = Morpheus::RestClient.execute(method: :delete, url: url,
|
53
53
|
timeout: 10, headers: headers)
|
54
54
|
JSON.parse(response.to_s)
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
|
+
def firewall_disable(id)
|
58
|
+
url = "#{@base_url}/api/zones/#{id}/security-groups/disable"
|
59
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
60
|
+
response = Morpheus::RestClient.execute(method: :put, url: url,
|
61
|
+
timeout: 10, headers: headers)
|
62
|
+
JSON.parse(response.to_s)
|
63
|
+
end
|
64
|
+
|
65
|
+
def firewall_enable(id)
|
66
|
+
url = "#{@base_url}/api/zones/#{id}/security-groups/enable"
|
67
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
68
|
+
response = Morpheus::RestClient.execute(method: :put, url: url,
|
69
|
+
timeout: 10, headers: headers)
|
70
|
+
JSON.parse(response.to_s)
|
71
|
+
end
|
72
|
+
|
73
|
+
def security_groups(id)
|
74
|
+
url = "#{@base_url}/api/zones/#{id}/security-groups"
|
75
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
76
|
+
response = Morpheus::RestClient.execute(method: :get, url: url,
|
77
|
+
timeout: 10, headers: headers)
|
78
|
+
JSON.parse(response.to_s)
|
79
|
+
end
|
80
|
+
|
81
|
+
def apply_security_groups(id, options)
|
82
|
+
url = "#{@base_url}/api/zones/#{id}/security-groups"
|
83
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
84
|
+
payload = options
|
85
|
+
response = Morpheus::RestClient.execute(method: :post, url: url,
|
86
|
+
timeout: 10, headers: headers, payload: payload.to_json)
|
87
|
+
JSON.parse(response.to_s)
|
88
|
+
end
|
89
|
+
end
|
data/lib/morpheus/cli.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "morpheus/cli/version"
|
2
|
+
require "morpheus/rest_client"
|
2
3
|
|
3
4
|
module Morpheus
|
4
5
|
module Cli
|
@@ -10,6 +11,8 @@ module Morpheus
|
|
10
11
|
require 'morpheus/api/instance_types_interface'
|
11
12
|
require 'morpheus/api/apps_interface'
|
12
13
|
require 'morpheus/api/deploy_interface'
|
14
|
+
require 'morpheus/api/security_groups_interface'
|
15
|
+
require 'morpheus/api/security_group_rules_interface'
|
13
16
|
require 'morpheus/cli/credentials'
|
14
17
|
require 'morpheus/cli/error_handler'
|
15
18
|
require 'morpheus/cli/remote'
|
@@ -20,6 +23,8 @@ module Morpheus
|
|
20
23
|
require 'morpheus/cli/apps'
|
21
24
|
require 'morpheus/cli/deploys'
|
22
25
|
require 'morpheus/cli/instance_types'
|
26
|
+
require 'morpheus/cli/security_groups'
|
27
|
+
require 'morpheus/cli/security_group_rules'
|
23
28
|
# Your code goes here...
|
24
29
|
end
|
25
30
|
end
|
data/lib/morpheus/cli/apps.rb
CHANGED
@@ -5,8 +5,10 @@ require 'term/ansicolor'
|
|
5
5
|
require 'optparse'
|
6
6
|
require 'filesize'
|
7
7
|
require 'table_print'
|
8
|
+
require 'morpheus/cli/cli_command'
|
8
9
|
|
9
10
|
class Morpheus::Cli::Apps
|
11
|
+
include Morpheus::Cli::CliCommand
|
10
12
|
include Term::ANSIColor
|
11
13
|
def initialize()
|
12
14
|
@appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
@@ -24,9 +26,6 @@ class Morpheus::Cli::Apps
|
|
24
26
|
print red,bold, "\nInvalid Credentials. Unable to acquire access token. Please verify your credentials and try again.\n\n",reset
|
25
27
|
return 1
|
26
28
|
end
|
27
|
-
if args.empty?
|
28
|
-
puts "\nUsage: morpheus apps [list,add,remove,stop,start,restart,resize,upgrade,clone,envs,setenv,delenv] [name]\n\n"
|
29
|
-
end
|
30
29
|
|
31
30
|
case args[0]
|
32
31
|
when 'list'
|
@@ -50,9 +49,17 @@ class Morpheus::Cli::Apps
|
|
50
49
|
when 'setenv'
|
51
50
|
setenv(args[1..-1])
|
52
51
|
when 'delenv'
|
53
|
-
delenv(args[1..-1])
|
52
|
+
delenv(args[1..-1])
|
53
|
+
when 'firewall_disable'
|
54
|
+
firewall_disable(args[1..-1])
|
55
|
+
when 'firewall_enable'
|
56
|
+
firewall_enable(args[1..-1])
|
57
|
+
when 'security_groups'
|
58
|
+
security_groups(args[1..-1])
|
59
|
+
when 'apply_security_groups'
|
60
|
+
apply_security_groups(args[1..-1])
|
54
61
|
else
|
55
|
-
puts "\nUsage: morpheus apps [list,add,remove,stop,start,restart,resize,upgrade,clone,envs,setenv,delenv] [name]\n\n"
|
62
|
+
puts "\nUsage: morpheus apps [list,add,remove,stop,start,restart,resize,upgrade,clone,envs,setenv,delenv,firewall_disable,firewall_enable,security_groups,apply_security_groups] [name]\n\n"
|
56
63
|
end
|
57
64
|
end
|
58
65
|
|
@@ -398,7 +405,7 @@ class Morpheus::Cli::Apps
|
|
398
405
|
puts yellow,"No apps currently configured.",reset
|
399
406
|
else
|
400
407
|
apps.each do |app|
|
401
|
-
print cyan, "= #{app['name']}
|
408
|
+
print cyan, "= #{app['name']}\n"
|
402
409
|
end
|
403
410
|
end
|
404
411
|
print reset,"\n\n"
|
@@ -433,6 +440,145 @@ class Morpheus::Cli::Apps
|
|
433
440
|
end
|
434
441
|
end
|
435
442
|
|
443
|
+
def firewall_disable(args)
|
444
|
+
if args.count < 1
|
445
|
+
puts "\nUsage: morpheus apps firewall_disable [name]\n\n"
|
446
|
+
return
|
447
|
+
end
|
448
|
+
begin
|
449
|
+
app_results = @apps_interface.get({name: args[0]})
|
450
|
+
if app_results['apps'].empty?
|
451
|
+
puts "App not found by name #{args[0]}"
|
452
|
+
return
|
453
|
+
end
|
454
|
+
@apps_interface.firewall_disable(app_results['apps'][0]['id'])
|
455
|
+
security_groups([args[0]])
|
456
|
+
rescue RestClient::Exception => e
|
457
|
+
if e.response.code == 400
|
458
|
+
error = JSON.parse(e.response.to_s)
|
459
|
+
::Morpheus::Cli::ErrorHandler.new.print_errors(error)
|
460
|
+
else
|
461
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
462
|
+
end
|
463
|
+
return nil
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
def firewall_enable(args)
|
468
|
+
if args.count < 1
|
469
|
+
puts "\nUsage: morpheus apps firewall_enable [name]\n\n"
|
470
|
+
return
|
471
|
+
end
|
472
|
+
begin
|
473
|
+
app_results = @apps_interface.get({name: args[0]})
|
474
|
+
if app_results['apps'].empty?
|
475
|
+
puts "App not found by name #{args[0]}"
|
476
|
+
return
|
477
|
+
end
|
478
|
+
@apps_interface.firewall_enable(app_results['apps'][0]['id'])
|
479
|
+
security_groups([args[0]])
|
480
|
+
rescue RestClient::Exception => e
|
481
|
+
if e.response.code == 400
|
482
|
+
error = JSON.parse(e.response.to_s)
|
483
|
+
::Morpheus::Cli::ErrorHandler.new.print_errors(error)
|
484
|
+
else
|
485
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
486
|
+
end
|
487
|
+
return nil
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
def security_groups(args)
|
492
|
+
if args.count < 1
|
493
|
+
puts "\nUsage: morpheus apps security_groups [name]\n\n"
|
494
|
+
return
|
495
|
+
end
|
496
|
+
begin
|
497
|
+
app_results = @apps_interface.get({name: args[0]})
|
498
|
+
if app_results['apps'].empty?
|
499
|
+
puts "Instance not found by name #{args[0]}"
|
500
|
+
return
|
501
|
+
end
|
502
|
+
|
503
|
+
app_id = app_results['apps'][0]['id']
|
504
|
+
json_response = @apps_interface.security_groups(app_id)
|
505
|
+
|
506
|
+
securityGroups = json_response['securityGroups']
|
507
|
+
print "\n" ,cyan, bold, "Morpheus Security Groups for App:#{app_id}\n","==================", reset, "\n\n"
|
508
|
+
print cyan, "Firewall Enabled=#{json_response['firewallEnabled']}\n\n"
|
509
|
+
if securityGroups.empty?
|
510
|
+
puts yellow,"No security groups currently applied.",reset
|
511
|
+
else
|
512
|
+
securityGroups.each do |securityGroup|
|
513
|
+
print cyan, "= #{securityGroup['id']} (#{securityGroup['name']}) - (#{securityGroup['description']})\n"
|
514
|
+
end
|
515
|
+
end
|
516
|
+
print reset,"\n\n"
|
517
|
+
|
518
|
+
rescue RestClient::Exception => e
|
519
|
+
if e.response.code == 400
|
520
|
+
error = JSON.parse(e.response.to_s)
|
521
|
+
::Morpheus::Cli::ErrorHandler.new.print_errors(error)
|
522
|
+
else
|
523
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
524
|
+
end
|
525
|
+
return nil
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
def apply_security_groups(args)
|
530
|
+
usage = <<-EOF
|
531
|
+
Usage: morpheus apps apply_security_groups [name] [options]
|
532
|
+
EOF
|
533
|
+
if args.count < 1
|
534
|
+
puts usage
|
535
|
+
return
|
536
|
+
end
|
537
|
+
|
538
|
+
options = {}
|
539
|
+
clear_or_secgroups_specified = false
|
540
|
+
optparse = OptionParser.new do|opts|
|
541
|
+
opts.banner = usage
|
542
|
+
opts.on( '-c', '--clear', "Clear all security groups" ) do
|
543
|
+
options[:securityGroupIds] = []
|
544
|
+
clear_or_secgroups_specified = true
|
545
|
+
end
|
546
|
+
opts.on( '-s', '--secgroups SECGROUPS', "Apply the specified comma separated security group ids" ) do |secgroups|
|
547
|
+
options[:securityGroupIds] = secgroups.split(",")
|
548
|
+
clear_or_secgroups_specified = true
|
549
|
+
end
|
550
|
+
opts.on( '-h', '--help', "Prints this help" ) do
|
551
|
+
puts opts
|
552
|
+
exit
|
553
|
+
end
|
554
|
+
end
|
555
|
+
optparse.parse(args)
|
556
|
+
|
557
|
+
if !clear_or_secgroups_specified
|
558
|
+
puts usage
|
559
|
+
exit
|
560
|
+
end
|
561
|
+
|
562
|
+
begin
|
563
|
+
app_results = @apps_interface.get({name: args[0]})
|
564
|
+
if app_results['apps'].empty?
|
565
|
+
puts "App not found by name #{args[0]}"
|
566
|
+
return
|
567
|
+
end
|
568
|
+
|
569
|
+
@apps_interface.apply_security_groups(app_results['apps'][0]['id'], options)
|
570
|
+
security_groups([args[0]])
|
571
|
+
rescue RestClient::Exception => e
|
572
|
+
if e.response.code == 400
|
573
|
+
error = JSON.parse(e.response.to_s)
|
574
|
+
::Morpheus::Cli::ErrorHandler.new.print_errors(error)
|
575
|
+
else
|
576
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
577
|
+
end
|
578
|
+
return nil
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
436
582
|
private
|
437
583
|
def find_group_by_name(name)
|
438
584
|
group_results = @groups_interface.get(name)
|
@@ -451,4 +597,4 @@ private
|
|
451
597
|
end
|
452
598
|
return instance_type_results['appTypes'][0]
|
453
599
|
end
|
454
|
-
end
|
600
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'morpheus/cli/cli_registry'
|
2
|
+
|
3
|
+
module Morpheus
|
4
|
+
module Cli
|
5
|
+
# Module to be included by every CLI command so that commands get registered
|
6
|
+
module CliCommand
|
7
|
+
|
8
|
+
def self.included(klass)
|
9
|
+
Morpheus::Cli::CliRegistry.add(klass)
|
10
|
+
klass.extend ClassMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def cli_command_name(cmd_name)
|
15
|
+
Morpheus::Cli::CliRegistry.add(self, cmd_name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|