morpheus-cli 6.0.0 → 6.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd7f59f72f0bc788526827effe2023844d0a99eb3485b27f276b296d604b00e0
4
- data.tar.gz: f10d8bd99db70dc0399475e5df17d93eab19b6ed45748a6edefcfb9fd5f5b945
3
+ metadata.gz: eb39926e3f31b77cdca9175335ca0260b720641e469a240618fc98816b2b98ee
4
+ data.tar.gz: ef40d39ffa3f4a6d51139524fee83dd990b082c326b528ad66a6a8e6629c43e0
5
5
  SHA512:
6
- metadata.gz: fd82a4e9ff23ba92dd577667e28258b4cf04d1ee147210b6553cbda7e56c1aea5313a8f2c25a4703f7e67d3dfdeefcb3ca811fd9cd9037c6980062f8ee40475e
7
- data.tar.gz: c0ffcee9b0a774ffcb0df995b1fbd5247ea6fcc4dad3f1d2fa7ab3ceff6e9a4e89faf29e87a65c335a3eab6db2bce1368b60ef0453ed8fbe1e18f77186767154
6
+ metadata.gz: 32d58f65d940360fdfb48ff00f88d7f2221dbe4ad1d50adbd441ee68ae79cf7fb5e1314b7d1644808a8795fa362b0e0698e0d89ef8f57187442880fc1a0fec40
7
+ data.tar.gz: 19f7a173551371d306edbbbde91ad910f96c5c77fe8c70ef09200ba85e50885e4533cfb36c1f6c26b3cacacb629d7459aabb569f03e71d07e0a5720e3134fc9c
data/Dockerfile CHANGED
@@ -1,5 +1,5 @@
1
1
  FROM ruby:2.7.5
2
2
 
3
- RUN gem install morpheus-cli -v 6.0.0
3
+ RUN gem install morpheus-cli -v 6.0.2
4
4
 
5
5
  ENTRYPOINT ["morpheus"]
@@ -43,10 +43,10 @@ class Morpheus::JobsInterface < Morpheus::APIClient
43
43
  execute(method: :delete, url: url, headers: headers)
44
44
  end
45
45
 
46
- def execute_job(id, params={})
46
+ def execute_job(id, payload={}, params={})
47
47
  url = "#{base_path}/#{id}/execute"
48
48
  headers = { params: params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
49
- execute(method: :put, url: url, headers: headers)
49
+ execute(method: :put, url: url, headers: headers, payload: payload.to_json)
50
50
  end
51
51
 
52
52
  =begin
@@ -23,6 +23,22 @@ class Morpheus::NetworkServicesInterface < Morpheus::APIClient
23
23
  execute(method: :get, url: url, headers: headers)
24
24
  end
25
25
 
26
+ def get_server(server_id)
27
+ execute(method: :get, url: "#{@base_url}/api/networks/servers/#{server_id}", params: {}, headers: {})
28
+ end
29
+
30
+ def list_servers()
31
+ execute(method: :get, url: "#{@base_url}/api/networks/servers", params: {}, headers: {})
32
+ end
33
+
34
+ def refresh(server_id)
35
+ url = "#{@base_url}/api/networks/servers/#{server_id}/refresh"
36
+
37
+ headers = { :params => {}, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
38
+ opts = {method: :post, url: url, headers: headers}
39
+ execute(opts)
40
+ end
41
+
26
42
  # def create(payload)
27
43
  # url = "#{@base_url}/api/networks/services"
28
44
  # headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
@@ -1020,7 +1020,7 @@ EOT
1020
1020
  end
1021
1021
 
1022
1022
  def apply(args)
1023
- default_refresh_interval = 10
1023
+ default_refresh_interval = 5
1024
1024
  params, payload, options = {}, {}, {}
1025
1025
  optparse = Morpheus::Cli::OptionParser.new do |opts|
1026
1026
  opts.banner = subcommand_usage("[app] [options]")
@@ -716,6 +716,7 @@ EOT
716
716
  # "Content" => lambda {|it| it['content'] },
717
717
  "Enabled" => lambda {|it| format_boolean(it['enabled']) },
718
718
  "Featured" => lambda {|it| format_boolean(it['featured']) },
719
+ "Allow Quantity" => lambda {|it| format_boolean(it['allowQuantity']) },
719
720
  #"Config" => lambda {|it| it['config'] },
720
721
  "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
721
722
  "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
@@ -757,19 +758,20 @@ EOT
757
758
  {'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 4},
758
759
  {'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'defaultValue' => true, 'displayOrder' => 5},
759
760
  {'fieldName' => 'featured', 'fieldLabel' => 'Featured', 'type' => 'checkbox', 'defaultValue' => false, 'displayOrder' => 6},
760
- {'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'}, {'name' => 'Public', 'value' => 'public'}], 'defaultValue' => 'private', 'required' => true, 'displayOrder' => 7},
761
- {'fieldName' => 'layoutCode', 'fieldLabel' => 'Layout Code', 'type' => 'text', 'required' => false, 'displayOrder' => 8},
762
- {'fieldName' => 'iconPath', 'fieldLabel' => 'Logo', 'type' => 'select', 'optionSource' => 'iconList', 'displayOrder' => 9},
761
+ {'fieldName' => 'allowQuantity', 'fieldLabel' => 'Allow Quantity', 'type' => 'checkbox', 'defaultValue' => false, 'displayOrder' => 7},
762
+ {'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'}, {'name' => 'Public', 'value' => 'public'}], 'defaultValue' => 'private', 'required' => true, 'displayOrder' => 8},
763
+ {'fieldName' => 'layoutCode', 'fieldLabel' => 'Layout Code', 'type' => 'text', 'required' => false, 'displayOrder' => 9},
764
+ {'fieldName' => 'iconPath', 'fieldLabel' => 'Logo', 'type' => 'select', 'optionSource' => 'iconList', 'displayOrder' => 10},
763
765
  #{'fieldName' => 'optionTypes', 'fieldLabel' => 'Option Types', 'type' => 'text', 'description' => 'Option Types to include, comma separated list of names or IDs.', 'displayOrder' => 8},
764
- {'dependsOnCode' => 'catalogItemType.type:instance', 'fieldName' => 'config', 'fieldLabel' => 'Config', 'type' => 'code-editor', 'description' => 'JSON or YAML', 'required' => true, 'displayOrder' => 10},
765
- {'dependsOnCode' => 'catalogItemType.type:workflow', 'fieldName' => 'workflowConfig', 'fieldLabel' => 'Config', 'type' => 'textarea', 'description' => 'Enter configuration for the Workflow', 'required' => false, 'noParse' => true, 'displayOrder' => 10},
766
- {'dependsOnCode' => 'catalogItemType.type:blueprint', 'fieldName' => 'blueprint', 'fieldLabel' => 'Blueprint', 'type' => 'select', 'optionSource' => 'blueprints', 'description' => 'Choose a blueprint to apply to the catalog item.', 'required' => true, 'noParams' => true, 'displayOrder' => 11},
767
- {'dependsOnCode' => 'catalogItemType.type:blueprint', 'fieldName' => 'appSpec', 'fieldLabel' => 'App Spec', 'type' => 'code-editor', 'description' => 'Enter a spec in the for the App, the Scribe YAML format', 'required' => true, 'displayOrder' => 12},
768
- {'dependsOnCode' => 'catalogItemType.type:workflow', 'fieldName' => 'workflow', 'fieldLabel' => 'Workflow', 'type' => 'select', 'optionSource' => 'operationWorkflows', 'description' => 'Enter a spec in the for the App, the Scribe YAML format', 'required' => true, 'noParams' => true, 'displayOrder' => 13},
766
+ {'dependsOnCode' => 'catalogItemType.type:instance', 'fieldName' => 'config', 'fieldLabel' => 'Config', 'type' => 'code-editor', 'description' => 'JSON or YAML', 'required' => true, 'displayOrder' => 11},
767
+ {'dependsOnCode' => 'catalogItemType.type:workflow', 'fieldName' => 'workflowConfig', 'fieldLabel' => 'Config', 'type' => 'textarea', 'description' => 'Enter configuration for the Workflow', 'required' => false, 'noParse' => true, 'displayOrder' => 11},
768
+ {'dependsOnCode' => 'catalogItemType.type:blueprint', 'fieldName' => 'blueprint', 'fieldLabel' => 'Blueprint', 'type' => 'select', 'optionSource' => 'blueprints', 'description' => 'Choose a blueprint to apply to the catalog item.', 'required' => true, 'noParams' => true, 'displayOrder' => 12},
769
+ {'dependsOnCode' => 'catalogItemType.type:blueprint', 'fieldName' => 'appSpec', 'fieldLabel' => 'App Spec', 'type' => 'code-editor', 'description' => 'Enter a spec in the for the App, the Scribe YAML format', 'required' => true, 'displayOrder' => 13},
770
+ {'dependsOnCode' => 'catalogItemType.type:workflow', 'fieldName' => 'workflow', 'fieldLabel' => 'Workflow', 'type' => 'select', 'optionSource' => 'operationWorkflows', 'description' => 'Enter a spec in the for the App, the Scribe YAML format', 'required' => true, 'noParams' => true, 'displayOrder' => 14},
769
771
  {'dependsOnCode' => 'catalogItemType.type:workflow', 'fieldName' => 'context', 'fieldLabel' => 'Context Type', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
770
772
  [{'name' => "Select", 'value' => ""}, {'name' => "None", 'value' => "appliance"}, {'name' => "Instance", 'value' => "instance"}, {'name' => "Server", 'value' => "server"}]
771
773
  }, 'description' => 'Context for operational workflow, determines target type', 'defaultValue' => 'Select', 'required' => false},
772
- {'fieldName' => 'content', 'fieldLabel' => 'Content', 'type' => 'code-editor', 'description' => 'Wiki Page Content describing the catalog item', 'displayOrder' => 14}
774
+ {'fieldName' => 'content', 'fieldLabel' => 'Content', 'type' => 'code-editor', 'description' => 'Wiki Page Content describing the catalog item', 'displayOrder' => 15}
773
775
  ]
774
776
  end
775
777
 
@@ -27,7 +27,11 @@ class Morpheus::Cli::CurlCommand
27
27
  curl_method = "DELETE"
28
28
  end
29
29
  opts.on( '--data DATA', String, "HTTP request body for use with POST and PUT, typically JSON." ) do |val|
30
- curl_data = val
30
+ begin
31
+ options[:payload] = JSON.parse(val.to_s)
32
+ rescue => ex
33
+ raise ::OptionParser::InvalidOption.new("Failed to parse payload as JSON. Error: #{ex.message}")
34
+ end
31
35
  end
32
36
  opts.on('--absolute', "Absolute path, value can be used to prevent automatic using the automatic /api/ path prefix to the path by default.") do
33
37
  options[:absolute_path] = true
@@ -4946,7 +4946,7 @@ EOT
4946
4946
  end
4947
4947
 
4948
4948
  def apply(args)
4949
- default_refresh_interval = 10
4949
+ default_refresh_interval = 5
4950
4950
  params, payload, options = {}, {}, {}
4951
4951
  optparse = Morpheus::Cli::OptionParser.new do |opts|
4952
4952
  opts.banner = subcommand_usage("[instance] [options]")
@@ -350,7 +350,7 @@ class Morpheus::Cli::InvoicesCommand
350
350
  if cost_rows.sum { |it| it[:extra].to_f } == 0
351
351
  cost_columns.delete("Extra".upcase)
352
352
  end
353
- print as_pretty_table(cost_rows, cost_columns, options)
353
+ print as_pretty_table(cost_rows, cost_columns, options.merge(include_fields: nil))
354
354
  else
355
355
  print "\n"
356
356
  print yellow, "No invoice totals data", reset, "\n"
@@ -280,17 +280,37 @@ class Morpheus::Cli::JobsCommand
280
280
  end
281
281
  options[:type] = 'morpheus.securityScan'
282
282
  end
283
- opts.on('--context-type [TYPE]', String, "Context type (instance|server|none). Default is none") do |val|
283
+ opts.on('--context-type [TYPE]', String, "Context type (instance|instance-label|server|server-label|none). Default is none") do |val|
284
+ val = val.to_s.downcase
284
285
  params['targetType'] = (val == 'none' ? 'appliance' : val)
285
286
  end
287
+ opts.on('--target-type [TYPE]', String, "alias for --context-type") do |val|
288
+ val = val.to_s.downcase
289
+ params['targetType'] = (val == 'none' ? 'appliance' : val)
290
+ end
291
+ opts.add_hidden_option('--target-type')
286
292
  opts.on('--instances [LIST]', Array, "Context instances(s), comma separated list of instance IDs. Incompatible with --servers") do |list|
287
293
  params['targetType'] = 'instance'
288
294
  params['targets'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq.collect {|it| {'refId' => it.to_i}}
289
295
  end
296
+ opts.on('--instance-label LABEL', String, "Instance Label") do |val|
297
+ if params['targetType'] && params['targetType'] != 'instance-label'
298
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{params['targetType']})")
299
+ end
300
+ params['targetType'] = 'instance-label'
301
+ params['instanceLabel'] = val
302
+ end
290
303
  opts.on('--servers [LIST]', Array, "Context server(s), comma separated list of server IDs. Incompatible with --instances") do |list|
291
304
  params['targetType'] = 'server'
292
305
  params['targets'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq.collect {|it| {'refId' => it.to_i}}
293
306
  end
307
+ opts.on('--server-label LABEL', String, "Server Label") do |val|
308
+ if params['targetType'] && params['targetType'] != 'server-label'
309
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{params['targetType']})")
310
+ end
311
+ params['targetType'] = 'server-label'
312
+ params['serverLabel'] = val
313
+ end
294
314
  opts.on('-S', '--schedule [SCHEDULE]', String, "Job execution schedule type name or ID") do |val|
295
315
  options[:schedule] = val
296
316
  end
@@ -465,8 +485,15 @@ class Morpheus::Cli::JobsCommand
465
485
  end
466
486
  end
467
487
  params['targets'] = targets.collect {|it| {'refId' => it}}
488
+ elsif params['targetType'] == 'instance-label'
489
+ if params['instanceLabel'].nil?
490
+ params['instanceLabel'] = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instance-label', 'fieldName' => 'instanceLabel', 'fieldLabel' => 'Instance Label', 'type' => 'text', 'required' => true, 'description' => 'Instance Label'}], options[:options], @api_client)['instanceLabel']
491
+ end
492
+ elsif params['targetType'] == 'server-label'
493
+ if params['serverLabel'].nil?
494
+ params['serverLabel'] = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'server-label', 'fieldName' => 'serverLabel', 'fieldLabel' => 'Server Label', 'type' => 'text', 'required' => true, 'description' => 'Server Label'}], options[:options], @api_client)['serverLabel']
495
+ end
468
496
  end
469
-
470
497
  # schedule
471
498
  if options[:schedule].nil?
472
499
  options[:schedule] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'scheduleMode', 'fieldLabel' => "Schedule", 'type' => 'select', 'required' => true, 'selectOptions' => job_options['schedules'], 'defaultValue' => job_options['schedules'].first['name']}], options[:options], @api_client, {})['scheduleMode']
@@ -554,17 +581,37 @@ class Morpheus::Cli::JobsCommand
554
581
  options[:security_package] = val
555
582
  end
556
583
  end
557
- opts.on('--context-type [TYPE]', String, "Context type (instance|server|none). Default is none") do |val|
584
+ opts.on('--context-type [TYPE]', String, "Context type (instance|instance-label|server|server-label|none). Default is none") do |val|
585
+ val = val.to_s.downcase
586
+ params['targetType'] = (val == 'none' ? 'appliance' : val)
587
+ end
588
+ opts.on('--target-type [TYPE]', String, "alias for --context-type") do |val|
589
+ val = val.to_s.downcase
558
590
  params['targetType'] = (val == 'none' ? 'appliance' : val)
559
591
  end
592
+ opts.add_hidden_option('--target-type')
560
593
  opts.on('--instances [LIST]', Array, "Context instances(s), comma separated list of instance IDs. Incompatible with --servers") do |list|
561
594
  params['targetType'] = 'instance'
562
595
  options[:targets] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip.to_i }.compact.uniq.collect {|it| {'refId' => it.to_i}}
563
596
  end
597
+ opts.on('--instance-label LABEL', String, "Instance Label") do |val|
598
+ if params['targetType'] && params['targetType'] != 'instance-label'
599
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{params['targetType']})")
600
+ end
601
+ params['targetType'] = 'instance-label'
602
+ params['instanceLabel'] = val
603
+ end
564
604
  opts.on('--servers [LIST]', Array, "Context server(s), comma separated list of server IDs. Incompatible with --instances") do |list|
565
605
  params['targetType'] = 'server'
566
606
  options[:targets] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip.to_i }.compact.uniq.collect {|it| {'refId' => it.to_i}}
567
607
  end
608
+ opts.on('--server-label LABEL', String, "Server Label") do |val|
609
+ if params['targetType'] && params['targetType'] != 'server-label'
610
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{params['targetType']})")
611
+ end
612
+ params['targetType'] = 'server-label'
613
+ params['serverLabel'] = val
614
+ end
568
615
  opts.on('--schedule [SCHEDULE]', String, "Job execution schedule type name or ID") do |val|
569
616
  options[:schedule] = val
570
617
  end
@@ -24,6 +24,9 @@ class Morpheus::Cli::LoadBalancers
24
24
  render_response(json_response, options, rest_object_key) do
25
25
  record = json_response[rest_object_key]
26
26
  options[:exclude_username] = record['username'].nil?
27
+ options[:exclude_owner] = record['owner'].nil?
28
+ options[:exclude_tenants] = record['tenants'].nil? || record['tenants'].empty?
29
+ options[:exclude_permissions] = record['resourcePermission'].nil?
27
30
  print_h1 rest_label, [], options
28
31
  print cyan
29
32
  print_description_list(rest_column_definitions(options), record, options)
@@ -125,6 +128,8 @@ EOT
125
128
  "Provider ID" => 'externalId'
126
129
  }
127
130
  columns.merge!({"Username" => 'username'}) if !options[:exclude_username]
131
+ columns.merge!({"Owner" => lambda { |it| it['owner']['name'] rescue '' }}) if !options[:exclude_owner]
132
+ columns.merge!({"Tenants" => lambda { |it| it['tenants'].collect {|tenant| tenant['name']}.join(', ') rescue '' }}) if !options[:exclude_tenants]
128
133
  columns.merge({
129
134
  "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
130
135
  "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
@@ -7,7 +7,7 @@ class Morpheus::Cli::NetworkServicesCommand
7
7
  set_command_name :'network-services'
8
8
 
9
9
  # register_subcommands :list, :get, :add, :update, :remove
10
- register_subcommands :list
10
+ register_subcommands :list, :refresh
11
11
 
12
12
  # set_default_subcommand :list
13
13
 
@@ -90,6 +90,43 @@ class Morpheus::Cli::NetworkServicesCommand
90
90
  exit 1
91
91
  end
92
92
  end
93
+
94
+ def refresh(args)
95
+ options = {}
96
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
97
+ opts.banner = subcommand_usage("[name]")
98
+ build_common_options(opts, options, [:auto_confirm, :quiet, :json, :dry_run, :remote])
99
+ opts.footer = "Refresh a network integration/server.\n" +
100
+ "[name] is required. This is the name or id of a network server/integration."
101
+ end
102
+ optparse.parse!(args)
103
+ if args.count < 1
104
+ puts optparse
105
+ exit 1
106
+ end
107
+ connect(options)
108
+ begin
109
+ server = find_network_server_by_name_or_id(args[0])
110
+ if !server
111
+ exit 1
112
+ end
113
+ @network_services_interface.setopts(options)
114
+ if options[:dry_run]
115
+ print_dry_run @network_services_interface.dry.refresh(server['id'])
116
+ return
117
+ end
118
+ json_response = @network_services_interface.refresh(server['id'])
119
+ if options[:json]
120
+ print JSON.pretty_generate(json_response)
121
+ print "\n"
122
+ elsif !options[:quiet]
123
+ print_green_success "Refreshing #{server["name"]}"
124
+ end
125
+ rescue RestClient::Exception => e
126
+ print_rest_exception(e, options)
127
+ exit 1
128
+ end
129
+ end
93
130
 
94
131
 
95
132
  private
@@ -136,4 +173,26 @@ class Morpheus::Cli::NetworkServicesCommand
136
173
  end
137
174
  end
138
175
 
176
+ def find_network_server_by_name_or_id(val)
177
+ if val.to_s =~ /\A\d{1,}\Z/
178
+ return find_network_server_by_id(val)
179
+ else
180
+ return find_network_service_by_name(val)
181
+ end
182
+ end
183
+
184
+ def find_network_server_by_id(id)
185
+ begin
186
+ json_response = @network_services_interface.get_server(id.to_i)
187
+ return json_response['networkServer']
188
+ rescue RestClient::Exception => e
189
+ if e.response && e.response.code == 404
190
+ print_red_alert "Network Service not found by id #{id}"
191
+ return nil
192
+ else
193
+ raise e
194
+ end
195
+ end
196
+ end
197
+
139
198
  end
@@ -594,11 +594,15 @@ EOT
594
594
  type_id = nil
595
595
  workflow_context = nil
596
596
  workflow_target = nil
597
+ quantity = nil
597
598
  optparse = Morpheus::Cli::OptionParser.new do |opts|
598
599
  opts.banner = subcommand_usage("[type] [options]")
599
600
  opts.on('-t', '--type TYPE', String, "Catalog Item Type Name or ID") do |val|
600
601
  type_id = val.to_s
601
602
  end
603
+ opts.on('--quantity QUANTITY', String, "Quantity for this catalog item. Will be overridden to 1 if quantity not allowed.") do |val|
604
+ quantity = val.to_s
605
+ end
602
606
  opts.on('--validate','--validate', "Validate Only. Validates the configuration and skips adding the item.") do
603
607
  options[:validate_only] = true
604
608
  end
@@ -648,6 +652,16 @@ EOT
648
652
  payload[add_item_object_key]['type'] = {'name' => catalog_item_type['name']}
649
653
  #payload[add_item_object_key]['type'] = {'id' => catalog_item_type['id']}
650
654
 
655
+ if quantity
656
+ payload[add_item_object_key].deep_merge!({'quantity' => quantity})
657
+ else
658
+ if catalog_item_type['allowQuantity']
659
+ quantity_option_type = {'fieldName' => 'quantity', 'fieldLabel' => 'Quantity', 'type' => 'number', 'defaultValue' => 1, 'required' => true, 'displayOrder' => 1}
660
+ quantity_prompt = Morpheus::Cli::OptionTypes.prompt( [quantity_option_type], options[:options], @api_client, options[:params])['quantity']
661
+ payload[add_item_object_key].deep_merge!({'quantity' => quantity_prompt})
662
+ end
663
+ end
664
+
651
665
  # this is silly, need to load by id to get optionTypes
652
666
  # maybe do ?name=foo&includeOptionTypes=true
653
667
  if catalog_item_type['optionTypes'].nil?
@@ -926,11 +940,15 @@ EOT
926
940
  type_id = nil
927
941
  workflow_context = nil
928
942
  workflow_target = nil
943
+ quantity = nil
929
944
  optparse = Morpheus::Cli::OptionParser.new do |opts|
930
945
  opts.banner = subcommand_usage("[type] [options]")
931
946
  opts.on('-t', '--type TYPE', String, "Catalog Item Type Name or ID") do |val|
932
947
  type_id = val.to_s
933
948
  end
949
+ opts.on('--quantity QUANTITY', String, "Quantity for this catalog item. Will be overridden to 1 if quantity not allowed.") do |val|
950
+ quantity = val.to_s
951
+ end
934
952
  opts.on('--validate','--validate', "Validate Only. Validates the configuration and skips creating the order.") do
935
953
  options[:validate_only] = true
936
954
  end
@@ -991,6 +1009,17 @@ EOT
991
1009
  item_payload['type'] = {'name' => catalog_item_type['name']}
992
1010
  #payload[add_item_object_key]['type'] = {'id' => catalog_item_type['id']}
993
1011
 
1012
+ if quantity
1013
+ item_payload.deep_merge!({'quantity' => quantity})
1014
+ else
1015
+ if catalog_item_type['allowQuantity']
1016
+ quantity_option_type = {'fieldName' => 'quantity', 'fieldLabel' => 'Quantity', 'type' => 'number', 'defaultValue' => 1, 'required' => true, 'displayOrder' => 1}
1017
+ quantity_prompt = Morpheus::Cli::OptionTypes.prompt( [quantity_option_type], options[:options], @api_client, options[:params])['quantity']
1018
+ item_payload.deep_merge!({'quantity' => quantity_prompt})
1019
+ end
1020
+ end
1021
+
1022
+
994
1023
  # this is silly, need to load by id to get optionTypes
995
1024
  # maybe do ?name=foo&includeOptionTypes=true
996
1025
  if catalog_item_type['optionTypes'].nil?
@@ -1200,6 +1229,7 @@ EOT
1200
1229
  # "Blueprint" => lambda {|it| it['blueprint'] ? it['blueprint']['name'] : nil },
1201
1230
  # "Enabled" => lambda {|it| format_boolean(it['enabled']) },
1202
1231
  "Featured" => lambda {|it| format_boolean(it['featured']) },
1232
+ "Allow Quantity" => lambda {|it| format_boolean(it['allowQuantity']) },
1203
1233
  #"Config" => lambda {|it| it['config'] },
1204
1234
  # "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
1205
1235
  # "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
@@ -1408,7 +1438,7 @@ EOT
1408
1438
  {"ID" => lambda {|it| it['id'] } },
1409
1439
  #{"NAME" => lambda {|it| it['name'] } },
1410
1440
  {"Type" => lambda {|it| it['type']['name'] rescue '' } },
1411
- #{"Qty" => lambda {|it| it['quantity'] } },
1441
+ {"Qty" => lambda {|it| it['quantity'] } },
1412
1442
  {"Price" => lambda {|it| it['price'] ? format_money(it['price'] , it['currency'], {sigdig:options[:sigdig] || default_sigdig}) : "No pricing configured" } },
1413
1443
  {"Status" => lambda {|it|
1414
1444
  status_string = format_catalog_item_status(it)
@@ -1438,7 +1468,7 @@ EOT
1438
1468
  {"ID" => lambda {|it| it['id'] } },
1439
1469
  #{"NAME" => lambda {|it| it['name'] } },
1440
1470
  {"TYPE" => lambda {|it| it['type']['name'] rescue '' } },
1441
- #{"QTY" => lambda {|it| it['quantity'] } },
1471
+ {"QTY" => lambda {|it| it['quantity'] } },
1442
1472
  {"PRICE" => lambda {|it| it['price'] ? format_money(it['price'] , it['currency'], {sigdig:options[:sigdig] || default_sigdig}) : "No pricing configured" } },
1443
1473
  {"STATUS" => lambda {|it|
1444
1474
  status_string = format_catalog_item_status(it)
@@ -171,13 +171,21 @@ class Morpheus::Cli::ServicePlanCommand
171
171
  ranges = (service_plan['config'] ? service_plan['config']['ranges'] : nil) || {}
172
172
 
173
173
  if (ranges['minStorage'] && ranges['minStorage'] != '') || (ranges['maxStorage'] && ranges['maxStorage'] != '')
174
- description_cols['Custom Storage Range'] = lambda {|it|
174
+ description_cols['Custom Total Storage Range'] = lambda {|it|
175
175
  get_range(
176
176
  ranges['minStorage'] && ranges['minStorage'] != '' ? "#{ranges['minStorage']} #{(it['config'] && it['config']['storageSizeType'] ? it['config']['storageSizeType'] : 'GB').upcase}" : nil,
177
177
  ranges['maxStorage'] && ranges['maxStorage'] != '' ? "#{ranges['maxStorage']} #{(it['config'] && it['config']['storageSizeType'] ? it['config']['storageSizeType'] : 'GB').upcase}" : nil,
178
178
  )
179
179
  }
180
180
  end
181
+ if (ranges['minPerDiskSize'] && ranges['minPerDiskSize'] != '') || (ranges['maxPerDiskSize'] && ranges['maxPerDiskSize'] != '')
182
+ description_cols['Custom Per Disk Range'] = lambda {|it|
183
+ get_range(
184
+ ranges['minPerDiskSize'] && ranges['minPerDiskSize'] != '' ? "#{ranges['minPerDiskSize']} GB" : nil,
185
+ ranges['maxPerDiskSize'] && ranges['maxPerDiskSize'] != '' ? "#{ranges['maxPerDiskSize']} GB" : nil
186
+ )
187
+ }
188
+ end
181
189
  if (ranges['minMemory'] && ranges['minMemory'] != '') || (ranges['maxMemory'] && ranges['maxMemory'] != '')
182
190
  description_cols['Custom Memory Range'] = lambda {|it|
183
191
  get_range(
@@ -264,6 +272,9 @@ class Morpheus::Cli::ServicePlanCommand
264
272
  opts.on('--disks [NUMBER]', Integer, "Max disks allowed" ) do |val|
265
273
  params['maxDisks'] = val.to_i || 1
266
274
  end
275
+ opts.on('--cores-per-socket [NUMBER]', Integer, "Cores Per Socket") do |val|
276
+ params['coresPerSocket'] = val.to_i || 1
277
+ end
267
278
  opts.on('--custom-cores [on|off]', String, "Can be used to enable / disable customizable cores. Default is on") do |val|
268
279
  params['customCores'] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
269
280
  end
@@ -285,17 +296,17 @@ class Morpheus::Cli::ServicePlanCommand
285
296
  opts.on('--price-sets [LIST]', Array, 'Price set(s), comma separated list of price set IDs') do |list|
286
297
  params['priceSets'] = list.collect {|it| it.to_s.strip.empty? || !it.to_i ? nil : it.to_s.strip}.compact.uniq.collect {|it| {'id' => it.to_i}}
287
298
  end
288
- opts.on('--min-storage NUMBER', String, "Min storage. Assumes GB unless optional modifier specified, ex: 512MB") do |val|
289
- # Storage doesn't get converted to bytes
290
- bytes = parse_bytes_param(val, '--min-storage', 'GB', true)
291
- ((params['config'] ||= {})['ranges'] ||= {})['minStorage'] = bytes[:number]
292
- (params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
299
+ opts.on('--min-storage NUMBER', String, "Min total storage in GB.") do |val|
300
+ ((params['config'] ||= {})['ranges'] ||= {})['minStorage'] = val.to_i
293
301
  end
294
- opts.on('--max-storage NUMBER', String, "Max storage. Assumes GB unless optional modifier specified, ex: 512MB") do |val|
295
- # Storage doesn't get converted to bytes
296
- bytes = parse_bytes_param(val.to_s, '--max-storage', 'GB', true)
297
- ((params['config'] ||= {})['ranges'] ||= {})['maxStorage'] = bytes[:number]
298
- (params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
302
+ opts.on('--max-storage NUMBER', String, "Max total storage in GB.") do |val|
303
+ ((params['config'] ||= {})['ranges'] ||= {})['maxStorage'] = val.to_i
304
+ end
305
+ opts.on('--min-per-disk-size NUMBER', String, "Min per disk size in GB.") do |val|
306
+ ((params['config'] ||= {})['ranges'] ||= {})['minPerDiskSize'] = val.to_i
307
+ end
308
+ opts.on('--max-per-disk-size NUMBER', String, "Max per disk size in GB.") do |val|
309
+ ((params['config'] ||= {})['ranges'] ||= {})['maxPerDiskSize'] = val.to_i
299
310
  end
300
311
  opts.on('--min-memory NUMBER', String, "Min memory. Assumes MB unless optional modifier specified, ex: 1GB") do |val|
301
312
  # Memory does get converted to bytes
@@ -315,6 +326,18 @@ class Morpheus::Cli::ServicePlanCommand
315
326
  opts.on('--max-cores NUMBER', String, "Max cores") do |val|
316
327
  ((params['config'] ||= {})['ranges'] ||= {})['maxCores'] = val.to_i
317
328
  end
329
+ opts.on('--min-sockets NUMBER', String, "Min sockets") do |val|
330
+ ((params['config'] ||= {})['ranges'] ||= {})['minSockets'] = val.to_i
331
+ end
332
+ opts.on('--max-sockets NUMBER', String, "Max sockets") do |val|
333
+ ((params['config'] ||= {})['ranges'] ||= {})['maxSockets'] = val.to_i
334
+ end
335
+ opts.on('--min-cores-per-socket NUMBER', String, "Min cores per socket") do |val|
336
+ ((params['config'] ||= {})['ranges'] ||= {})['minCoresPerSocket'] = val.to_i
337
+ end
338
+ opts.on('--max-cores-per-socket NUMBER', String, "Max cores per socket") do |val|
339
+ ((params['config'] ||= {})['ranges'] ||= {})['maxCoresPerSocket'] = val.to_i
340
+ end
318
341
  add_perms_options(opts, options, ['plans', 'groupDefaults'])
319
342
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote, :quiet])
320
343
  opts.footer = "Create service plan"
@@ -396,13 +419,41 @@ class Morpheus::Cli::ServicePlanCommand
396
419
  true
397
420
  )
398
421
  params['maxMemory'] = bytes[:bytes]
399
- # (params['config'] ||= {})['memorySizeType'] = bytes[:unit].downcase
400
422
  rescue
401
423
  print "Invalid Value... Please try again.\n"
402
424
  end
425
+ params['customMaxMemory'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'customMaxMemory', 'type' => 'checkbox', 'fieldLabel' => 'Custom Max Memory', 'required' => false, 'description' => 'Custom Max Memory', 'defaultValue' => false}],options[:options],@api_client,{}, options[:no_prompt])['customMaxMemory']
403
426
  end
404
427
  end
405
428
 
429
+ # add'n options
430
+ addn_options = [
431
+ {'fieldName' => 'maxCores', 'fieldLabel' => 'Core Count', 'type' => 'number', 'required' => true, 'defaultValue' => 1, 'displayOrder' => 1},
432
+ {'fieldName' => 'customCores', 'fieldLabel' => 'Custom Cores', 'type' => 'checkbox', 'defaultValue' => false, 'displayOrder' => 2},
433
+ {'fieldName' => 'coresPerSocket', 'fieldLabel' => 'Cores Per Socket', 'type' => 'number', 'required' => true, 'defaultValue' => 1, 'displayOrder' => 3},
434
+ {'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minStorage', 'fieldLabel' => 'Min Total Storage (GB)', 'type' => 'number', 'displayOrder' => 1},
435
+ {'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxStorage', 'fieldLabel' => 'Max Total Storage (GB)', 'type' => 'number', 'displayOrder' => 2},
436
+ {'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minPerDiskSize', 'fieldLabel' => 'Min Per Disk Size (GB)', 'type' => 'number', 'displayOrder' => 3},
437
+ {'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxPerDiskSize', 'fieldLabel' => 'Max Per Disk Size (GB)', 'type' => 'number', 'displayOrder' => 4},
438
+ {'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minMemory', 'fieldLabel' => 'Min Memory (GB)', 'type' => 'number', 'displayOrder' => 5},
439
+ {'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxMemory', 'fieldLabel' => 'Max Memory (GB)', 'type' => 'number', 'displayOrder' => 6},
440
+ {'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minCores', 'fieldLabel' => 'Min Cores', 'type' => 'number', 'displayOrder' => 7},
441
+ {'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxCores', 'fieldLabel' => 'Max Cores', 'type' => 'number', 'displayOrder' => 8}
442
+ ]
443
+
444
+ if provision_type['hasSocketRange']
445
+ addn_options.push({'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minSockets', 'fieldLabel' => 'Min Sockets', 'type' => 'number', 'displayOrder' => 9})
446
+ addn_options.push({'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxSockets', 'fieldLabel' => 'Max Sockets', 'type' => 'number', 'displayOrder' => 10})
447
+ end
448
+
449
+ if provision_type['hasCoresPerSocketRange']
450
+ addn_options.push({'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'minCoresPerSocket', 'fieldLabel' => 'Min Cores Per Socket', 'type' => 'number', 'displayOrder' => 11})
451
+ addn_options.push({'fieldContext' => 'config.ranges', 'fieldGroup' => 'Custom Ranges', 'fieldName' => 'maxCoresPerSocket', 'fieldLabel' => 'Max Cores Per Socket', 'type' => 'number', 'displayOrder' => 12})
452
+ end
453
+
454
+ v_prompt = Morpheus::Cli::OptionTypes.prompt(addn_options, options[:options], @api_client, params)
455
+ params.deep_merge!(v_prompt)
456
+
406
457
  # price sets
407
458
  if params['priceSets'].nil? && !options[:no_prompt]
408
459
  price_sets = []
@@ -517,17 +568,17 @@ class Morpheus::Cli::ServicePlanCommand
517
568
  opts.on('--price-sets [LIST]', Array, 'Price set(s), comma separated list of price set IDs') do |list|
518
569
  params['priceSets'] = list.collect {|it| it.to_s.strip.empty? || !it.to_i ? nil : it.to_s.strip}.compact.uniq.collect {|it| {'id' => it.to_i}}
519
570
  end
520
- opts.on('--min-storage NUMBER', String, "Min storage. Assumes GB unless optional modifier specified, ex: 512MB") do |val|
521
- # Storage doesn't get converted to bytes
522
- bytes = parse_bytes_param(val, '--min-storage', 'GB')
523
- ((params['config'] ||= {})['ranges'] ||= {})['minStorage'] = bytes[:number]
524
- (params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
571
+ opts.on('--min-storage NUMBER', String, "Min total storage in GB.") do |val|
572
+ ((params['config'] ||= {})['ranges'] ||= {})['minStorage'] = val.to_i
525
573
  end
526
- opts.on('--max-storage NUMBER', String, "Max storage. Assumes GB unless optional modifier specified, ex: 512MB") do |val|
527
- # Storage doesn't get converted to bytes
528
- bytes = parse_bytes_param(val, '--max-storage', 'GB', true)
529
- ((params['config'] ||= {})['ranges'] ||= {})['maxStorage'] = bytes[:number]
530
- (params['config'] ||= {})['storageSizeType'] = bytes[:unit].downcase
574
+ opts.on('--max-storage NUMBER', String, "Max total storage in GB.") do |val|
575
+ ((params['config'] ||= {})['ranges'] ||= {})['maxStorage'] = val.to_i
576
+ end
577
+ opts.on('--min-per-disk-size NUMBER', String, "Min per disk size in GB.") do |val|
578
+ ((params['config'] ||= {})['ranges'] ||= {})['minPerDiskSize'] = val.to_i
579
+ end
580
+ opts.on('--max-per-disk-size NUMBER', String, "Max per disk size in GB.") do |val|
581
+ ((params['config'] ||= {})['ranges'] ||= {})['maxPerDiskSize'] = val.to_i
531
582
  end
532
583
  opts.on('--min-memory NUMBER', String, "Min memory. Assumes MB unless optional modifier specified, ex: 1GB") do |val|
533
584
  # Memory does get converted to bytes
@@ -546,6 +597,18 @@ class Morpheus::Cli::ServicePlanCommand
546
597
  end
547
598
  opts.on('--max-cores NUMBER', String, "Max cores") do |val|
548
599
  ((params['config'] ||= {})['ranges'] ||= {})['maxCores'] = val.to_i
600
+ end
601
+ opts.on('--min-sockets NUMBER', String, "Min sockets") do |val|
602
+ ((params['config'] ||= {})['ranges'] ||= {})['minSockets'] = val.to_i
603
+ end
604
+ opts.on('--max-sockets NUMBER', String, "Max sockets") do |val|
605
+ ((params['config'] ||= {})['ranges'] ||= {})['maxSockets'] = val.to_i
606
+ end
607
+ opts.on('--min-cores-per-socket NUMBER', String, "Min cores per socket") do |val|
608
+ ((params['config'] ||= {})['ranges'] ||= {})['minCoresPerSocket'] = val.to_i
609
+ end
610
+ opts.on('--max-cores-per-socket NUMBER', String, "Max cores per socket") do |val|
611
+ ((params['config'] ||= {})['ranges'] ||= {})['maxCoresPerSocket'] = val.to_i
549
612
  end
550
613
  add_perms_options(opts, options, ['plans', 'groupDefaults'])
551
614
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote, :quiet])
@@ -359,7 +359,7 @@ class Morpheus::Cli::Shell
359
359
  end
360
360
  out << "See the available commands below.\n"
361
361
 
362
- out << "\nCommands:"
362
+ out << "\nCommands:\n"
363
363
  # commands = @morpheus_commands + @shell_commands
364
364
  # @morpheus_commands.sort.each {|cmd|
365
365
  # out << "\t#{cmd.to_s}\n"
@@ -442,7 +442,7 @@ class Morpheus::Cli::Tasks
442
442
  # Result Type
443
443
  if options[:options]['resultType']
444
444
  payload['task']['resultType'] = options[:options]['resultType']
445
- else
445
+ elsif task_type['hasResults']
446
446
  result_types_dropdown = [{"name" => "Value", "value" => "value"}, {"name" => "Exit Code", "value" => "exitCode"}, {"name" => "Key Value", "value" => "keyValue"}, {"name" => "JSON", "value" => "json"}]
447
447
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'resultType', 'fieldLabel' => 'Result Type', 'type' => 'select', 'selectOptions' => result_types_dropdown}], options[:options], @api_client)
448
448
  payload['task']['resultType'] = v_prompt['resultType'] unless v_prompt['resultType'].to_s.empty?
@@ -471,6 +471,7 @@ class Morpheus::Cli::Tasks
471
471
  end
472
472
  end
473
473
  end
474
+ process_special_task_option_typeaheads(task_option_types)
474
475
  # inject file_params into options for file-content prompt
475
476
  # or into taskOptions.script for types not yet using file-content
476
477
  unless file_params.empty?
@@ -859,38 +860,99 @@ class Morpheus::Cli::Tasks
859
860
  target_type = nil
860
861
  instance_ids = []
861
862
  instances = []
863
+ instance_label = nil
862
864
  server_ids = []
863
865
  servers = []
864
- default_refresh_interval = 10
866
+ server_label = nil
867
+ default_refresh_interval = 5
868
+ all_target_types = ['appliance', 'instance', 'instance-label', 'server', 'server-label']
865
869
  optparse = Morpheus::Cli::OptionParser.new do |opts|
866
- opts.banner = subcommand_usage("[task] --instance [instance] [options]")
867
- opts.on('--instance INSTANCE', String, "Instance name or id to execute the task on. This option can be passed more than once.") do |val|
870
+ opts.banner = subcommand_usage("[task] [options]")
871
+ opts.on('--context-type VALUE', String, "Context Type, #{ored_list(all_target_types)}") do |val|
872
+ val = val.downcase
873
+ val = 'appliance' if val == 'none'
874
+ if target_type && target_type != val
875
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
876
+ end
877
+ if !all_target_types.include?(val)
878
+ raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance")
879
+ end
880
+ target_type = val
881
+ end
882
+ opts.on('--target-type VALUE', String, "alias for context-type") do |val|
883
+ val = val.downcase
884
+ val = 'appliance' if val == 'none'
885
+ if target_type && target_type != val
886
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
887
+ end
888
+ if !all_target_types.include?(val)
889
+ raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance")
890
+ end
891
+ target_type = val
892
+ end
893
+ opts.add_hidden_option('--target-type')
894
+ opts.on('--instance INSTANCE', String, "Instance name or id to target for execution. This option can be passed more than once.") do |val|
895
+ if target_type && target_type != 'instance'
896
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
897
+ end
868
898
  target_type = 'instance'
869
899
  instance_ids << val
870
900
  end
871
- opts.on('--instances [LIST]', Array, "Instances, comma separated list of instance names or IDs.") do |list|
901
+ opts.on('--instances LIST', Array, "Instances, comma separated list of instance names or IDs.") do |list|
902
+ if target_type && target_type != 'instance'
903
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
904
+ end
872
905
  target_type = 'instance'
873
906
  instance_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
874
907
  end
875
- opts.on('--host HOST', String, "Host name or id to execute the task on. This option can be passed more than once.") do |val|
908
+ opts.on('--instance-label LABEL', String, "Instance Label") do |val|
909
+ if target_type && target_type != 'instance-label'
910
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
911
+ end
912
+ target_type = 'instance-label'
913
+ instance_label = val
914
+ end
915
+ opts.on('--server SERVER', String, "Server name or id to target for execution. This option can be passed more than once.") do |val|
916
+ if target_type && target_type != 'server'
917
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
918
+ end
876
919
  target_type = 'server'
877
920
  server_ids << val
878
921
  end
879
- opts.on('--hosts [LIST]', Array, "Hosts, comma separated list of host names or IDs.") do |list|
922
+ opts.on('--servers LIST', Array, "Servers, comma separated list of host names or IDs.") do |list|
923
+ if target_type && target_type != 'server'
924
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
925
+ end
880
926
  target_type = 'server'
881
927
  server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
882
928
  end
883
- opts.on('--server HOST', String, "alias for --host") do |val|
929
+ opts.on('--server-label LABEL', String, "Server Label") do |val|
930
+ if target_type && target_type != 'server-label'
931
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
932
+ end
933
+ target_type = 'server-label'
934
+ server_label = val
935
+ end
936
+ opts.on('--host HOST', String, "alias for --server") do |val|
937
+ if target_type && target_type != 'server'
938
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
939
+ end
884
940
  target_type = 'server'
885
941
  server_ids << val
886
942
  end
887
- opts.on('--servers [LIST]', Array, "alias for --hosts") do |list|
943
+ opts.add_hidden_option('--host')
944
+ opts.on('--hosts HOSTS', Array, "alias for --servers") do |list|
945
+ if target_type && target_type != 'server'
946
+ raise ::OptionParser::InvalidOption.new("The --hosts option cannot be combined with another context (#{target_type})")
947
+ end
888
948
  target_type = 'server'
889
949
  server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
890
950
  end
891
- opts.add_hidden_option('--server')
892
- opts.add_hidden_option('--servers')
951
+ opts.add_hidden_option('--hosts')
893
952
  opts.on('-a', '--appliance', "Execute on the appliance, the target is the appliance itself.") do
953
+ if target_type && target_type != 'appliance'
954
+ raise ::OptionParser::InvalidOption.new("The --appliance option cannot be combined with another context (#{target_type})")
955
+ end
894
956
  target_type = 'appliance'
895
957
  end
896
958
  opts.on('--config [TEXT]', String, "Custom config") do |val|
@@ -921,46 +983,59 @@ class Morpheus::Cli::Tasks
921
983
  payload = options[:payload]
922
984
  payload.deep_merge!({'job' => passed_options}) unless passed_options.empty?
923
985
  else
924
- # always parse instances and/or hosts
925
- if instance_ids.size > 0 && server_ids.size > 0
926
- raise_command_error "Pass --instance or --host, not both.\n#{optparse}"
927
- elsif instance_ids.size > 0
986
+ # prompt for target type and target
987
+ if target_type.nil?
988
+ # todo: Need api to fetch available Context Types for taskId/workflowId
989
+ available_target_types = get_available_contexts_for_task(task)
990
+ default_target_type = available_target_types.first ? available_target_types.first['name'] : nil
991
+ if !available_target_types.empty?
992
+ default_target_type = available_target_types.first ? available_target_types.first['name'] : nil
993
+ target_type = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'context-type', 'fieldName' => 'targetType', 'fieldLabel' => 'Context Type', 'type' => 'select', 'selectOptions' => available_target_types, 'defaultValue' => default_target_type, 'required' => true, 'description' => 'Context Type determines the type of target(s) for the execution'}], options[:options], @api_client)['targetType']
994
+ end
995
+ end
996
+ if target_type
997
+ params['targetType'] = target_type
998
+ end
999
+ if target_type == 'instance'
1000
+ if instance_ids.empty?
1001
+ instance_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instances', 'fieldName' => 'instances', 'fieldLabel' => 'Instance(s)', 'type' => 'text', 'required' => true, 'description' => 'Instances, comma separated list of instance names or IDs.'}], options[:options], @api_client)['instances']
1002
+ instance_ids = parse_array(instance_ids_value)
1003
+ end
928
1004
  instance_ids.each do |instance_id|
929
1005
  instance = find_instance_by_name_or_id(instance_id)
930
1006
  return 1 if instance.nil?
931
1007
  instances << instance
932
1008
  end
933
1009
  params['instances'] = instances.collect {|it| it['id'] }
934
- elsif server_ids.size > 0
1010
+ elsif target_type == 'instance-label'
1011
+ if instance_label.nil?
1012
+ instance_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instance-label', 'fieldName' => 'instanceLabel', 'fieldLabel' => 'Instance Label', 'type' => 'text', 'required' => true, 'description' => 'Instance Label'}], options[:options], @api_client)['instanceLabel']
1013
+ end
1014
+ # params['config'] ||= {}
1015
+ # params['config']['instanceLabel'] = instance_label
1016
+ params['instanceLabel'] = instance_label
1017
+ elsif target_type == 'server'
1018
+ if server_ids.empty?
1019
+ server_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'servers', 'fieldName' => 'servers', 'fieldLabel' => 'Server(s)', 'type' => 'text', 'required' => true, 'description' => 'Servers, comma separated list of server names or IDs.'}], options[:options], @api_client)['servers']
1020
+ server_ids = parse_array(server_ids_value)
1021
+ end
935
1022
  server_ids.each do |server_id|
936
1023
  server = find_server_by_name_or_id(server_id)
937
1024
  return 1 if server.nil?
938
1025
  servers << server
939
1026
  end
940
1027
  params['servers'] = servers.collect {|it| it['id'] }
941
- end
942
- # validate requires inputs based on task executeTarget
943
- if task['executeTarget'] == 'resource'
944
- if instance_ids.empty? && server_ids.empty?
945
- # todo: prompt for Context: None,Instance,Server and then Instance(s) or Server(s)
946
- raise_command_error "missing required option: --instance or --host\n#{optparse}"
1028
+ elsif target_type == 'server-label'
1029
+ if server_label.nil?
1030
+ server_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'server-label', 'fieldName' => 'serverLabel', 'fieldLabel' => 'Server Label', 'type' => 'text', 'required' => true, 'description' => 'Server Label'}], options[:options], @api_client)['serverLabel']
947
1031
  end
948
- elsif task['executeTarget'] == 'local'
949
- # no targetType required for local
950
- elsif task['executeTarget'] == 'remote'
951
- # not sure about this one
952
- else
953
- # unknown executeTarget
1032
+ # params['config'] ||= {}
1033
+ # params['config']['serverLabel'] = server_label
1034
+ params['serverLabel'] = server_label
954
1035
  end
955
-
956
-
957
-
958
1036
  # todo: prompt to task optionTypes for customOptions
959
1037
  if task['optionTypes']
960
1038
 
961
- end
962
- if target_type
963
- params['targetType'] = target_type
964
1039
  end
965
1040
  job_payload = {}
966
1041
  job_payload.deep_merge!(params)
@@ -1293,4 +1368,24 @@ class Morpheus::Cli::Tasks
1293
1368
  end
1294
1369
  end
1295
1370
 
1371
+ def process_special_task_option_typeaheads(option_types)
1372
+ # massage special task typeaheads options
1373
+ # this makes us all sad
1374
+ option_types.each do |option_type|
1375
+ if option_type['type'] == 'typeahead'
1376
+ if ['operationalWorkflowName','containerScript','containerTemplate'].include?(option_type['code'])
1377
+ option_type.deep_merge!({'config' => {'valueField' => 'name'}})
1378
+ end
1379
+ elsif option_type['type'] == 'hidden'
1380
+ if ['operationalWorkflowId','containerScriptId','containerTemplateId'].include?(option_type['code'])
1381
+ option_type['processValue'] = lambda {|val|
1382
+ if val.to_s.empty?
1383
+ selected_option = Morpheus::Cli::OptionTypes.get_last_select()
1384
+ selected_option ? selected_option['value'] : nil
1385
+ end
1386
+ }
1387
+ end
1388
+ end
1389
+ end
1390
+ end
1296
1391
  end
@@ -550,40 +550,101 @@ class Morpheus::Cli::Workflows
550
550
  target_type = nil
551
551
  instance_ids = []
552
552
  instances = []
553
+ instance_label = nil
553
554
  server_ids = []
554
555
  servers = []
555
- default_refresh_interval = 10
556
+ server_label = nil
557
+ default_refresh_interval = 5
558
+ all_target_types = ['appliance', 'instance', 'instance-label', 'server', 'server-label']
556
559
  optparse = Morpheus::Cli::OptionParser.new do |opts|
557
- opts.banner = subcommand_usage("[workflow] --instance [instance] [options]")
558
- opts.on('--instance INSTANCE', String, "Instance name or id to execute the workflow on. This option can be passed more than once.") do |val|
560
+ opts.banner = subcommand_usage("[workflow] [options]")
561
+ opts.on('--context-type VALUE', String, "Context Type, #{ored_list(all_target_types)}") do |val|
562
+ val = val.downcase
563
+ val = 'appliance' if val == 'none'
564
+ if target_type && target_type != val
565
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
566
+ end
567
+ if !all_target_types.include?(val)
568
+ raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance")
569
+ end
570
+ target_type = val
571
+ end
572
+ opts.on('--target-type VALUE', String, "alias for context-type") do |val|
573
+ val = val.downcase
574
+ val = 'appliance' if val == 'none'
575
+ if target_type && target_type != val
576
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
577
+ end
578
+ if !all_target_types.include?(val)
579
+ raise ::OptionParser::InvalidOption.new("'#{val}' is invalid. It must be one of the following: instance, instance-label, server, server-label or appliance")
580
+ end
581
+ target_type = val
582
+ end
583
+ opts.add_hidden_option('--target-type')
584
+ opts.on('--instance INSTANCE', String, "Instance name or id to target for execution. This option can be passed more than once.") do |val|
585
+ if target_type && target_type != 'instance'
586
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
587
+ end
559
588
  target_type = 'instance'
560
589
  instance_ids << val
561
590
  end
562
- opts.on('--instances [LIST]', Array, "Instances, comma separated list of instance names or IDs.") do |list|
591
+ opts.on('--instances LIST', Array, "Instances, comma separated list of instance names or IDs.") do |list|
592
+ if target_type && target_type != 'instance'
593
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
594
+ end
563
595
  target_type = 'instance'
564
596
  instance_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
565
597
  end
566
- opts.on('--host HOST', String, "Host name or id to execute the workflow on. This option can be passed more than once.") do |val|
598
+ opts.on('--instance-label LABEL', String, "Instance Label") do |val|
599
+ if target_type && target_type != 'instance-label'
600
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
601
+ end
602
+ target_type = 'instance-label'
603
+ instance_label = val
604
+ end
605
+ opts.on('--server SERVER', String, "Server name or id to target for execution. This option can be passed more than once.") do |val|
606
+ if target_type && target_type != 'server'
607
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
608
+ end
567
609
  target_type = 'server'
568
610
  server_ids << val
569
611
  end
570
- opts.on('--hosts [LIST]', Array, "Hosts, comma separated list of host names or IDs.") do |list|
612
+ opts.on('--servers LIST', Array, "Servers, comma separated list of host names or IDs.") do |list|
613
+ if target_type && target_type != 'server'
614
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
615
+ end
571
616
  target_type = 'server'
572
617
  server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
573
618
  end
574
- opts.on('--server HOST', String, "alias for --host") do |val|
619
+ opts.on('--server-label LABEL', String, "Server Label") do |val|
620
+ if target_type && target_type != 'server-label'
621
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
622
+ end
623
+ target_type = 'server-label'
624
+ server_label = val
625
+ end
626
+ opts.on('--host HOST', String, "alias for --server") do |val|
627
+ if target_type && target_type != 'server'
628
+ raise ::OptionParser::InvalidOption.new("cannot be combined with another context (#{target_type})")
629
+ end
575
630
  target_type = 'server'
576
631
  server_ids << val
577
632
  end
578
- opts.on('--servers [LIST]', Array, "alias for --hosts") do |list|
633
+ opts.add_hidden_option('--host')
634
+ opts.on('--hosts HOSTS', Array, "alias for --servers") do |list|
635
+ if target_type && target_type != 'server'
636
+ raise ::OptionParser::InvalidOption.new("The --hosts option cannot be combined with another context (#{target_type})")
637
+ end
579
638
  target_type = 'server'
580
639
  server_ids = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
581
640
  end
641
+ opts.add_hidden_option('--hosts')
582
642
  opts.on('-a', '--appliance', "Execute on the appliance, the target is the appliance itself.") do
643
+ if target_type && target_type != 'appliance'
644
+ raise ::OptionParser::InvalidOption.new("The --appliance option cannot be combined with another context (#{target_type})")
645
+ end
583
646
  target_type = 'appliance'
584
647
  end
585
- opts.add_hidden_option('--server')
586
- opts.add_hidden_option('--servers')
587
648
  opts.on('--config [TEXT]', String, "Custom config") do |val|
588
649
  params['customConfig'] = val.to_s
589
650
  end
@@ -611,27 +672,55 @@ class Morpheus::Cli::Workflows
611
672
  payload = options[:payload]
612
673
  payload.deep_merge!({'job' => passed_options}) unless passed_options.empty?
613
674
  else
614
- if instance_ids.size > 0 && server_ids.size > 0
615
- raise_command_error "Pass --instance or --host, not both.\n#{optparse}"
616
- elsif instance_ids.size > 0
675
+ # prompt for target type and target
676
+ if target_type.nil?
677
+ # todo: Need api to fetch available Context Types for taskId/workflowId
678
+ available_target_types = get_available_contexts_for_workflow(workflow)
679
+ default_target_type = available_target_types.first ? available_target_types.first['name'] : nil
680
+ if !available_target_types.empty?
681
+ default_target_type = available_target_types.first ? available_target_types.first['name'] : nil
682
+ target_type = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'context-type', 'fieldName' => 'targetType', 'fieldLabel' => 'Context Type', 'type' => 'select', 'selectOptions' => available_target_types, 'defaultValue' => default_target_type, 'required' => true, 'description' => 'Context Type determines the type of target(s) for the execution'}], options[:options], @api_client)['targetType']
683
+ end
684
+ end
685
+ if target_type
686
+ params['targetType'] = target_type
687
+ end
688
+ if target_type == 'instance'
689
+ if instance_ids.empty?
690
+ instance_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instances', 'fieldName' => 'instances', 'fieldLabel' => 'Instance(s)', 'type' => 'text', 'required' => true, 'description' => 'Instances, comma separated list of instance names or IDs.'}], options[:options], @api_client)['instances']
691
+ instance_ids = parse_array(instance_ids_value)
692
+ end
617
693
  instance_ids.each do |instance_id|
618
694
  instance = find_instance_by_name_or_id(instance_id)
619
695
  return 1 if instance.nil?
620
696
  instances << instance
621
697
  end
622
698
  params['instances'] = instances.collect {|it| it['id'] }
623
- elsif server_ids.size > 0
699
+ elsif target_type == 'instance-label'
700
+ if instance_label.nil?
701
+ instance_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'instance-label', 'fieldName' => 'instanceLabel', 'fieldLabel' => 'Instance Label', 'type' => 'text', 'required' => true, 'description' => 'Instance Label'}], options[:options], @api_client)['instanceLabel']
702
+ end
703
+ # params['config'] ||= {}
704
+ # params['config']['instanceLabel'] = instance_label
705
+ params['instanceLabel'] = instance_label
706
+ elsif target_type == 'server'
707
+ if server_ids.empty?
708
+ server_ids_value = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'servers', 'fieldName' => 'servers', 'fieldLabel' => 'Server(s)', 'type' => 'text', 'required' => true, 'description' => 'Servers, comma separated list of server names or IDs.'}], options[:options], @api_client)['servers']
709
+ server_ids = parse_array(server_ids_value)
710
+ end
624
711
  server_ids.each do |server_id|
625
712
  server = find_server_by_name_or_id(server_id)
626
713
  return 1 if server.nil?
627
714
  servers << server
628
715
  end
629
716
  params['servers'] = servers.collect {|it| it['id'] }
630
- elsif target_type == 'appliance'
631
- # cool, run it locally.
632
- else
633
- # cool, run it locally.
634
- #raise_command_error "missing required option: --instance, --host or --appliance\n#{optparse}"
717
+ elsif target_type == 'server-label'
718
+ if server_label.nil?
719
+ server_label = Morpheus::Cli::OptionTypes.prompt([{'switch' => 'server-label', 'fieldName' => 'serverLabel', 'fieldLabel' => 'Server Label', 'type' => 'text', 'required' => true, 'description' => 'Server Label'}], options[:options], @api_client)['serverLabel']
720
+ end
721
+ # params['config'] ||= {}
722
+ # params['config']['serverLabel'] = server_label
723
+ params['serverLabel'] = server_label
635
724
  end
636
725
 
637
726
  # prompt to workflow optionTypes for customOptions
@@ -643,9 +732,6 @@ class Morpheus::Cli::Workflows
643
732
  }
644
733
  custom_options = Morpheus::Cli::OptionTypes.prompt(custom_option_types, options[:options], @api_client, {})
645
734
  end
646
- if target_type
647
- params['targetType'] = target_type
648
- end
649
735
  job_payload = {}
650
736
  job_payload.deep_merge!(params)
651
737
  passed_options.delete('customOptions')
@@ -41,8 +41,8 @@ module Morpheus::Cli::JobsHelper
41
41
  "Created By" => lambda {|it| it[:created_by]},
42
42
  "Duration" => lambda {|it| it[:duration]},
43
43
  "Status" => lambda {|it| it[:status]},
44
- "Error" => lambda {|it| options[:details] ? it[:error] : truncate_string(it[:error], 32) },
45
- "Output" => lambda {|it| options[:details] ? it[:output] : truncate_string(it[:output], 32) }
44
+ "Error" => lambda {|it| options[:details] ? it[:error].to_s.strip : truncate_string(it[:error], 32).to_s.strip.gsub("\n", ' ') },
45
+ "Output" => lambda {|it| options[:details] ? it[:output].to_s.strip : truncate_string(it[:output], 32).to_s.strip.gsub("\n", ' ') }
46
46
  }
47
47
  print as_pretty_table(events.collect {|it| get_process_event_data(it)}, event_columns.upcase_keys!, options)
48
48
  end
@@ -147,7 +147,7 @@ module Morpheus::Cli::JobsHelper
147
147
  # refresh execution request until it is finished
148
148
  # returns json response data of the last execution request when status reached 'completed' or 'failed'
149
149
  def wait_for_job_execution(job_execution_id, options={}, print_output = true)
150
- refresh_interval = 10
150
+ refresh_interval = 5
151
151
  if options[:refresh_interval].to_i > 0
152
152
  refresh_interval = options[:refresh_interval]
153
153
  end
@@ -168,5 +168,32 @@ module Morpheus::Cli::JobsHelper
168
168
  end
169
169
 
170
170
 
171
+ def get_available_contexts_for_task(task)
172
+ #If task has target of resource, then CAN NOT run it local
173
+ targets = []
174
+ has_resource = task['executeTarget'] == 'resource'
175
+ if !has_resource
176
+ targets << {'name' => 'None', 'value' => 'appliance'}
177
+ end
178
+ targets << {'name' => 'Instance', 'value' => 'instance'}
179
+ targets << {'name' => 'Instance Label', 'value' => 'instance-label'}
180
+ targets << {'name' => 'Server', 'value' => 'server'}
181
+ targets << {'name' => 'Server Label', 'value' => 'server-label'}
182
+ return targets
183
+ end
184
+
185
+ def get_available_contexts_for_workflow(workflow)
186
+ #If any task has target of resource, then CAN NOT run it local
187
+ targets = []
188
+ has_resource = workflow['taskSetTasks'].find {|task| task['executeTarget'] == 'resource' }
189
+ if !has_resource
190
+ targets << {'name' => 'None', 'value' => 'appliance'}
191
+ end
192
+ targets << {'name' => 'Instance', 'value' => 'instance'}
193
+ targets << {'name' => 'Instance Label', 'value' => 'instance-label'}
194
+ targets << {'name' => 'Server', 'value' => 'server'}
195
+ targets << {'name' => 'Server Label', 'value' => 'server-label'}
196
+ return targets
197
+ end
171
198
 
172
199
  end
@@ -88,36 +88,12 @@ module Morpheus::Cli::ProcessesHelper
88
88
 
89
89
  # decolorize, remove newlines and truncate for table cell
90
90
  def format_process_error(process, max_length=20, return_color=cyan)
91
- #return max_length ? truncate_string(process['error'], max_length) : process['error']
92
- out = ""
93
- if process['error']
94
- # lines = process['error'].split("\n").collect {|line| reset + "#{line.to_s.strip}" }
95
- # lines = process['error'].split("\n").collect {|line| "#{line.to_s.strip}" }
96
- lines = [process['error']]
97
- out = lines.join(" ")
98
- if max_length
99
- out = truncate_string(out, max_length)
100
- end
101
- out << return_color if return_color
102
- end
103
- out
91
+ truncate_string(process['error'].to_s.strip.gsub("\n", " "), max_length)
104
92
  end
105
93
 
106
94
  # decolorize, remove newlines and truncate for table cell
107
95
  def format_process_output(process, max_length=20, return_color=cyan)
108
- return max_length ? truncate_string(process['output'], max_length) : process['output']
109
- out = ""
110
- if process['output']
111
- # lines = process['output'].split("\n").collect {|line| reset + "#{line.to_s.strip}" }
112
- # lines = process['error'].split("\n").collect {|line| "#{line.to_s.strip}" }
113
- lines = [process['output']]
114
- out = lines.join(" ")
115
- if max_length
116
- out = truncate_string(out, max_length)
117
- end
118
- out << return_color if return_color
119
- end
120
- out
96
+ truncate_string(process['output'].to_s.strip.gsub("\n", " "), max_length)
121
97
  end
122
98
 
123
99
  # format for either ETA/Duration
@@ -777,15 +777,22 @@ module Morpheus::Cli::ProvisioningHelper
777
777
  option_type_list = option_type_list.reject {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
778
778
 
779
779
  resource_pool_options = options_interface.options_for_source('zonePools', {groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], layoutId: layout["id"]}.merge(service_plan.nil? ? {} : {planId: service_plan["id"]}))['data']
780
- resource_pool = resource_pool_options.find {|opt| opt['id'] == options[:resource_pool].to_i} if options[:resource_pool]
781
-
780
+ if options[:resource_pool]
781
+ resource_pool = resource_pool_options.find {|opt| opt['value'] == options[:resource_pool].to_s || opt['value'] == "pool-#{options[:resource_pool]}"}
782
+ end
783
+ pool_required = provision_type["zonePoolRequired"]
784
+ # Should pool_id have the pool-,poolGroup- prefix or not?
785
+ use_pool_prefix = resource_pool_options.find {|opt| opt['value'].to_s.include?("pool") }
782
786
  if resource_pool
783
- pool_id = resource_pool['id']
787
+ pool_id = resource_pool['id'] # id or value?
784
788
  else
785
789
  if options[:default_resource_pool]
786
790
  default_resource_pool = resource_pool_options.find {|rp| rp['id'] == options[:default_resource_pool]}
787
791
  end
788
- resource_pool_option_type ||= {'fieldContext' => 'config', 'fieldName' => 'resourcePoolId', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'selectOptions' => resource_pool_options, 'required' => true, 'skipSingleOption' => true, 'description' => 'Select resource pool.', 'defaultValue' => default_resource_pool ? default_resource_pool['name'] : nil}
792
+ if use_pool_prefix && options[:options]['config'] && options[:options]['config']['resourcePoolId'] && !options[:options]['config']['resourcePoolId'].to_s.include?("pool")
793
+ options[:options]['config']['resourcePoolId'] = "pool-" + options[:options]['config']['resourcePoolId'].to_s
794
+ end
795
+ resource_pool_option_type ||= {'fieldContext' => 'config', 'fieldName' => 'resourcePoolId', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'selectOptions' => resource_pool_options, 'required' => pool_required, 'skipSingleOption' => true, 'description' => 'Select resource pool.', 'defaultValue' => default_resource_pool ? default_resource_pool['name'] : nil}
789
796
  resource_pool_prompt = Morpheus::Cli::OptionTypes.prompt([resource_pool_option_type],options[:options],api_client,{}, no_prompt, true)
790
797
  resource_pool_prompt.deep_compact!
791
798
  payload.deep_merge!(resource_pool_prompt)
@@ -795,7 +802,7 @@ module Morpheus::Cli::ProvisioningHelper
795
802
  elsif resource_pool_prompt[resource_pool_option_type['fieldName']]
796
803
  pool_id = resource_pool_prompt[resource_pool_option_type['fieldName']]
797
804
  end
798
- resource_pool ||= resource_pool_options.find {|it| it['id'] == pool_id}
805
+ resource_pool ||= resource_pool_options.find {|it| it['value'].to_s == pool_id.to_s}
799
806
  end
800
807
  end
801
808
  end
@@ -582,6 +582,9 @@ module Morpheus
582
582
 
583
583
  if no_prompt
584
584
  if !value_found
585
+ if default_value == ""
586
+ default_value = nil
587
+ end
585
588
  if !default_value.nil? && !select_options.nil?
586
589
  matched_option = select_options.find {|it| it[value_field].to_s == default_value.to_s }
587
590
  if matched_option.nil?
@@ -814,7 +817,7 @@ module Morpheus
814
817
  api_params ||= {}
815
818
  api_params['query'] = query_value
816
819
  # skip refresh if you just hit enter
817
- if !query_value.empty?
820
+ if !query_value.empty? || (select_options.nil? || select_options.empty?)
818
821
  select_options = load_options(option_type, api_client, api_params, query_value)
819
822
  end
820
823
 
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "6.0.0"
4
+ VERSION = "6.0.2"
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: morpheus-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.0
4
+ version: 6.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Estes
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2023-03-02 00:00:00.000000000 Z
14
+ date: 2023-04-14 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler