morpheus-cli 0.1.0 → 0.1.1
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.
- 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,192 @@
|
|
1
|
+
# require 'yaml'
|
2
|
+
require 'io/console'
|
3
|
+
require 'rest_client'
|
4
|
+
require 'term/ansicolor'
|
5
|
+
require 'optparse'
|
6
|
+
require 'filesize'
|
7
|
+
require 'table_print'
|
8
|
+
require 'morpheus/cli/cli_command'
|
9
|
+
|
10
|
+
class Morpheus::Cli::SecurityGroups
|
11
|
+
include Morpheus::Cli::CliCommand
|
12
|
+
include Term::ANSIColor
|
13
|
+
def initialize()
|
14
|
+
@appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
15
|
+
@access_token = Morpheus::Cli::Credentials.new(@appliance_name,@appliance_url).request_credentials()
|
16
|
+
@security_groups_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).security_groups
|
17
|
+
@active_security_group = ::Morpheus::Cli::SecurityGroups.load_security_group_file
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def handle(args)
|
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
|
+
return 1
|
25
|
+
end
|
26
|
+
if args.empty?
|
27
|
+
puts "\nUsage: morpheus security-groups [list,get,add,remove,use] [name]\n\n"
|
28
|
+
return
|
29
|
+
end
|
30
|
+
|
31
|
+
case args[0]
|
32
|
+
when 'list'
|
33
|
+
list(args[1..-1])
|
34
|
+
when 'get'
|
35
|
+
get(args[1..-1])
|
36
|
+
when 'add'
|
37
|
+
add(args[1..-1])
|
38
|
+
when 'remove'
|
39
|
+
remove(args[1..-1])
|
40
|
+
when 'use'
|
41
|
+
use(args[1..-1])
|
42
|
+
else
|
43
|
+
puts "\nUsage: morpheus security-groups [list,get,add,remove,use] [name]\n\n"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def list(args)
|
48
|
+
begin
|
49
|
+
json_response = @security_groups_interface.list()
|
50
|
+
security_groups = json_response['securityGroups']
|
51
|
+
print "\n" ,cyan, bold, "Morpheus Security Groups\n","==================", reset, "\n\n"
|
52
|
+
if security_groups.empty?
|
53
|
+
puts yellow,"No Security Groups currently configured.",reset
|
54
|
+
else
|
55
|
+
security_groups.each do |security_group|
|
56
|
+
print cyan, "= #{security_group['id']}: #{security_group['name']} (#{security_group['description']})\n"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
print reset,"\n\n"
|
60
|
+
|
61
|
+
rescue => e
|
62
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
63
|
+
return nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def get(args)
|
68
|
+
if args.count < 1
|
69
|
+
puts "\nUsage: morpheus security-groups get ID\n\n"
|
70
|
+
return
|
71
|
+
end
|
72
|
+
|
73
|
+
begin
|
74
|
+
json_response = @security_groups_interface.get({id: args[0]})
|
75
|
+
security_group = json_response['securityGroup']
|
76
|
+
print "\n" ,cyan, bold, "Morpheus Security Group\n","==================", reset, "\n\n"
|
77
|
+
if security_group.nil?
|
78
|
+
puts yellow,"Security Group not found by id #{args[0]}",reset
|
79
|
+
else
|
80
|
+
print cyan, "= #{security_group['id']}: #{security_group['name']} (#{security_group['description']})\n"
|
81
|
+
end
|
82
|
+
print reset,"\n\n"
|
83
|
+
|
84
|
+
rescue => e
|
85
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
86
|
+
return nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def add(args)
|
91
|
+
if args.count < 1
|
92
|
+
puts "\nUsage: morpheus security-groups add NAME [options]\n\n"
|
93
|
+
return
|
94
|
+
end
|
95
|
+
|
96
|
+
options = {:securityGroup => {:name => args[0]} }
|
97
|
+
optparse = OptionParser.new do|opts|
|
98
|
+
opts.banner = "\nUsage: morpheus security-groups add NAME [options]"
|
99
|
+
opts.on( '-d', '--description Description', "Description of the security group" ) do |description|
|
100
|
+
options[:securityGroup][:description] = description
|
101
|
+
end
|
102
|
+
|
103
|
+
opts.on( '-h', '--help', "Prints this help" ) do
|
104
|
+
puts opts
|
105
|
+
exit
|
106
|
+
end
|
107
|
+
end
|
108
|
+
optparse.parse(args)
|
109
|
+
|
110
|
+
begin
|
111
|
+
@security_groups_interface.create(options)
|
112
|
+
rescue => e
|
113
|
+
if e.response.code == 400
|
114
|
+
error = JSON.parse(e.response.to_s)
|
115
|
+
::Morpheus::Cli::ErrorHandler.new.print_errors(error)
|
116
|
+
else
|
117
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
118
|
+
end
|
119
|
+
return nil
|
120
|
+
end
|
121
|
+
list([])
|
122
|
+
end
|
123
|
+
|
124
|
+
def remove(args)
|
125
|
+
if args.count < 1
|
126
|
+
puts "\nUsage: morpheus security-groups remove ID\n\n"
|
127
|
+
return
|
128
|
+
end
|
129
|
+
begin
|
130
|
+
json_response = @security_groups_interface.get({id: args[0]})
|
131
|
+
security_group = json_response['securityGroup']
|
132
|
+
if security_group.nil?
|
133
|
+
puts "Security Group not found by id #{args[0]}"
|
134
|
+
return
|
135
|
+
end
|
136
|
+
@security_groups_interface.delete(security_group['id'])
|
137
|
+
list([])
|
138
|
+
rescue RestClient::Exception => e
|
139
|
+
if e.response.code == 400
|
140
|
+
error = JSON.parse(e.response.to_s)
|
141
|
+
::Morpheus::Cli::ErrorHandler.new.print_errors(error)
|
142
|
+
else
|
143
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
144
|
+
end
|
145
|
+
return nil
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def use(args)
|
150
|
+
if args.length < 1
|
151
|
+
puts "Usage: morpheus security-groups use ID"
|
152
|
+
return
|
153
|
+
end
|
154
|
+
begin
|
155
|
+
json_response = @security_groups_interface.get({id: args[0]})
|
156
|
+
security_group = json_response['securityGroup']
|
157
|
+
if !security_group.nil?
|
158
|
+
@active_security_group[@appliance_name.to_sym] = security_group['id']
|
159
|
+
::Morpheus::Cli::SecurityGroups.save_security_group(@active_security_group)
|
160
|
+
puts "Using Security Group #{args[0]}"
|
161
|
+
else
|
162
|
+
puts "Security Group not found"
|
163
|
+
end
|
164
|
+
rescue => e
|
165
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
166
|
+
return nil
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def self.load_security_group_file
|
171
|
+
remote_file = security_group_file_path
|
172
|
+
if File.exist? remote_file
|
173
|
+
return YAML.load_file(remote_file)
|
174
|
+
else
|
175
|
+
{}
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.security_group_file_path
|
180
|
+
home_dir = Dir.home
|
181
|
+
morpheus_dir = File.join(home_dir,".morpheus")
|
182
|
+
if !Dir.exist?(morpheus_dir)
|
183
|
+
Dir.mkdir(morpheus_dir)
|
184
|
+
end
|
185
|
+
return File.join(morpheus_dir,"securitygroup")
|
186
|
+
end
|
187
|
+
|
188
|
+
def self.save_security_group(security_group_map)
|
189
|
+
File.open(security_group_file_path, 'w') {|f| f.write security_group_map.to_yaml } #Store
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
data/lib/morpheus/cli/servers.rb
CHANGED
@@ -3,10 +3,13 @@ require 'io/console'
|
|
3
3
|
require 'rest_client'
|
4
4
|
require 'term/ansicolor'
|
5
5
|
require 'optparse'
|
6
|
+
require 'morpheus/cli/cli_command'
|
6
7
|
|
7
8
|
|
8
9
|
class Morpheus::Cli::Servers
|
9
10
|
include Term::ANSIColor
|
11
|
+
include Morpheus::Cli::CliCommand
|
12
|
+
|
10
13
|
def initialize()
|
11
14
|
@appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
12
15
|
@access_token = Morpheus::Cli::Credentials.new(@appliance_name,@appliance_url).request_credentials()
|
@@ -259,4 +262,4 @@ private
|
|
259
262
|
end
|
260
263
|
return group_results['groups'][0]
|
261
264
|
end
|
262
|
-
end
|
265
|
+
end
|
data/lib/morpheus/cli/version.rb
CHANGED
data/lib/morpheus/cli/zones.rb
CHANGED
@@ -3,9 +3,10 @@ require 'io/console'
|
|
3
3
|
require 'rest_client'
|
4
4
|
require 'term/ansicolor'
|
5
5
|
require 'optparse'
|
6
|
-
|
6
|
+
require 'morpheus/cli/cli_command'
|
7
7
|
|
8
8
|
class Morpheus::Cli::Zones
|
9
|
+
include Morpheus::Cli::CliCommand
|
9
10
|
include Term::ANSIColor
|
10
11
|
def initialize()
|
11
12
|
@appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
@@ -21,7 +22,7 @@ class Morpheus::Cli::Zones
|
|
21
22
|
return 1
|
22
23
|
end
|
23
24
|
if args.empty?
|
24
|
-
puts "\nUsage: morpheus zones [list,add,remove] [name]\n\n"
|
25
|
+
puts "\nUsage: morpheus zones [list,add,remove,firewall_disable,firewall_enable,security_groups,apply_security_groups] [name]\n\n"
|
25
26
|
return
|
26
27
|
end
|
27
28
|
|
@@ -32,8 +33,16 @@ class Morpheus::Cli::Zones
|
|
32
33
|
add(args[1..-1])
|
33
34
|
when 'remove'
|
34
35
|
remove(args[1..-1])
|
36
|
+
when 'firewall_disable'
|
37
|
+
firewall_disable(args[1..-1])
|
38
|
+
when 'firewall_enable'
|
39
|
+
firewall_enable(args[1..-1])
|
40
|
+
when 'security_groups'
|
41
|
+
security_groups(args[1..-1])
|
42
|
+
when 'apply_security_groups'
|
43
|
+
apply_security_groups(args[1..-1])
|
35
44
|
else
|
36
|
-
puts "\nUsage: morpheus zones [list,add,remove] [name]\n\n"
|
45
|
+
puts "\nUsage: morpheus zones [list,add,remove,firewall_disable,firewall_enable,security_groups,apply_security_groups] [name]\n\n"
|
37
46
|
end
|
38
47
|
end
|
39
48
|
|
@@ -163,6 +172,145 @@ class Morpheus::Cli::Zones
|
|
163
172
|
end
|
164
173
|
end
|
165
174
|
|
175
|
+
def firewall_disable(args)
|
176
|
+
if args.count < 1
|
177
|
+
puts "\nUsage: morpheus zones firewall_disable [name]\n\n"
|
178
|
+
return
|
179
|
+
end
|
180
|
+
begin
|
181
|
+
zone_results = @zones_interface.get({name: args[0]})
|
182
|
+
if zone_results['zones'].empty?
|
183
|
+
puts "Zone not found by name #{args[0]}"
|
184
|
+
return
|
185
|
+
end
|
186
|
+
@zones_interface.firewall_disable(zone_results['zones'][0]['id'])
|
187
|
+
security_groups([args[0]])
|
188
|
+
rescue RestClient::Exception => e
|
189
|
+
if e.response.code == 400
|
190
|
+
error = JSON.parse(e.response.to_s)
|
191
|
+
::Morpheus::Cli::ErrorHandler.new.print_errors(error)
|
192
|
+
else
|
193
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
194
|
+
end
|
195
|
+
return nil
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def firewall_enable(args)
|
200
|
+
if args.count < 1
|
201
|
+
puts "\nUsage: morpheus zones firewall_enable [name]\n\n"
|
202
|
+
return
|
203
|
+
end
|
204
|
+
begin
|
205
|
+
zone_results = @zones_interface.get({name: args[0]})
|
206
|
+
if zone_results['zones'].empty?
|
207
|
+
puts "Zone not found by name #{args[0]}"
|
208
|
+
return
|
209
|
+
end
|
210
|
+
@zones_interface.firewall_enable(zone_results['zones'][0]['id'])
|
211
|
+
security_groups([args[0]])
|
212
|
+
rescue RestClient::Exception => e
|
213
|
+
if e.response.code == 400
|
214
|
+
error = JSON.parse(e.response.to_s)
|
215
|
+
::Morpheus::Cli::ErrorHandler.new.print_errors(error)
|
216
|
+
else
|
217
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
218
|
+
end
|
219
|
+
return nil
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def security_groups(args)
|
224
|
+
if args.count < 1
|
225
|
+
puts "\nUsage: morpheus zones security_groups [name]\n\n"
|
226
|
+
return
|
227
|
+
end
|
228
|
+
begin
|
229
|
+
zone_results = @zones_interface.get({name: args[0]})
|
230
|
+
if zone_results['zones'].empty?
|
231
|
+
puts "Zone not found by name #{args[0]}"
|
232
|
+
return
|
233
|
+
end
|
234
|
+
|
235
|
+
zone_id = zone_results['zones'][0]['id']
|
236
|
+
json_response = @zones_interface.security_groups(zone_id)
|
237
|
+
|
238
|
+
securityGroups = json_response['securityGroups']
|
239
|
+
print "\n" ,cyan, bold, "Morpheus Security Groups for Zone:#{zone_id}\n","==================", reset, "\n\n"
|
240
|
+
print cyan, "Firewall Enabled=#{json_response['firewallEnabled']}\n\n"
|
241
|
+
if securityGroups.empty?
|
242
|
+
puts yellow,"No security groups currently applied.",reset
|
243
|
+
else
|
244
|
+
securityGroups.each do |securityGroup|
|
245
|
+
print cyan, "= #{securityGroup['id']} (#{securityGroup['name']}) - (#{securityGroup['description']})\n"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
print reset,"\n\n"
|
249
|
+
|
250
|
+
rescue RestClient::Exception => e
|
251
|
+
if e.response.code == 400
|
252
|
+
error = JSON.parse(e.response.to_s)
|
253
|
+
::Morpheus::Cli::ErrorHandler.new.print_errors(error)
|
254
|
+
else
|
255
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
256
|
+
end
|
257
|
+
return nil
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def apply_security_groups(args)
|
262
|
+
usage = <<-EOF
|
263
|
+
Usage: morpheus zones apply_security_groups [name] [options]
|
264
|
+
EOF
|
265
|
+
if args.count < 1
|
266
|
+
puts usage
|
267
|
+
return
|
268
|
+
end
|
269
|
+
|
270
|
+
options = {}
|
271
|
+
clear_or_secgroups_specified = false
|
272
|
+
optparse = OptionParser.new do|opts|
|
273
|
+
opts.banner = usage
|
274
|
+
opts.on( '-c', '--clear', "Clear all security groups" ) do
|
275
|
+
options[:securityGroupIds] = []
|
276
|
+
clear_or_secgroups_specified = true
|
277
|
+
end
|
278
|
+
opts.on( '-s', '--secgroups SECGROUPS', "Apply the specified comma separated security group ids" ) do |secgroups|
|
279
|
+
options[:securityGroupIds] = secgroups.split(",")
|
280
|
+
clear_or_secgroups_specified = true
|
281
|
+
end
|
282
|
+
opts.on( '-h', '--help', "Prints this help" ) do
|
283
|
+
puts opts
|
284
|
+
exit
|
285
|
+
end
|
286
|
+
end
|
287
|
+
optparse.parse(args)
|
288
|
+
|
289
|
+
if !clear_or_secgroups_specified
|
290
|
+
puts usage
|
291
|
+
exit
|
292
|
+
end
|
293
|
+
|
294
|
+
begin
|
295
|
+
zone_results = @zones_interface.get({name: args[0]})
|
296
|
+
if zone_results['zones'].empty?
|
297
|
+
puts "Zone not found by name #{args[0]}"
|
298
|
+
return
|
299
|
+
end
|
300
|
+
|
301
|
+
@zones_interface.apply_security_groups(zone_results['zones'][0]['id'], options)
|
302
|
+
security_groups([args[0]])
|
303
|
+
rescue RestClient::Exception => e
|
304
|
+
if e.response.code == 400
|
305
|
+
error = JSON.parse(e.response.to_s)
|
306
|
+
::Morpheus::Cli::ErrorHandler.new.print_errors(error)
|
307
|
+
else
|
308
|
+
puts "Error Communicating with the Appliance. Please try again later. #{e}"
|
309
|
+
end
|
310
|
+
return nil
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
166
314
|
private
|
167
315
|
|
168
316
|
def zone_type_for_id(id)
|
@@ -202,4 +350,4 @@ class Morpheus::Cli::Zones
|
|
202
350
|
end
|
203
351
|
return group_results['groups'][0]
|
204
352
|
end
|
205
|
-
end
|
353
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
|
3
|
+
module Morpheus
|
4
|
+
# A wrapper around rest_client so we can more easily deal with passing options (like turning on/off SSL verification)
|
5
|
+
class RestClient
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def execute(options)
|
10
|
+
opts = options.merge({})
|
11
|
+
|
12
|
+
unless ssl_verification_enabled?
|
13
|
+
opts[:verify_ssl] = OpenSSL::SSL::VERIFY_NONE
|
14
|
+
end
|
15
|
+
|
16
|
+
::RestClient::Request.execute opts
|
17
|
+
end
|
18
|
+
|
19
|
+
def post(url, payload)
|
20
|
+
execute url: url, payload: payload, method: :post
|
21
|
+
end
|
22
|
+
|
23
|
+
def ssl_verification_enabled?
|
24
|
+
begin
|
25
|
+
@@ssl_verification_enabled.nil? ? true : @@ssl_verification_enabled
|
26
|
+
rescue
|
27
|
+
@@ssl_verification_enabled = true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def enable_ssl_verification=(verify)
|
32
|
+
@@ssl_verification_enabled = verify
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def build_request_args(url, method, payload)
|
38
|
+
args = {url: url,
|
39
|
+
method: method,
|
40
|
+
payload: payload}
|
41
|
+
|
42
|
+
unless ssl_verification_enabled?
|
43
|
+
args[:verify_ssl] = OpenSSL::SSL::VERIFY_NONE
|
44
|
+
end
|
45
|
+
|
46
|
+
args
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|