morpheus-cli 2.12.5 → 3.1.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +5 -0
  3. data/lib/morpheus/api/api_client.rb +15 -30
  4. data/lib/morpheus/api/app_templates_interface.rb +34 -7
  5. data/lib/morpheus/api/apps_interface.rb +20 -1
  6. data/lib/morpheus/api/archive_buckets_interface.rb +124 -0
  7. data/lib/morpheus/api/archive_files_interface.rb +182 -0
  8. data/lib/morpheus/api/{network_pools_interface.rb → image_builder_boot_scripts_interface.rb} +6 -6
  9. data/lib/morpheus/api/{policies_interface.rb → image_builder_image_builds_interface.rb} +20 -15
  10. data/lib/morpheus/api/image_builder_interface.rb +26 -0
  11. data/lib/morpheus/api/{network_proxies_interface.rb → image_builder_preseed_scripts_interface.rb} +6 -6
  12. data/lib/morpheus/cli.rb +10 -9
  13. data/lib/morpheus/cli/alias_command.rb +10 -9
  14. data/lib/morpheus/cli/app_templates.rb +1566 -457
  15. data/lib/morpheus/cli/apps.rb +284 -108
  16. data/lib/morpheus/cli/archives_command.rb +2184 -0
  17. data/lib/morpheus/cli/boot_scripts_command.rb +382 -0
  18. data/lib/morpheus/cli/cli_command.rb +9 -35
  19. data/lib/morpheus/cli/error_handler.rb +2 -0
  20. data/lib/morpheus/cli/hosts.rb +15 -3
  21. data/lib/morpheus/cli/image_builder_command.rb +1208 -0
  22. data/lib/morpheus/cli/instances.rb +118 -47
  23. data/lib/morpheus/cli/man_command.rb +27 -24
  24. data/lib/morpheus/cli/mixins/print_helper.rb +19 -5
  25. data/lib/morpheus/cli/mixins/provisioning_helper.rb +20 -20
  26. data/lib/morpheus/cli/option_types.rb +45 -14
  27. data/lib/morpheus/cli/preseed_scripts_command.rb +381 -0
  28. data/lib/morpheus/cli/remote.rb +1 -0
  29. data/lib/morpheus/cli/roles.rb +2 -2
  30. data/lib/morpheus/cli/shell.rb +3 -2
  31. data/lib/morpheus/cli/version.rb +1 -1
  32. data/lib/morpheus/ext/hash.rb +22 -0
  33. data/lib/morpheus/formatters.rb +33 -0
  34. data/lib/morpheus/terminal.rb +1 -1
  35. metadata +13 -21
  36. data/lib/morpheus/api/cloud_policies_interface.rb +0 -47
  37. data/lib/morpheus/api/group_policies_interface.rb +0 -47
  38. data/lib/morpheus/api/network_domains_interface.rb +0 -47
  39. data/lib/morpheus/api/network_groups_interface.rb +0 -47
  40. data/lib/morpheus/api/network_pool_servers_interface.rb +0 -47
  41. data/lib/morpheus/api/network_services_interface.rb +0 -47
  42. data/lib/morpheus/api/networks_interface.rb +0 -54
  43. data/lib/morpheus/cli/network_domains_command.rb +0 -571
  44. data/lib/morpheus/cli/network_groups_command.rb +0 -602
  45. data/lib/morpheus/cli/network_pool_servers_command.rb +0 -430
  46. data/lib/morpheus/cli/network_pools_command.rb +0 -495
  47. data/lib/morpheus/cli/network_proxies_command.rb +0 -594
  48. data/lib/morpheus/cli/network_services_command.rb +0 -148
  49. data/lib/morpheus/cli/networks_command.rb +0 -855
  50. data/lib/morpheus/cli/policies_command.rb +0 -847
  51. data/scripts/generate_morpheus_commands_help.morpheus +0 -1313
@@ -218,11 +218,13 @@ module Morpheus::Cli::ProvisioningHelper
218
218
 
219
219
  payload = {
220
220
  'zoneId' => cloud_id,
221
+ # 'siteId' => siteId,
221
222
  'instance' => {
222
223
  'name' => instance_name,
223
224
  'site' => {
224
225
  'id' => group_id
225
226
  },
227
+ 'type' => instance_type_code,
226
228
  'instanceType' => {
227
229
  'code' => instance_type_code
228
230
  }
@@ -263,7 +265,7 @@ module Morpheus::Cli::ProvisioningHelper
263
265
  payload['instance']['layout'] = {'id' => layout['id']}
264
266
 
265
267
  # prompt for service plan
266
- service_plans_json = @instances_interface.service_plans({zoneId: cloud_id, layoutId: layout_id})
268
+ service_plans_json = @instances_interface.service_plans({zoneId: cloud_id, layoutId: layout_id, siteId: group_id})
267
269
  service_plans = service_plans_json["plans"]
268
270
  service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"]} } # already sorted
269
271
  plan_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'servicePlan', 'type' => 'select', 'fieldLabel' => 'Plan', 'selectOptions' => service_plans_dropdown, 'required' => true, 'description' => 'Choose the appropriately sized plan for this instance'}],options[:options])
@@ -289,29 +291,27 @@ module Morpheus::Cli::ProvisioningHelper
289
291
  end
290
292
  end
291
293
 
292
-
294
+ # build option types
295
+ option_type_list = []
293
296
  if !layout['optionTypes'].nil? && !layout['optionTypes'].empty?
294
- type_payload = Morpheus::Cli::OptionTypes.prompt(layout['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
295
- payload.deep_merge!(type_payload)
296
- elsif !instance_type['optionTypes'].nil? && !instance_type['optionTypes'].empty?
297
- type_payload = Morpheus::Cli::OptionTypes.prompt(instance_type['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
298
- payload.deep_merge!(type_payload)
297
+ option_type_list += layout['optionTypes']
298
+ end
299
+ if !instance_type['optionTypes'].nil? && !instance_type['optionTypes'].empty?
300
+ option_type_list += instance_type['optionTypes']
299
301
  end
300
-
301
302
  if !layout['provisionType'].nil? && !layout['provisionType']['optionTypes'].nil? && !layout['provisionType']['optionTypes'].empty?
302
- instance_type_option_types = layout['provisionType']['optionTypes']
303
- # remove volume options if volumes were configured
304
- if !payload['volumes'].empty?
305
- instance_type_option_types = reject_volume_option_types(instance_type_option_types)
306
- end
307
- # remove networkId option if networks were configured above
308
- if !payload['networkInterfaces'].empty?
309
- instance_type_option_types = reject_networking_option_types(instance_type_option_types)
310
- end
311
- #print "#{dark} #=> gathering instance type option types for layout provision type...#{reset}\n" if Morpheus::Logging.debug?
312
- provision_payload = Morpheus::Cli::OptionTypes.prompt(instance_type_option_types,options[:options],api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
313
- payload.deep_merge!(provision_payload)
303
+ option_type_list += layout['provisionType']['optionTypes']
304
+ end
305
+ if !payload['volumes'].empty?
306
+ option_type_list = reject_volume_option_types(option_type_list)
314
307
  end
308
+ # remove networkId option if networks were configured above
309
+ if !payload['networkInterfaces'].empty?
310
+ option_type_list = reject_networking_option_types(option_type_list)
311
+ end
312
+
313
+ instance_config_payload = Morpheus::Cli::OptionTypes.prompt(option_type_list, options[:options], @api_client, {groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
314
+ payload.deep_merge!(instance_config_payload)
315
315
 
316
316
  ## Advanced Options
317
317
 
@@ -194,7 +194,7 @@ module Morpheus
194
194
  value_found = false
195
195
  value = nil
196
196
  while !value_found do
197
- print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
197
+ print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{option_type['defaultValue'] ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
198
198
  input = $stdin.gets.chomp!
199
199
  value = input.empty? ? option_type['defaultValue'] : input
200
200
  value = value.to_s.include?('.') ? value.to_f : value.to_i
@@ -233,7 +233,7 @@ module Morpheus
233
233
  else
234
234
  print Term::ANSIColor.red, "\nInvalid Option #{option_type['fieldLabel']}: [#{use_value}]\n\n", Term::ANSIColor.reset
235
235
  print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] - #{option_type['description']}\n", Term::ANSIColor.reset
236
- display_select_options(select_options)
236
+ display_select_options(opt, select_options)
237
237
  print "\n"
238
238
  exit 1
239
239
  end
@@ -247,7 +247,7 @@ module Morpheus
247
247
  if option_type['required']
248
248
  print Term::ANSIColor.red, "\nMissing Required Option\n\n", Term::ANSIColor.reset
249
249
  print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] - #{option_type['description']}\n", Term::ANSIColor.reset
250
- display_select_options(select_options)
250
+ display_select_options(option_type, select_options)
251
251
  print "\n"
252
252
  exit 1
253
253
  else
@@ -258,8 +258,20 @@ module Morpheus
258
258
  while !value_found do
259
259
  Readline.completion_append_character = ""
260
260
  Readline.basic_word_break_characters = ''
261
- Readline.completion_proc = proc {|s| select_options.clone.collect{|opt| opt['name']}.grep(/^#{Regexp.escape(s)}/)}
262
- input = Readline.readline("#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''} ['?' for options]: ", false).to_s
261
+ Readline.completion_proc = proc {|s|
262
+ matches = []
263
+ available_options = (select_options || [])
264
+ available_options.each{|option|
265
+ if option['name'] && option['name'] =~ /^#{Regexp.escape(s)}/
266
+ matches << option['name']
267
+ # elsif option['id'] && option['id'].to_s =~ /^#{Regexp.escape(s)}/
268
+ elsif option['value'] && option['value'].to_s == s
269
+ matches << option['name']
270
+ end
271
+ }
272
+ matches
273
+ }
274
+ input = Readline.readline("#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{optional_label(option_type)}#{option_type['defaultValue'] ? ' ['+option_type['defaultValue'].to_s+']' : ''} ['?' for options]: ", false).to_s
263
275
  input = input.chomp.strip
264
276
  if input.empty?
265
277
  value = option_type['defaultValue']
@@ -273,7 +285,7 @@ module Morpheus
273
285
  end
274
286
  if input == '?'
275
287
  help_prompt(option_type)
276
- display_select_options(select_options)
288
+ display_select_options(option_type, select_options)
277
289
  elsif !value.nil? || option_type['required'] != true
278
290
  value_found = true
279
291
  end
@@ -323,7 +335,7 @@ module Morpheus
323
335
  value_found = false
324
336
  value = nil
325
337
  while !value_found do
326
- print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
338
+ print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{optional_label(option_type)}#{option_type['defaultValue'] ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
327
339
  input = $stdin.gets.chomp!
328
340
  value = input.empty? ? option_type['defaultValue'] : input
329
341
  if input == '?'
@@ -340,7 +352,7 @@ module Morpheus
340
352
  value = nil
341
353
  while !value_found do
342
354
  if value.nil?
343
- print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''} [Type 'EOF' to stop input]: \n"
355
+ print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{optional_label(option_type)} [Type 'EOF' to stop input]: \n"
344
356
  end
345
357
  input = $stdin.gets.chomp!
346
358
  # value = input.empty? ? option_type['defaultValue'] : input
@@ -361,12 +373,15 @@ module Morpheus
361
373
  def self.password_prompt(option_type)
362
374
  value_found = false
363
375
  while !value_found do
364
- print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}: "
376
+ print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{optional_label(option_type)}#{option_type['defaultValue'] ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
365
377
  input = $stdin.noecho(&:gets).chomp!
366
378
  value = input
367
379
  print "\n"
368
380
  if input == '?'
369
381
  help_prompt(option_type)
382
+ elsif input == "" && option_type['defaultValue'] != nil
383
+ value = option_type['defaultValue'].to_s
384
+ value_found = true
370
385
  elsif !value.empty? || option_type['required'] != true
371
386
  value_found = true
372
387
  end
@@ -378,11 +393,11 @@ module Morpheus
378
393
  value_found = false
379
394
  value = nil
380
395
  while !value_found do
381
- print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
396
+ #print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{optional_label(option_type)}#{option_type['defaultValue'] ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
382
397
  Readline.completion_append_character = ""
383
398
  Readline.basic_word_break_characters = ''
384
399
  Readline.completion_proc = proc {|s| Readline::FILENAME_COMPLETION_PROC.call(s) }
385
- input = Readline.readline("#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''} ['?' for options]: ", false).to_s
400
+ input = Readline.readline("#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{optional_label(option_type)}#{option_type['defaultValue'] ? ' ['+option_type['defaultValue'].to_s+']' : ''} ['?' for options]: ", false).to_s
386
401
  input = input.chomp.strip
387
402
  #input = $stdin.gets.chomp!
388
403
  value = input.empty? ? option_type['defaultValue'] : input.to_s
@@ -409,7 +424,14 @@ module Morpheus
409
424
  end
410
425
 
411
426
  def self.help_prompt(option_type)
412
- print Term::ANSIColor.green," * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] - ", Term::ANSIColor.reset , "#{option_type['description']}\n"
427
+ full_field_name = option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''
428
+ full_field_name << option_type['fieldName'].to_s
429
+ # an attempt at prompting help for natural options without the -O switch
430
+ if option_type[:fmt] == :natural
431
+ print Term::ANSIColor.green," * #{option_type['fieldLabel']} [--#{full_field_name}=] ", Term::ANSIColor.reset , "#{option_type['description']}\n"
432
+ else
433
+ print Term::ANSIColor.green," * #{option_type['fieldLabel']} [-O #{full_field_name}=] - ", Term::ANSIColor.reset , "#{option_type['description']}\n"
434
+ end
413
435
  end
414
436
 
415
437
 
@@ -417,8 +439,9 @@ module Morpheus
417
439
  api_client.options.options_for_source(source,params)['data']
418
440
  end
419
441
 
420
- def self.display_select_options(select_options = [])
421
- puts "\nOptions"
442
+ def self.display_select_options(opt, select_options = [])
443
+ header = opt['fieldLabel'] ? "#{opt['fieldLabel']} Options" : "Options"
444
+ puts "\n#{header}"
422
445
  puts "==============="
423
446
  select_options.each do |option|
424
447
  puts " * #{option['name']} [#{option['value']}]"
@@ -438,6 +461,14 @@ module Morpheus
438
461
  puts self.format_option_types_help(option_types)
439
462
  end
440
463
 
464
+ def self.optional_label(option_type)
465
+ # removing this for now, for the sake of providing less to look at
466
+ if option_type[:fmt] == :natural # || true
467
+ return ""
468
+ else
469
+ return option_type['required'] ? '' : ' (optional)'
470
+ end
471
+ end
441
472
  end
442
473
  end
443
474
  end
@@ -0,0 +1,381 @@
1
+ require 'rest_client'
2
+ require 'optparse'
3
+ require 'filesize'
4
+ require 'table_print'
5
+ require 'morpheus/cli/cli_command'
6
+
7
+ class Morpheus::Cli::PreseedScriptsCommand
8
+ include Morpheus::Cli::CliCommand
9
+
10
+ #set_command_name :'preseed-scripts'
11
+ # lives under image-builder domain right now
12
+ set_command_hidden
13
+ def command_name
14
+ "image-builder preseed-scripts"
15
+ end
16
+
17
+ register_subcommands :list, :get, :add, :update, :remove
18
+
19
+ # set_default_subcommand :list
20
+
21
+ def initialize()
22
+ # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
23
+ end
24
+
25
+ def connect(opts)
26
+ @api_client = establish_remote_appliance_connection(opts)
27
+ @image_builder_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).image_builder
28
+ @preseed_scripts_interface = @image_builder_interface.preseed_scripts
29
+ end
30
+
31
+ def handle(args)
32
+ handle_subcommand(args)
33
+ end
34
+
35
+ def list(args)
36
+ options = {}
37
+ optparse = OptionParser.new do|opts|
38
+ opts.banner = subcommand_usage()
39
+ build_common_options(opts, options, [:list, :json, :dry_run])
40
+ end
41
+ optparse.parse!(args)
42
+ connect(options)
43
+ begin
44
+ params = {}
45
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
46
+ params[k] = options[k] unless options[k].nil?
47
+ end
48
+
49
+ if options[:dry_run]
50
+ print_dry_run @preseed_scripts_interface.dry.list(params)
51
+ return
52
+ end
53
+
54
+ json_response = @preseed_scripts_interface.list(params)
55
+ if options[:json]
56
+ print JSON.pretty_generate(json_response)
57
+ print "\n"
58
+ return
59
+ end
60
+ preseed_scripts = json_response['preseedScripts']
61
+ title = "Morpheus Preseed Scripts"
62
+ subtitles = []
63
+ if params[:phrase]
64
+ subtitles << "Search: #{params[:phrase]}".strip
65
+ end
66
+ print_h1 title, subtitles
67
+ if preseed_scripts.empty?
68
+ print cyan,"No preseed scripts found.",reset,"\n"
69
+ else
70
+ rows = preseed_scripts.collect {|preseed_script|
71
+ row = {
72
+ id: preseed_script['id'],
73
+ name: preseed_script['fileName']
74
+ }
75
+ row
76
+ }
77
+ columns = [:id, :name]
78
+ if options[:include_fields]
79
+ columns = options[:include_fields]
80
+ end
81
+ print cyan
82
+ print as_pretty_table(rows, columns, options)
83
+ print reset
84
+ print_results_pagination(json_response)
85
+ end
86
+ print reset,"\n"
87
+ rescue RestClient::Exception => e
88
+ print_rest_exception(e, options)
89
+ exit 1
90
+ end
91
+ end
92
+
93
+ def get(args)
94
+ options = {}
95
+ optparse = OptionParser.new do|opts|
96
+ opts.banner = subcommand_usage("[preseed-script]")
97
+ build_common_options(opts, options, [:json, :dry_run])
98
+ end
99
+ optparse.parse!(args)
100
+ if args.count < 1
101
+ print_error Morpheus::Terminal.angry_prompt
102
+ puts_error "#{command_name} missing argument: [preseed-script]\n#{optparse}"
103
+ return 1
104
+ end
105
+ connect(options)
106
+ begin
107
+ if options[:dry_run]
108
+ if args[0].to_s =~ /\A\d{1,}\Z/
109
+ print_dry_run @preseed_scripts_interface.dry.get(args[0].to_i)
110
+ else
111
+ print_dry_run @preseed_scripts_interface.dry.list({name:args[0]})
112
+ end
113
+ return
114
+ end
115
+ preseed_script = find_preseed_script_by_name_or_id(args[0])
116
+ return 1 if preseed_script.nil?
117
+ json_response = {'preseedScript' => preseed_script} # skip redundant request
118
+ # json_response = @preseed_scripts_interface.get(preseed_script['id'])
119
+ preseed_script = json_response['preseedScript']
120
+ if options[:json]
121
+ print JSON.pretty_generate(json_response)
122
+ return
123
+ end
124
+ print_h1 "Preseed Script Details"
125
+ print cyan
126
+ description_cols = {
127
+ "ID" => 'id',
128
+ "Name" => 'fileName',
129
+ # "Description" => 'description',
130
+ # "Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
131
+ # "Visibility" => lambda {|it| it['visibility'] ? it['visibility'].capitalize() : 'Private' },
132
+ }
133
+ print_description_list(description_cols, preseed_script)
134
+
135
+ print_h2 "Script"
136
+ print cyan
137
+ puts preseed_script['content']
138
+
139
+ print reset,"\n"
140
+
141
+ rescue RestClient::Exception => e
142
+ print_rest_exception(e, options)
143
+ return 1
144
+ end
145
+ end
146
+
147
+ def add(args)
148
+ options = {}
149
+ optparse = OptionParser.new do|opts|
150
+ opts.banner = subcommand_usage("[fileName]")
151
+ build_option_type_options(opts, options, add_preseed_script_option_types(false))
152
+ build_common_options(opts, options, [:options, :json, :dry_run, :quiet])
153
+ end
154
+ optparse.parse!(args)
155
+ connect(options)
156
+ begin
157
+ options[:options] ||= {}
158
+ # support [preseed-script] as first argument still
159
+ if args[0]
160
+ options[:options]['fileName'] = args[0]
161
+ end
162
+
163
+ payload = {
164
+ 'preseedScript' => {}
165
+ }
166
+ # prompt for Script Content unless --file is passed.
167
+ my_options = add_preseed_script_option_types()
168
+ if options[:options]['file']
169
+ my_options = my_options.reject {|it| it['fieldName'] == 'content' }
170
+ # elsif options[:options]['content']
171
+ # my_options = my_options.reject {|it| it['fieldName'] == 'file' }
172
+ else
173
+ my_options = my_options.reject {|it| it['fieldName'] == 'file' }
174
+ end
175
+ params = Morpheus::Cli::OptionTypes.prompt(my_options, options[:options], @api_client, options[:params])
176
+ script_file = params.delete('file')
177
+ if script_file
178
+ if !File.exists?(script_file)
179
+ print_red_alert "File not found: #{script_file}"
180
+ return 1
181
+ end
182
+ payload['preseedScript']['content'] = File.read(script_file)
183
+ end
184
+ payload['preseedScript'].merge!(params)
185
+ if options[:dry_run]
186
+ print_dry_run @preseed_scripts_interface.dry.create(payload)
187
+ return
188
+ end
189
+ json_response = @preseed_scripts_interface.create(payload)
190
+ if options[:json]
191
+ print JSON.pretty_generate(json_response)
192
+ print "\n"
193
+ elsif !options[:quiet]
194
+ print_green_success "Added image build #{payload['preseedScript']['fileName']}"
195
+ # list([])
196
+ preseed_script = json_response['preseedScript']
197
+ get([preseed_script['id']])
198
+ end
199
+
200
+ rescue RestClient::Exception => e
201
+ print_rest_exception(e, options)
202
+ exit 1
203
+ end
204
+ end
205
+
206
+ def update(args)
207
+ options = {}
208
+ optparse = OptionParser.new do|opts|
209
+ opts.banner = subcommand_usage("[preseed-script] [options]")
210
+ build_option_type_options(opts, options, update_preseed_script_option_types(false))
211
+ build_common_options(opts, options, [:options, :json, :dry_run])
212
+ end
213
+ optparse.parse!(args)
214
+ if args.count < 1
215
+ puts optparse
216
+ return 1
217
+ end
218
+ connect(options)
219
+
220
+ begin
221
+ preseed_script = find_preseed_script_by_name_or_id(args[0])
222
+
223
+ payload = {
224
+ 'preseedScript' => {id: preseed_script["id"]}
225
+ }
226
+
227
+ params = options[:options] || {}
228
+ #puts "parsed params is : #{params.inspect}"
229
+ params = params.select {|k,v| params[k].to_s != "" }
230
+ if params.empty?
231
+ print_red_alert "Specify atleast one option to update"
232
+ puts optparse
233
+ return 1
234
+ end
235
+
236
+ # prompt for Script Content unless --file is passed.
237
+ # my_options = add_preseed_script_option_types()
238
+ # if options[:options]['file']
239
+ # my_options = my_options.reject {|it| it['fieldName'] == 'content' }
240
+ # # elsif options[:options]['content']
241
+ # # my_options = my_options.reject {|it| it['fieldName'] == 'file' }
242
+ # else
243
+ # my_options = my_options.reject {|it| it['fieldName'] == 'file' }
244
+ # end
245
+ # params = Morpheus::Cli::OptionTypes.prompt(my_options, options[:options], @api_client, options[:params])
246
+ script_file = params.delete('file')
247
+ if script_file
248
+ if !File.exists?(script_file)
249
+ print_red_alert "File not found: #{script_file}"
250
+ return 1
251
+ end
252
+ payload['preseedScript']['content'] = File.read(script_file)
253
+ end
254
+ payload['preseedScript'].merge!(params)
255
+
256
+ if options[:dry_run]
257
+ print_dry_run @preseed_scripts_interface.dry.update(preseed_script["id"], payload)
258
+ return
259
+ end
260
+
261
+ json_response = @preseed_scripts_interface.update(preseed_script["id"], payload)
262
+ if options[:json]
263
+ print JSON.pretty_generate(json_response)
264
+ print "\n"
265
+ else
266
+ print_green_success "Updated preseed script #{preseed_script['fileName']}"
267
+ get([preseed_script['id']])
268
+ end
269
+ return 0
270
+ rescue RestClient::Exception => e
271
+ print_rest_exception(e, options)
272
+ return 1
273
+ end
274
+ end
275
+
276
+ def remove(args)
277
+ options = {}
278
+ optparse = OptionParser.new do|opts|
279
+ opts.banner = subcommand_usage("[preseed-script]")
280
+ build_common_options(opts, options, [:account, :auto_confirm, :json, :dry_run])
281
+ end
282
+ optparse.parse!(args)
283
+
284
+ if args.count < 1
285
+ print_error Morpheus::Terminal.angry_prompt
286
+ puts_error "#{command_name} missing argument: [preseed-script]\n#{optparse}"
287
+ return 1
288
+ end
289
+
290
+ connect(options)
291
+ begin
292
+ preseed_script = find_preseed_script_by_name_or_id(args[0])
293
+ return 1 if preseed_script.nil?
294
+
295
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the preseed script: #{preseed_script['fileName']}?")
296
+ return 9, "aborted command"
297
+ end
298
+ if options[:dry_run]
299
+ print_dry_run @preseed_scripts_interface.dry.destroy(preseed_script['id'])
300
+ return 0
301
+ end
302
+ json_response = @preseed_scripts_interface.destroy(preseed_script['id'])
303
+ if options[:json]
304
+ print JSON.pretty_generate(json_response)
305
+ print "\n"
306
+ else
307
+ print_green_success "Removed preseed script #{preseed_script['fileName']}"
308
+ # list([])
309
+ end
310
+ return 0
311
+ rescue RestClient::Exception => e
312
+ print_rest_exception(e, options)
313
+ return 1
314
+ end
315
+ end
316
+
317
+ private
318
+
319
+ def get_available_preseed_script_types()
320
+ [{'name' => 'VMware', 'value' => 'vmware'}]
321
+ end
322
+
323
+ def add_preseed_script_option_types(connected=true)
324
+ [
325
+ {'fieldName' => 'fileName', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Enter a name for this script.'},
326
+ # {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false},
327
+ {'fieldName' => 'file', 'fieldLabel' => 'Script File', 'type' => 'file', 'required' => false, 'description' => 'Set script contents to that of a local file.'},
328
+ {'fieldName' => 'content', 'fieldLabel' => 'Script', 'type' => 'code-editor', 'required' => true},
329
+ ]
330
+ end
331
+
332
+ def update_preseed_script_option_types(connected=true)
333
+ list = add_preseed_script_option_types(connected)
334
+ # list = list.reject {|it| ["group"].include? it['fieldName'] }
335
+ list.each {|it| it['required'] = false }
336
+ list
337
+ end
338
+
339
+ def find_preseed_script_by_name_or_id(val)
340
+ if val.to_s =~ /\A\d{1,}\Z/
341
+ return find_preseed_script_by_id(val)
342
+ else
343
+ return find_preseed_script_by_name(val)
344
+ end
345
+ end
346
+
347
+ def find_preseed_script_by_id(id)
348
+ begin
349
+ json_response = @preseed_scripts_interface.get(id.to_i)
350
+ return json_response['preseedScript']
351
+ rescue RestClient::Exception => e
352
+ if e.response && e.response.code == 404
353
+ print_red_alert "Preseed Script not found by id #{id}"
354
+ return nil
355
+ else
356
+ raise e
357
+ end
358
+ end
359
+ end
360
+
361
+ def find_preseed_script_by_name(name)
362
+ preseed_scripts = @preseed_scripts_interface.list({name: name.to_s})['preseedScripts']
363
+ if preseed_scripts.empty?
364
+ print_red_alert "Preseed Script not found by name #{name}"
365
+ return nil
366
+ elsif preseed_scripts.size > 1
367
+ print_red_alert "#{preseed_scripts.size} preseed scripts found by name #{name}"
368
+ # print_preseed_scripts_table(preseed_scripts, {color: red})
369
+ rows = preseed_scripts.collect do |preseed_script|
370
+ {id: it['id'], name: it['fileName']}
371
+ end
372
+ print red
373
+ tp rows, [:id, :name]
374
+ print reset,"\n"
375
+ return nil
376
+ else
377
+ return preseed_scripts[0]
378
+ end
379
+ end
380
+
381
+ end