morpheus-cli 6.1.1 → 6.2.0
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/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +8 -4
- data/lib/morpheus/api/backup_jobs_interface.rb +4 -0
- data/lib/morpheus/api/backup_restores_interface.rb +23 -0
- data/lib/morpheus/api/backup_results_interface.rb +28 -0
- data/lib/morpheus/api/backups_interface.rb +5 -4
- data/lib/morpheus/cli/cli_command.rb +172 -45
- data/lib/morpheus/cli/commands/appliance_settings_command.rb +7 -19
- data/lib/morpheus/cli/commands/apps.rb +1 -1
- data/lib/morpheus/cli/commands/backup_jobs_command.rb +77 -20
- data/lib/morpheus/cli/commands/backup_restores_command.rb +144 -0
- data/lib/morpheus/cli/commands/backup_results_command.rb +149 -0
- data/lib/morpheus/cli/commands/backups_command.rb +214 -93
- data/lib/morpheus/cli/commands/hosts.rb +15 -2
- data/lib/morpheus/cli/commands/instances.rb +23 -3
- data/lib/morpheus/cli/commands/load_balancer_pools.rb +37 -1
- data/lib/morpheus/cli/commands/security_groups.rb +58 -37
- data/lib/morpheus/cli/commands/service_catalog_command.rb +50 -83
- data/lib/morpheus/cli/commands/view.rb +20 -20
- data/lib/morpheus/cli/mixins/backups_helper.rb +58 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +27 -4
- data/lib/morpheus/cli/option_types.rb +10 -7
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/formatters.rb +1 -1
- data/lib/morpheus/routes.rb +18 -3
- metadata +6 -8
- data/lib/morpheus/api/doc_interface.rb +0 -50
- data/lib/morpheus/cli/commands/doc.rb +0 -182
- data/test/api/doc_interface_test.rb +0 -35
- data/test/cli/doc_test.rb +0 -35
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
require 'morpheus/cli/cli_command'
|
2
3
|
|
3
4
|
class Morpheus::Cli::BackupsCommand
|
@@ -5,17 +6,20 @@ class Morpheus::Cli::BackupsCommand
|
|
5
6
|
include Morpheus::Cli::BackupsHelper
|
6
7
|
include Morpheus::Cli::ProvisioningHelper
|
7
8
|
include Morpheus::Cli::OptionSourceHelper
|
8
|
-
|
9
|
-
set_command_hidden # hide until ready
|
10
9
|
|
10
|
+
set_command_description "View and manage backups"
|
11
11
|
set_command_name :'backups'
|
12
|
+
register_subcommands :list, :get, :add, :update, :remove, :execute #, :restore
|
13
|
+
register_subcommands :list_jobs, :get_job, :add_job, :update_job, :remove_job, :execute_job
|
14
|
+
register_subcommands :list_results, :get_result, :remove_result
|
15
|
+
register_subcommands :list_restores, :get_restore, :remove_restore
|
12
16
|
|
13
|
-
register_subcommands :list, :get, :add, :update, :remove, :run, :restore
|
14
|
-
|
15
17
|
def connect(opts)
|
16
18
|
@api_client = establish_remote_appliance_connection(opts)
|
17
19
|
@backups_interface = @api_client.backups
|
18
20
|
@backup_jobs_interface = @api_client.backup_jobs
|
21
|
+
@backup_results_interface = @api_client.backup_results
|
22
|
+
@backup_restores_interface = @api_client.backup_restores
|
19
23
|
@instances_interface = @api_client.instances
|
20
24
|
@servers_interface = @api_client.servers
|
21
25
|
end
|
@@ -40,14 +44,9 @@ class Morpheus::Cli::BackupsCommand
|
|
40
44
|
options[:phrase] = args.join(" ")
|
41
45
|
end
|
42
46
|
params.merge!(parse_list_options(options))
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
return
|
47
|
-
end
|
48
|
-
json_response = @backups_interface.list(params)
|
49
|
-
backups = json_response['backups']
|
50
|
-
render_response(json_response, options, 'backups') do
|
47
|
+
parse_options(options, params)
|
48
|
+
execute_api(@backups_interface, :list, [], options, 'backup') do |json_response|
|
49
|
+
backups = json_response['backups']
|
51
50
|
print_h1 "Morpheus Backups", parse_list_subtitles(options), options
|
52
51
|
if backups.empty?
|
53
52
|
print cyan,"No backups found.",reset,"\n"
|
@@ -74,6 +73,7 @@ EOT
|
|
74
73
|
optparse.parse!(args)
|
75
74
|
verify_args!(args:args, optparse:optparse, min:1)
|
76
75
|
connect(options)
|
76
|
+
parse_options(options, params)
|
77
77
|
id_list = parse_id_list(args)
|
78
78
|
return run_command_for_each_arg(id_list) do |arg|
|
79
79
|
_get(arg, params, options)
|
@@ -88,14 +88,10 @@ EOT
|
|
88
88
|
end
|
89
89
|
id = record['id']
|
90
90
|
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
96
|
-
json_response = @backups_interface.get(id, params)
|
97
|
-
backup = json_response['backup']
|
98
|
-
render_response(json_response, options, 'backup') do
|
91
|
+
options[:params] = params # parse_options(options, params)
|
92
|
+
options.delete(:payload)
|
93
|
+
execute_api(@backups_interface, :get, [id], options, 'backup') do |json_response|
|
94
|
+
backup = json_response['backup']
|
99
95
|
print_h1 "Backup Details", [], options
|
100
96
|
print cyan
|
101
97
|
columns = backup_column_definitions
|
@@ -105,7 +101,6 @@ EOT
|
|
105
101
|
print_description_list(columns, backup, options)
|
106
102
|
print reset,"\n"
|
107
103
|
end
|
108
|
-
return 0, nil
|
109
104
|
end
|
110
105
|
|
111
106
|
def add(args)
|
@@ -113,7 +108,6 @@ EOT
|
|
113
108
|
params = {}
|
114
109
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
115
110
|
opts.banner = subcommand_usage("[name] [options]")
|
116
|
-
# build_option_type_options(opts, options, add_backup_option_types)
|
117
111
|
opts.on('--source VALUE', String, "Backup Source: instance, host or provider") do |val|
|
118
112
|
options[:options]['source'] = val
|
119
113
|
end
|
@@ -133,7 +127,8 @@ EOT
|
|
133
127
|
opts.on('--name VALUE', String, "Name") do |val|
|
134
128
|
options[:options]['name'] = val
|
135
129
|
end
|
136
|
-
|
130
|
+
# build_option_type_options(opts, options, add_backup_option_types)
|
131
|
+
build_standard_add_many_options(opts, options)
|
137
132
|
opts.footer = <<-EOT
|
138
133
|
Create a new backup.
|
139
134
|
EOT
|
@@ -142,13 +137,10 @@ EOT
|
|
142
137
|
verify_args!(args:args, optparse:optparse, min:0, max:1)
|
143
138
|
options[:options]['name'] = args[0] if args[0]
|
144
139
|
connect(options)
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
else
|
150
|
-
payload.deep_merge!({'backup' => parse_passed_options(options)})
|
151
|
-
|
140
|
+
parse_payload(options, 'backup') do |payload|
|
141
|
+
# v_prompt = Morpheus::Cli::OptionTypes.no_prompt(add_backup_option_types, options[:options], @api_client)
|
142
|
+
# v_prompt.deep_compact!.booleanize! # remove empty values and convert checkbox "on" and "off" to true and false
|
143
|
+
# params.deep_merge!(v_prompt)
|
152
144
|
location_type = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'source', 'fieldLabel' => 'Source', 'type' => 'select', 'selectOptions' => [{'name' => 'Instance', 'value' => 'instance'}, {'name' => 'Host', 'value' => 'server'}, {'name' => 'Provider', 'value' => 'provider'}], 'defaultValue' => 'instance', 'required' => true, 'description' => 'Where is the backup located?'}], options[:options], @api_client)['source']
|
153
145
|
params['locationType'] = location_type
|
154
146
|
if location_type == 'instance'
|
@@ -183,7 +175,6 @@ EOT
|
|
183
175
|
end
|
184
176
|
elsif location_type == 'server'
|
185
177
|
|
186
|
-
|
187
178
|
end
|
188
179
|
# Backup Type
|
189
180
|
avail_backup_types = (create_results['backupTypes'] || []).collect {|it| {'name' => it['name'], 'value' => it['code']} }
|
@@ -197,9 +188,15 @@ EOT
|
|
197
188
|
params['jobAction'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'jobAction', 'fieldLabel' => 'Backup Job Type', 'type' => 'select', 'optionSource' => 'backupJobActions', 'required' => true, 'defaultValue' => 'new'}], options[:options], @api_client)['jobAction']
|
198
189
|
if params['jobAction'] == 'new'
|
199
190
|
params['jobName'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'jobName', 'fieldLabel' => 'Job Name', 'type' => 'text', 'required' => false, 'defaultValue' => nil}], options[:options], @api_client)['jobName']
|
200
|
-
default_retention_count = create_results['backup'] ? create_results['backup']['retentionCount'] : nil
|
191
|
+
default_retention_count = (create_results['backup'] && create_results['backup']['retentionCount']) ? create_results['backup']['retentionCount'] : ((create_results['backupSettings'] && create_results['backupSettings']['retentionCount']) ? create_results['backupSettings']['retentionCount'] : nil)
|
201
192
|
params['retentionCount'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'retentionCount', 'fieldLabel' => 'Retention Count', 'type' => 'number', 'required' => false, 'defaultValue' => default_retention_count}], options[:options], @api_client)['retentionCount']
|
202
|
-
params['jobSchedule'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'jobSchedule', 'fieldLabel' => 'Backup Schedule', 'type' => 'select', 'optionSource' =>
|
193
|
+
params['jobSchedule'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'jobSchedule', 'fieldLabel' => 'Backup Schedule', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
|
194
|
+
schedules = api_client.options.options_for_source('executeSchedules',{})['data']
|
195
|
+
[{"name" => "Manual", "value" => "manual"}] + schedules
|
196
|
+
}, 'required' => false}], options[:options], @api_client)['jobSchedule']
|
197
|
+
if params['jobSchedule'] == 'manual' || params['jobSchedule'] == ''
|
198
|
+
params.delete('jobSchedule')
|
199
|
+
end
|
203
200
|
elsif params['jobAction'] == 'clone'
|
204
201
|
params['jobId'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'jobId', 'fieldLabel' => 'Backup Job', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
|
205
202
|
@backup_jobs_interface.list({max:10000})['jobs'].collect {|backup_job|
|
@@ -215,21 +212,13 @@ EOT
|
|
215
212
|
}, 'required' => true}], options[:options], @api_client)['jobId']
|
216
213
|
end
|
217
214
|
end
|
218
|
-
|
219
215
|
payload['backup'].deep_merge!(params)
|
220
216
|
end
|
221
|
-
@backups_interface
|
222
|
-
|
223
|
-
print_dry_run @backups_interface.dry.create(payload)
|
224
|
-
return 0, nil
|
225
|
-
end
|
226
|
-
json_response = @backups_interface.create(payload)
|
227
|
-
backup = json_response['backup']
|
228
|
-
render_response(json_response, options, 'backup') do
|
217
|
+
execute_api(@backups_interface, :create, [], options, 'backup') do |json_response|
|
218
|
+
backup = json_response['backup']
|
229
219
|
print_green_success "Added backup #{backup['name']}"
|
230
|
-
|
220
|
+
_get(backup["id"], {}, options)
|
231
221
|
end
|
232
|
-
return 0, nil
|
233
222
|
end
|
234
223
|
|
235
224
|
def update(args)
|
@@ -238,8 +227,16 @@ EOT
|
|
238
227
|
payload = {}
|
239
228
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
240
229
|
opts.banner = subcommand_usage("[backup] [options]")
|
230
|
+
# opts.on('--name NAME', String, "Name") do |val|
|
231
|
+
# options[:options]['name'] = val
|
232
|
+
# end
|
233
|
+
# opts.on('--job JOB', String, "Name or ID of the Backup Job to associate this backup with") do |val|
|
234
|
+
# options[:options]['jobId'] = val
|
235
|
+
# end
|
236
|
+
# opts.on('--enabled [on|off]', String, "Can be used to disable") do |val|
|
237
|
+
# options[:options]['enabled'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s.empty?
|
238
|
+
# end
|
241
239
|
build_option_type_options(opts, options, update_backup_option_types)
|
242
|
-
build_option_type_options(opts, options, update_backup_advanced_option_types)
|
243
240
|
build_standard_update_options(opts, options)
|
244
241
|
opts.footer = <<-EOT
|
245
242
|
Update a backup.
|
@@ -251,36 +248,21 @@ EOT
|
|
251
248
|
connect(options)
|
252
249
|
backup = find_backup_by_name_or_id(args[0])
|
253
250
|
return 1 if backup.nil?
|
254
|
-
|
255
|
-
if options[:payload]
|
256
|
-
payload = options[:payload]
|
257
|
-
payload.deep_merge!({'backup' => parse_passed_options(options)})
|
258
|
-
else
|
259
|
-
payload.deep_merge!({'backup' => parse_passed_options(options)})
|
251
|
+
parse_payload(options, 'backup') do |payload|
|
260
252
|
# do not prompt on update
|
261
|
-
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_backup_option_types, options[:options], @api_client
|
262
|
-
v_prompt.deep_compact!
|
253
|
+
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_backup_option_types, options[:options], @api_client)
|
254
|
+
v_prompt.deep_compact!.booleanize! # remove empty values and convert checkbox "on" and "off" to true and false
|
263
255
|
params.deep_merge!(v_prompt)
|
264
|
-
advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_backup_advanced_option_types, options[:options], @api_client, options[:params])
|
265
|
-
advanced_config.deep_compact!
|
266
|
-
params.deep_merge!(advanced_config)
|
267
256
|
payload.deep_merge!({'backup' => params})
|
268
257
|
if payload['backup'].empty? # || options[:no_prompt]
|
269
258
|
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
270
259
|
end
|
271
260
|
end
|
272
|
-
@backups_interface
|
273
|
-
|
274
|
-
print_dry_run @backups_interface.dry.update(backup['id'], payload)
|
275
|
-
return
|
276
|
-
end
|
277
|
-
json_response = @backups_interface.update(backup['id'], payload)
|
278
|
-
backup = json_response['backup']
|
279
|
-
render_response(json_response, options, 'backup') do
|
261
|
+
execute_api(@backups_interface, :update, [backup['id']], options, 'backup') do |json_response|
|
262
|
+
backup = json_response['backup']
|
280
263
|
print_green_success "Updated backup #{backup['name']}"
|
281
264
|
return _get(backup["id"], {}, options)
|
282
265
|
end
|
283
|
-
return 0, nil
|
284
266
|
end
|
285
267
|
|
286
268
|
def remove(args)
|
@@ -299,23 +281,169 @@ EOT
|
|
299
281
|
connect(options)
|
300
282
|
backup = find_backup_by_name_or_id(args[0])
|
301
283
|
return 1 if backup.nil?
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
284
|
+
parse_options(options, params)
|
285
|
+
confirm!("Are you sure you want to delete the backup #{backup['name']}?", options)
|
286
|
+
execute_api(@backups_interface, :destroy, [backup['id']], options, 'backup') do |json_response|
|
287
|
+
print_green_success "Removed backup #{backup['name']}"
|
306
288
|
end
|
307
|
-
|
308
|
-
|
289
|
+
end
|
290
|
+
|
291
|
+
def execute(args)
|
292
|
+
options = {}
|
293
|
+
params = {}
|
294
|
+
payload = {}
|
295
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
296
|
+
opts.banner = subcommand_usage("[backup] [options]")
|
297
|
+
build_standard_post_options(opts, options)
|
298
|
+
opts.footer = <<-EOT
|
299
|
+
Execute a backup to create a new backup result.
|
300
|
+
[backup] is required. This is the name or id of a backup.
|
301
|
+
EOT
|
309
302
|
end
|
310
|
-
|
311
|
-
|
312
|
-
|
303
|
+
optparse.parse!(args)
|
304
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
305
|
+
connect(options)
|
306
|
+
backup = find_backup_by_name_or_id(args[0])
|
307
|
+
return 1 if backup.nil?
|
308
|
+
parse_payload(options)
|
309
|
+
execute_api(@backups_interface, :execute_backup, [backup['id']], options, 'backup') do |json_response|
|
310
|
+
print_green_success "Executing backup #{backup['name']}"
|
311
|
+
# should get the result maybe, or could even support refreshing until it is complete...
|
312
|
+
# return _get(backup["id"], {}, options)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
def restore(args)
|
317
|
+
raise "Not Yet Implemented"
|
318
|
+
options = {}
|
319
|
+
params = {}
|
320
|
+
payload = {}
|
321
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
322
|
+
opts.banner = subcommand_usage("[backup] [result] [options]")
|
323
|
+
build_standard_post_options(opts, options)
|
324
|
+
opts.on('--result ID', String, "Backup Result ID that is being restored") do |val|
|
325
|
+
options[:options]['backupResultId'] = val
|
326
|
+
end
|
327
|
+
opts.on('--restore-instance existing|new', String, "Instance being targeted for the restore, existing to restore the current instance or new to create a new instance. The current instance is targeted by default.") do |val|
|
328
|
+
# restoreInstanceSelect=current|new and the flag on the restore object is called 'restoreToNew'
|
329
|
+
options[:options]['restoreInstanceSelect'] = val
|
330
|
+
end
|
331
|
+
opts.footer = <<-EOT
|
332
|
+
Restore a backup, replacing the existing target with the specified backup result.
|
333
|
+
[backup] is required. This is the name or id of a backup.
|
334
|
+
--result ID is required. This is the id of a backup result being restored.
|
335
|
+
EOT
|
336
|
+
end
|
337
|
+
optparse.parse!(args)
|
338
|
+
verify_args!(args:args, optparse:optparse, max:1)
|
339
|
+
connect(options)
|
340
|
+
backup = nil
|
341
|
+
backup_result = nil
|
342
|
+
if args[0]
|
343
|
+
backup = find_backup_by_name_or_id(args[0])
|
344
|
+
return 1 if backup.nil?
|
345
|
+
else
|
346
|
+
# Prompt for backup
|
347
|
+
if backup.nil?
|
348
|
+
# Backup
|
349
|
+
available_backups = @backups_interface.list({max:10000})['backups'].collect {|it| {'name' => it['name'], 'value' => it['id']}}
|
350
|
+
backup_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'backupId', 'fieldLabel' => 'Backup', 'type' => 'select', 'selectOptions' => available_backups, 'required' => true}], options[:options], @api_client)['backupId']
|
351
|
+
backup = find_backup_by_name_or_id(backup_id)
|
352
|
+
return 1 if backup.nil?
|
353
|
+
end
|
354
|
+
end
|
355
|
+
# Prompt for backup result
|
356
|
+
if backup_result.nil?
|
357
|
+
|
358
|
+
# Instance
|
359
|
+
available_backup_results = @backups_interface.list({backupId: backup['id'], max:10000})['results'].collect {|it| {'name' => it['name'], 'value' => it['id']}}
|
360
|
+
params['backupResultId'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'backupResultId', 'fieldLabel' => 'Backup Result', 'type' => 'select', 'selectOptions' => available_backup_results, 'required' => true}], options[:options], @api_client)['backupResultId']
|
361
|
+
# Name
|
362
|
+
params['name'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Backup Name'}], options[:options], @api_client)['name']
|
363
|
+
end
|
364
|
+
|
365
|
+
parse_payload(options, 'restore') do |payload|
|
366
|
+
# Prompt for restore configuration
|
367
|
+
# We should probably require identifying the instance by name or id too, just to be safe.
|
368
|
+
# Target Instance
|
369
|
+
if backup_result['instance']
|
370
|
+
params['restoreInstanceSelect'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Instance being targeted for the restore, existing to restore the current instance or new to create a new instance. By default the existing instance is restored.'}], options[:options], @api_client)['restoreInstanceSelect']
|
371
|
+
end
|
372
|
+
payload['backup'].deep_merge!(params)
|
373
|
+
end
|
374
|
+
|
375
|
+
print cyan,"#{bold}WARNING!#{reset}#{cyan} Restoring a backup will erase all data when restored to an existing instance.",reset,"\n"
|
376
|
+
confirm!("Are you sure you want to restore the backup result ID: #{backup_result['id']} Name: #{backup_result['backup']['name'] rescue ''} Date: (#{format_local_dt(backup_result['dateCreated'])})?", options)
|
377
|
+
execute_api(@backups_interface, :restore, [backup['id']], options, 'backup') do |json_response|
|
378
|
+
print_green_success "Restoring backup result ID: #{backup_result['id']} Name: #{backup_result['backup']['name'] rescue ''} Date: (#{format_local_dt(backup_result['dateCreated'])}"
|
379
|
+
# should get the restore maybe, or could even support refreshing until it is complete...
|
380
|
+
# restore = json_response["restore"]
|
381
|
+
# return _get_restore(restore["id"], {}, options)
|
313
382
|
end
|
314
|
-
|
383
|
+
end
|
384
|
+
|
385
|
+
# Delegate jobs, results and restores
|
386
|
+
# to backup-jobs, backup-results and backup-restores
|
387
|
+
# which are hidden in the docs
|
388
|
+
|
389
|
+
## Backup Jobs
|
390
|
+
|
391
|
+
def list_jobs(args)
|
392
|
+
Morpheus::Cli::BackupJobsCommand.new.list(args)
|
393
|
+
end
|
394
|
+
|
395
|
+
def get_job(args)
|
396
|
+
Morpheus::Cli::BackupJobsCommand.new.get(args)
|
397
|
+
end
|
398
|
+
|
399
|
+
def add_job(args)
|
400
|
+
Morpheus::Cli::BackupJobsCommand.new.add(args)
|
401
|
+
end
|
402
|
+
|
403
|
+
def update_job(args)
|
404
|
+
Morpheus::Cli::BackupJobsCommand.new.update(args)
|
405
|
+
end
|
406
|
+
|
407
|
+
def remove_job(args)
|
408
|
+
Morpheus::Cli::BackupJobsCommand.new.remove(args)
|
409
|
+
end
|
410
|
+
|
411
|
+
def execute_job(args)
|
412
|
+
Morpheus::Cli::BackupJobsCommand.new.execute(args)
|
413
|
+
end
|
414
|
+
|
415
|
+
## Backup Results
|
416
|
+
|
417
|
+
def list_results(args)
|
418
|
+
Morpheus::Cli::BackupResultsCommand.new.list(args)
|
419
|
+
end
|
420
|
+
|
421
|
+
def get_result(args)
|
422
|
+
Morpheus::Cli::BackupResultsCommand.new.get(args)
|
423
|
+
end
|
424
|
+
|
425
|
+
def remove_result(args)
|
426
|
+
Morpheus::Cli::BackupResultsCommand.new.remove(args)
|
427
|
+
end
|
428
|
+
|
429
|
+
## Backup Restores
|
430
|
+
|
431
|
+
def list_restores(args)
|
432
|
+
Morpheus::Cli::BackupRestoresCommand.new.list(args)
|
433
|
+
end
|
434
|
+
|
435
|
+
def get_restore(args)
|
436
|
+
Morpheus::Cli::BackupRestoresCommand.new.get(args)
|
437
|
+
end
|
438
|
+
|
439
|
+
def remove_restore(args)
|
440
|
+
Morpheus::Cli::BackupRestoresCommand.new.remove(args)
|
315
441
|
end
|
316
442
|
|
317
443
|
private
|
318
444
|
|
445
|
+
## Backups
|
446
|
+
|
319
447
|
def backup_list_column_definitions()
|
320
448
|
{
|
321
449
|
"ID" => 'id',
|
@@ -345,12 +473,13 @@ EOT
|
|
345
473
|
"Host" => lambda {|it| it['server']['name'] rescue '' },
|
346
474
|
"Schedule" => lambda {|it| it['schedule']['name'] rescue '' },
|
347
475
|
"Backup Job" => lambda {|it| it['job']['name'] rescue '' },
|
476
|
+
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
348
477
|
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
349
478
|
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
350
479
|
}
|
351
480
|
end
|
352
481
|
|
353
|
-
# this is not so simple, need to first choose select instance, host or provider
|
482
|
+
# not used atm, this is not so simple, need to first choose select instance, host or provider
|
354
483
|
def add_backup_option_types
|
355
484
|
[
|
356
485
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true},
|
@@ -364,24 +493,16 @@ EOT
|
|
364
493
|
]
|
365
494
|
end
|
366
495
|
|
367
|
-
def add_backup_advanced_option_types
|
368
|
-
[]
|
369
|
-
end
|
370
|
-
|
371
496
|
def update_backup_option_types
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
it.delete('required')
|
382
|
-
it.delete('defaultValue')
|
383
|
-
it
|
384
|
-
}
|
497
|
+
[
|
498
|
+
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text'},
|
499
|
+
{'fieldName' => 'jobId', 'fieldLabel' => 'Backup Job', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
|
500
|
+
@backup_jobs_interface.list({max:10000})['jobs'].collect {|backup_job|
|
501
|
+
{'name' => backup_job['name'], 'value' => backup_job['id'], 'id' => backup_job['id']}
|
502
|
+
}
|
503
|
+
} },
|
504
|
+
{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox'},
|
505
|
+
]
|
385
506
|
end
|
386
507
|
|
387
508
|
end
|
@@ -1500,8 +1500,19 @@ class Morpheus::Cli::Hosts
|
|
1500
1500
|
params = {}
|
1501
1501
|
options = {}
|
1502
1502
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1503
|
-
opts.banner = subcommand_usage("[
|
1503
|
+
opts.banner = subcommand_usage("[host] [workflow] [options]")
|
1504
|
+
opts.on("--phase PHASE", String, "Task Phase to run for Provisioning workflows. The default is provision.") do |val|
|
1505
|
+
options[:phase] = val
|
1506
|
+
end
|
1504
1507
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
|
1508
|
+
opts.footer = <<-EOT
|
1509
|
+
Run workflow for a host.
|
1510
|
+
[host] is required. This is the name or id of a host
|
1511
|
+
[workflow] is required. This is the name or id of a workflow
|
1512
|
+
By default the provision phase is executed.
|
1513
|
+
Use the --phase option to execute a different phase.
|
1514
|
+
The available phases are start, stop, preProvision, provision, postProvision, preDeploy, deploy, reconfigure, teardown, startup and shutdown.
|
1515
|
+
EOT
|
1505
1516
|
end
|
1506
1517
|
optparse.parse!(args)
|
1507
1518
|
if args.count != 2
|
@@ -1555,7 +1566,9 @@ class Morpheus::Cli::Hosts
|
|
1555
1566
|
payload['taskSet']["#{workflow['id']}"] ||= {}
|
1556
1567
|
payload['taskSet']["#{workflow['id']}"].deep_merge!(params)
|
1557
1568
|
end
|
1558
|
-
|
1569
|
+
if options[:phase]
|
1570
|
+
payload['taskPhase'] = options[:phase]
|
1571
|
+
end
|
1559
1572
|
begin
|
1560
1573
|
@servers_interface.setopts(options)
|
1561
1574
|
if options[:dry_run]
|
@@ -258,7 +258,7 @@ class Morpheus::Cli::Instances
|
|
258
258
|
end
|
259
259
|
row = {
|
260
260
|
id: instance['id'],
|
261
|
-
name: instance['name'],
|
261
|
+
name: instance['displayName'] ? instance['displayName'] : instance['name'],
|
262
262
|
labels: format_list(instance['labels'], '', 3),
|
263
263
|
connection: format_instance_connection_string(instance),
|
264
264
|
environment: instance['instanceContext'],
|
@@ -599,6 +599,9 @@ class Morpheus::Cli::Instances
|
|
599
599
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
600
600
|
opts.banner = subcommand_usage("[instance]")
|
601
601
|
opts.on('--name VALUE', String, "Name") do |val|
|
602
|
+
params['name'] = val
|
603
|
+
end
|
604
|
+
opts.on('--displayName VALUE', String, "Name") do |val|
|
602
605
|
params['displayName'] = val
|
603
606
|
end
|
604
607
|
opts.on('--description VALUE', String, "Description") do |val|
|
@@ -1400,6 +1403,7 @@ class Morpheus::Cli::Instances
|
|
1400
1403
|
description_cols = {
|
1401
1404
|
"ID" => 'id',
|
1402
1405
|
"Name" => 'name',
|
1406
|
+
"Display Name" => 'displayName',
|
1403
1407
|
"Description" => 'description',
|
1404
1408
|
"Group" => lambda {|it| it['group'] ? it['group']['name'] : '' },
|
1405
1409
|
"Cloud" => lambda {|it| it['cloud'] ? it['cloud']['name'] : '' },
|
@@ -3353,7 +3357,18 @@ EOT
|
|
3353
3357
|
options = {}
|
3354
3358
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
3355
3359
|
opts.banner = subcommand_usage("[instance] [workflow] [options]")
|
3360
|
+
opts.on("--phase PHASE", String, "Task Phase to run for Provisioning workflows. The default is provision.") do |val|
|
3361
|
+
options[:phase] = val
|
3362
|
+
end
|
3356
3363
|
build_common_options(opts, options, [:options, :json, :dry_run, :remote])
|
3364
|
+
opts.footer = <<-EOT
|
3365
|
+
Run workflow for an instance.
|
3366
|
+
[instance] is required. This is the name or id of an instance
|
3367
|
+
[workflow] is required. This is the name or id of a workflow
|
3368
|
+
By default the provision phase is executed.
|
3369
|
+
Use the --phase option to execute a different phase.
|
3370
|
+
The available phases are start, stop, preProvision, provision, postProvision, preDeploy, deploy, reconfigure, teardown, startup and shutdown.
|
3371
|
+
EOT
|
3357
3372
|
end
|
3358
3373
|
optparse.parse!(args)
|
3359
3374
|
if args.count != 2
|
@@ -3387,6 +3402,9 @@ EOT
|
|
3387
3402
|
# end
|
3388
3403
|
|
3389
3404
|
workflow_payload = {taskSet: {"#{workflow['id']}" => params }}
|
3405
|
+
if options[:phase]
|
3406
|
+
workflow_payload['taskPhase'] = options[:phase]
|
3407
|
+
end
|
3390
3408
|
begin
|
3391
3409
|
@instances_interface.setopts(options)
|
3392
3410
|
if options[:dry_run]
|
@@ -5294,6 +5312,7 @@ private
|
|
5294
5312
|
rescue RestClient::Exception => e
|
5295
5313
|
if e.response && e.response.code == 404
|
5296
5314
|
print_red_alert "Workflow not found by id #{id}"
|
5315
|
+
exit 1
|
5297
5316
|
else
|
5298
5317
|
raise e
|
5299
5318
|
end
|
@@ -5304,12 +5323,12 @@ private
|
|
5304
5323
|
workflows = @task_sets_interface.list({name: name.to_s})['taskSets']
|
5305
5324
|
if workflows.empty?
|
5306
5325
|
print_red_alert "Workflow not found by name #{name}"
|
5307
|
-
|
5326
|
+
exit 1
|
5308
5327
|
elsif workflows.size > 1
|
5309
5328
|
print_red_alert "#{workflows.size} workflows by name #{name}"
|
5310
5329
|
print_workflows_table(workflows, {color: red})
|
5311
5330
|
print reset,"\n\n"
|
5312
|
-
|
5331
|
+
exit 1
|
5313
5332
|
else
|
5314
5333
|
return workflows[0]
|
5315
5334
|
end
|
@@ -5423,6 +5442,7 @@ private
|
|
5423
5442
|
def add_instance_schedule_option_types()
|
5424
5443
|
[
|
5425
5444
|
{'code' => 'scheduleType', 'fieldName' => 'scheduleType', 'fieldLabel' => 'Schedule Type', 'type' => 'select', 'selectOptions' => [{'name'=>'Day Of Week', 'value'=>'dayOfWeek'},{'name'=>'Exact', 'value'=>'exact'}], 'description' => "Schedule type can be recurring day of the week str or exact start and end timestamp", 'required' => true, 'defaultValue' => 'dayOfWeek'},
|
5445
|
+
{'dependsOnCode' => 'scheduleType:dayOfWeek', 'fieldName' => 'scheduleTimezone', 'fieldLabel' => 'Timezone', 'type' => 'select', 'optionSource' => 'timezones' , 'description' => "The timezone", 'defaultValue' => "UTC", 'required' => false},
|
5426
5446
|
{'dependsOnCode' => 'scheduleType:dayOfWeek', 'fieldName' => 'startDayOfWeek', 'fieldLabel' => 'Start Day Of Week', 'type' => 'select', 'selectOptions' => day_of_week_dropdown, 'description' => "Start day of the week Sunday-Saturday (1-7)", 'defaultValue' => "Sunday", 'required' => true},
|
5427
5447
|
{'dependsOnCode' => 'scheduleType:dayOfWeek', 'fieldName' => 'startTime', 'fieldLabel' => 'Start Time (HH:MM)', 'type' => 'text', 'description' => "Start time in HH:MM 24-hour format", 'placeHolder' => 'HH:MM', 'defaultValue' => "01:00", 'required' => true},
|
5428
5448
|
{'dependsOnCode' => 'scheduleType:dayOfWeek', 'fieldName' => 'endDayOfWeek', 'fieldLabel' => 'End Day Of Week', 'type' => 'select', 'selectOptions' => day_of_week_dropdown, 'description' => "End day of the week Sunday-Saturday (1-7)", 'defaultValue' => "Sunday", 'required' => true},
|
@@ -13,7 +13,7 @@ class Morpheus::Cli::LoadBalancerPools
|
|
13
13
|
set_rest_parent_name :load_balancers
|
14
14
|
|
15
15
|
register_subcommands :list, :get, :add, :update, :remove
|
16
|
-
register_interfaces :load_balancers, :load_balancer_types
|
16
|
+
register_interfaces :load_balancer_pools_secondary, :load_balancers, :load_balancer_types
|
17
17
|
|
18
18
|
|
19
19
|
# set_rest_interface_name :load_balancer_pools
|
@@ -90,4 +90,40 @@ class Morpheus::Cli::LoadBalancerPools
|
|
90
90
|
|
91
91
|
## using CliCommand's generic find_by methods
|
92
92
|
|
93
|
+
def find_load_balancer_pool_by_name_or_id(load_balancer_pool_id, val)
|
94
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
95
|
+
return find_load_balancer_pool_by_id(load_balancer_pool_id, val)
|
96
|
+
else
|
97
|
+
return find_load_balancer_pool_by_name(load_balancer_pool_id, val)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def find_load_balancer_pool_by_id(load_balancer_pool_id, id)
|
102
|
+
begin
|
103
|
+
json_response = @load_balancer_pools_secondary_interface.get(load_balancer_pool_id, id.to_i)
|
104
|
+
return json_response[load_balancer_pool_object_key]
|
105
|
+
rescue RestClient::Exception => e
|
106
|
+
if e.response && e.response.code == 404
|
107
|
+
print_red_alert "Load Balancer Pool not found by id #{id}"
|
108
|
+
else
|
109
|
+
raise e
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def find_load_balancer_pool_by_name(load_balancer_pool_id, name)
|
115
|
+
lbs = @load_balancer_pools_secondary_interface.list(load_balancer_pool_id, {name: name.to_s})[load_balancer_pool_list_key]
|
116
|
+
if lbs.empty?
|
117
|
+
print_red_alert "Load Balancer Pool not found by name #{name}"
|
118
|
+
return nil
|
119
|
+
elsif lbs.size > 1
|
120
|
+
print_red_alert "#{lbs.size} load balancer pools found by name #{name}"
|
121
|
+
#print_lbs_table(lbs, {color: red})
|
122
|
+
print reset,"\n\n"
|
123
|
+
return nil
|
124
|
+
else
|
125
|
+
return lbs[0]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
93
129
|
end
|