morpheus-cli 8.0.10 → 8.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4fc087520efe1dab49dbe42df70b39da196e9539cd78eb162adec2fc8907a54
4
- data.tar.gz: b008d63500f56d6a72b12c918db54b3d2869df3fa3407e491411a8eab63ea6be
3
+ metadata.gz: bb7a990dcc082a03f2aca40fb88b97ebba11413844dc0108241f3e26f68ae61b
4
+ data.tar.gz: 66f510f249523971e5dc712d42b66e12cdf746162783c68b82df4549f942b2c2
5
5
  SHA512:
6
- metadata.gz: f00f2ea9c25064ad69f1038a83a5c0a23708c21d2bc670406ff1527dcdd0808361043c7e7c498fd9a03733106fcd8c1884515ebd4951c12b1bc839c37163b879
7
- data.tar.gz: 8c818cdda02325d65715ee474e72480467a27ce14548483415a555002042cfbb7638193feb9fc3c61138effa50d473703eeb4a6f66d47eb4ccf087e9c9b040c5
6
+ metadata.gz: 7586dc7f31d7c27c76cb4d2412ac023292dece2471c5c02e2e7dc8a4ef6cd79eeea55ad1654d4fff7af5e45714b4a5e1e51eb6d9eafa968006c70d5c15316345
7
+ data.tar.gz: 7378973777072746bcb3498a7940990ac2fd98328587a716b02935711684e23aee6242ba9d6300cb83be8a5e3edd1868887c9a560d8589fd2f15df59d2a75d87
data/Dockerfile CHANGED
@@ -1,5 +1,5 @@
1
1
  FROM ruby:2.7.5
2
2
 
3
- RUN gem install morpheus-cli -v 8.0.10
3
+ RUN gem install morpheus-cli -v 8.0.11
4
4
 
5
5
  ENTRYPOINT ["morpheus"]
@@ -2556,7 +2556,7 @@ EOT
2556
2556
  # prompt
2557
2557
  # Host (preferredParentServer.id)
2558
2558
  if payload['server']['host']
2559
- options[:options] = payload['server'].remove('host')
2559
+ options[:options] = payload['server'].delete('host')
2560
2560
  end
2561
2561
  default_host = (server['preferredParentServer'] ? server['preferredParentServer']['id'] : (server['parentServer'] ? server['parentServer']['id'] : nil))
2562
2562
  host = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'host', 'type' => 'select', 'fieldLabel' => 'Host', 'optionSource' => 'parentServers', 'required' => false, 'description' => 'Choose the preferred parent host for this virtual machine to be placed on.', 'defaultValue' => default_host}],options[:options],@api_client,{'serverId' => server['id']})['host']
@@ -102,7 +102,7 @@ class Morpheus::Cli::Shell
102
102
  command_list = @auto_complete_commands
103
103
  result = command_list.grep(/^#{Regexp.escape(s)}/)
104
104
  if result.nil? || result.empty?
105
- Readline::FILENAME_COMPLETION_PROC.call(s)
105
+ Readline::FILENAME_COMPLETION_PROC.call(s) rescue []
106
106
  else
107
107
  result
108
108
  end
@@ -27,6 +27,7 @@ class Morpheus::Cli::StorageProvidersCommand
27
27
  def connect(opts)
28
28
  @api_client = establish_remote_appliance_connection(opts)
29
29
  @storage_providers_interface = @api_client.storage_providers
30
+ @storage_servers_interface = @api_client.storage_servers
30
31
  @clouds_interface = @api_client.clouds
31
32
  @options_interface = @api_client.options
32
33
  end
@@ -215,10 +216,44 @@ class Morpheus::Cli::StorageProvidersCommand
215
216
  elsif options['providerType']
216
217
  storage_provider_type_code = options['providerType'].to_s
217
218
  else
218
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'providerType', 'fieldLabel' => 'Provider Type', 'type' => 'select', 'selectOptions' => get_storage_provider_types(), 'required' => true, 'description' => 'Choose a storage bucket type.'}], options, @api_client, {})
219
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'providerType',
220
+ 'fieldLabel' => 'Provider Type',
221
+ 'type' => 'select',
222
+ 'selectOptions' => get_storage_provider_types(),
223
+ 'required' => true,
224
+ 'description' => 'Choose a storage bucket type.'}],
225
+ options, @api_client, {})
219
226
  storage_provider_type_code = v_prompt['providerType'] unless v_prompt['providerType'].nil?
220
227
  end
221
- payload['storageBucket']['providerType'] = storage_provider_type_code
228
+ if storage_provider_type_code == 'amazonS3'
229
+ payload['storageBucket']['providerType'] = 's3' # cloud provided amazonS3
230
+ else
231
+ payload['storageBucket']['providerType'] = storage_provider_type_code
232
+ end
233
+
234
+ # Storage Service (only for amazonS3)
235
+ storage_server_type_id = nil
236
+ storage_server_id = nil
237
+ if storage_provider_type_code == 'amazonS3'
238
+ storage_server_type = @api_client.storage_server_types.list({max:1000})['storageServerTypes'].find {|it| it['code'].downcase == storage_provider_type_code.downcase }
239
+ if options['storageServer']
240
+ storage_server_id = options['storageServer']
241
+ else
242
+ if storage_server_type.nil?
243
+ raise_command_error "error: no storage server type found for amazonS3"
244
+ end
245
+ Morpheus::Logging::DarkPrinter.puts "Finding storage services..." if Morpheus::Logging.debug?
246
+ storage_server_options = @storage_servers_interface.list({max:1000, 'typeId': storage_server_type['id']})['storageServers'].collect {|it| {'name' => it['name'], 'value' => it['id'] } }
247
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'storageServer',
248
+ 'fieldLabel' => 'Storage Server',
249
+ 'type' => 'select',
250
+ 'selectOptions' => storage_server_options,
251
+ 'required' => true,
252
+ 'description' => 'Choose a connected storage service.'}], options, @api_client, {})
253
+ storage_server_id = v_prompt['storageServer'] unless v_prompt['storageServer'].nil?
254
+ end
255
+ payload['storageBucket']['storageServer'] = storage_server_id.to_s # api before 8.0.11 expects a string instead of a number, oooof
256
+ end
222
257
 
223
258
  # Provider Type Specific Options
224
259
  provider_type_option_types = nil
@@ -232,6 +267,15 @@ class Morpheus::Cli::StorageProvidersCommand
232
267
  {'fieldContext' => 'config', 'fieldName' => 'region', 'fieldLabel' => 'Region', 'type' => 'text', 'required' => false, 'description' => 'Optional Amazon region if creating a new bucket.'},
233
268
  {'fieldContext' => 'config', 'fieldName' => 'endpoint', 'fieldLabel' => 'Endpoint URL', 'type' => 'text', 'required' => false, 'description' => 'Optional endpoint URL if pointing to an object store other than amazon that mimics the Amazon S3 APIs.'}
234
269
  ]
270
+ elsif storage_provider_type_code == 'amazonS3'
271
+ # print_h2 "Amazon S3 Provided by Cloud Options"
272
+ provider_type_option_types = [
273
+ {'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''},
274
+ {'fieldName' => 'createBucket', 'fieldLabel' => 'Create Bucket', 'type' => 'checkbox', 'required' => false, 'defaultValue' => false, 'description' => 'Create the bucket if it does not exist.'},
275
+ {'fieldContext' => 'config', 'fieldName' => 'region', 'fieldLabel' => 'Region', 'type' => 'text', 'required' => false, 'description' => 'Optional Amazon region if creating a new bucket.'},
276
+ {'fieldContext' => 'config', 'fieldName' => 'endpoint', 'fieldLabel' => 'Endpoint URL', 'type' => 'text', 'required' => false, 'description' => 'Optional endpoint URL if pointing to an object store other than amazon that mimics the Amazon S3 APIs.'}
277
+ ]
278
+
235
279
  elsif storage_provider_type_code == 'azure'
236
280
  # print_h2 "Azure Options"
237
281
  provider_type_option_types = [
@@ -1215,14 +1259,15 @@ class Morpheus::Cli::StorageProvidersCommand
1215
1259
 
1216
1260
  def get_storage_provider_types()
1217
1261
  [
1218
- {'name' => 'Amazon S3', 'value' => 's3'},
1262
+ {'name' => 'Amazon S3', 'value' => 'amazonS3'},
1219
1263
  {'name' => 'Alibaba', 'value' => 'alibaba'},
1220
1264
  {'name' => 'Azure', 'value' => 'azure'},
1221
1265
  {'name' => 'CIFS', 'value' => 'cifs'},
1222
1266
  {'name' => 'Local Storage', 'value' => 'local'},
1223
1267
  {'name' => 'NFSv3', 'value' => 'nfs'},
1224
1268
  {'name' => 'Openstack Swift', 'value' => 'openstack'},
1225
- {'name' => 'Rackspace CDN', 'value' => 'rackspace'}
1269
+ {'name' => 'Rackspace CDN', 'value' => 'rackspace'},
1270
+ {'name' => 'S3', 'value' => 's3'},
1226
1271
  ]
1227
1272
  end
1228
1273
 
@@ -1117,6 +1117,10 @@ module Morpheus::Cli::ProvisioningHelper
1117
1117
  datastore_options << {"id" => it["value"] || it["id"], "name" => it["name"], "value" => it["value"] || it["id"]}
1118
1118
  end
1119
1119
  end
1120
+ storage_profiles = []
1121
+ if provision_type['storageProfiles']
1122
+ storage_profiles = provision_type['storageProfiles'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }.collect {|it| {'name' => it['name'], 'value' => it['code'], 'isDefault' => it['isDefault']} }
1123
+ end
1120
1124
 
1121
1125
  #puts "Configure Root Volume"
1122
1126
 
@@ -1193,6 +1197,10 @@ module Morpheus::Cli::ProvisioningHelper
1193
1197
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => 'Root Datastore', 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.', 'defaultValue' => default_datastore ? default_datastore['name'] : volume['datastoreId']}], options[:options])
1194
1198
  volume['datastoreId'] = v_prompt[field_context]['datastoreId']
1195
1199
  end
1200
+ if !storage_profiles.empty?
1201
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageProfile', 'type' => 'select', 'fieldLabel' => 'Root Storage Profile', 'selectOptions' => storage_profiles, 'required' => false, 'description' => 'Choose a storage profile.'}], options[:options])
1202
+ volume['storageProfile'] = v_prompt[field_context]['storageProfile'] if v_prompt[field_context] && !v_prompt[field_context]['storageProfile'].to_s.empty?
1203
+ end
1196
1204
 
1197
1205
  volumes << volume
1198
1206
 
@@ -1263,7 +1271,11 @@ module Morpheus::Cli::ProvisioningHelper
1263
1271
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Datastore", 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.', 'defaultValue' => volume['datastoreId']}], options[:options])
1264
1272
  volume['datastoreId'] = v_prompt[field_context]['datastoreId']
1265
1273
  end
1266
-
1274
+ if !storage_profiles.empty?
1275
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageProfile', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Profile", 'selectOptions' => storage_profiles, 'required' => false, 'description' => 'Choose a storage profile.'}], options[:options])
1276
+ volume['storageProfile'] = v_prompt[field_context]['storageProfile'] if v_prompt[field_context] && !v_prompt[field_context]['storageProfile'].to_s.empty?
1277
+ end
1278
+
1267
1279
  volumes << volume
1268
1280
 
1269
1281
  volume_index += 1
@@ -1347,7 +1359,10 @@ module Morpheus::Cli::ProvisioningHelper
1347
1359
  end
1348
1360
  end
1349
1361
  end
1350
-
1362
+ storage_profiles = []
1363
+ if provision_type['storageProfiles']
1364
+ storage_profiles = provision_type['storageProfiles'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }.collect {|it| {'name' => it['name'], 'value' => it['code'], 'isDefault' => it['isDefault']} }
1365
+ end
1351
1366
  #puts "Configure Root Volume"
1352
1367
 
1353
1368
  field_context = "rootVolume"
@@ -1385,6 +1400,9 @@ module Morpheus::Cli::ProvisioningHelper
1385
1400
  if !current_root_volume['controllerMountPoint'].to_s.empty?
1386
1401
  volume['controllerMountPoint'] = current_root_volume['controllerMountPoint']
1387
1402
  end
1403
+ if !current_root_volume['storageProfile'].to_s.empty?
1404
+ volume['storageProfile'] = current_root_volume['storageProfile']
1405
+ end
1388
1406
  if plan_info['rootDiskCustomizable'] && storage_type && storage_type['customLabel']
1389
1407
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Root Volume Label', 'required' => true, 'description' => 'Enter a volume label.', 'defaultValue' => volume['name']}], options[:options])
1390
1408
  volume['name'] = v_prompt[field_context]['name']
@@ -1413,7 +1431,10 @@ module Morpheus::Cli::ProvisioningHelper
1413
1431
  # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => 'Root Datastore', 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.'}], options[:options])
1414
1432
  # volume['datastoreId'] = v_prompt[field_context]['datastoreId']
1415
1433
  # end
1416
-
1434
+ if !storage_profiles.empty?
1435
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageProfile', 'type' => 'select', 'fieldLabel' => 'Root Storage Profile', 'selectOptions' => storage_profiles, 'required' => false, 'description' => 'Choose a storage profile.', 'defaultValue' => volume['storageProfile']}], options[:options])
1436
+ volume['storageProfile'] = v_prompt[field_context]['storageProfile'] if v_prompt[field_context] && !v_prompt[field_context]['storageProfile'].to_s.empty?
1437
+ end
1417
1438
  volumes << volume
1418
1439
 
1419
1440
  # modify or delete existing data volumes
@@ -1443,6 +1464,9 @@ module Morpheus::Cli::ProvisioningHelper
1443
1464
  if !current_volume['controllerMountPoint'].to_s.empty?
1444
1465
  volume['controllerMountPoint'] = current_volume['controllerMountPoint']
1445
1466
  end
1467
+ if !current_volume['storageProfile'].to_s.empty?
1468
+ volume['storageProfile'] = current_volume['storageProfile']
1469
+ end
1446
1470
  volumes << volume
1447
1471
  else
1448
1472
  # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageType', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Storage Type", 'selectOptions' => storage_types, 'required' => true, 'skipSingleOption' => true, 'description' => 'Choose a storage type.'}], options[:options])
@@ -1471,7 +1495,9 @@ module Morpheus::Cli::ProvisioningHelper
1471
1495
  if !current_volume['controllerMountPoint'].to_s.empty?
1472
1496
  volume['controllerMountPoint'] = current_volume['controllerMountPoint']
1473
1497
  end
1474
-
1498
+ if !current_volume['storageProfile'].to_s.empty?
1499
+ volume['storageProfile'] = current_volume['storageProfile']
1500
+ end
1475
1501
  if plan_info['customizeVolume'] && storage_type['customLabel']
1476
1502
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "Disk #{volume_index} Volume Label", 'required' => true, 'description' => 'Enter a volume label.', 'defaultValue' => volume['name']}], options[:options])
1477
1503
  volume['name'] = v_prompt[field_context]['name']
@@ -1499,6 +1525,10 @@ module Morpheus::Cli::ProvisioningHelper
1499
1525
  # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Datastore", 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.'}], options[:options])
1500
1526
  # volume['datastoreId'] = v_prompt[field_context]['datastoreId']
1501
1527
  # end
1528
+ if !storage_profiles.empty?
1529
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageProfile', 'type' => 'select', 'fieldLabel' => 'Root Storage Profile', 'selectOptions' => storage_profiles, 'required' => false, 'description' => 'Choose a storage profile.', 'defaultValue' => current_volume['storageProfile']}], options[:options])
1530
+ volume['storageProfile'] = v_prompt[field_context]['storageProfile'] if v_prompt[field_context] && !v_prompt[field_context]['storageProfile'].to_s.empty?
1531
+ end
1502
1532
 
1503
1533
  volumes << volume
1504
1534
 
@@ -1572,6 +1602,10 @@ module Morpheus::Cli::ProvisioningHelper
1572
1602
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'datastoreId', 'type' => 'select', 'fieldLabel' => "Disk #{volume_index} Datastore", 'selectOptions' => datastore_options, 'required' => true, 'description' => 'Choose a datastore.', 'defaultValue' => current_root_volume['datastoreId']}], options[:options])
1573
1603
  volume['datastoreId'] = v_prompt[field_context]['datastoreId'] unless v_prompt[field_context]['datastoreId'].to_s.empty?
1574
1604
  end
1605
+ if !storage_profiles.empty?
1606
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'storageProfile', 'type' => 'select', 'fieldLabel' => 'Root Storage Profile', 'selectOptions' => storage_profiles, 'required' => false, 'description' => 'Choose a storage profile.'}], options[:options])
1607
+ volume['storageProfile'] = v_prompt[field_context]['storageProfile'] if v_prompt[field_context] && !v_prompt[field_context]['storageProfile'].to_s.empty?
1608
+ end
1575
1609
 
1576
1610
  volumes << volume
1577
1611
 
@@ -716,7 +716,7 @@ module Morpheus
716
716
  end
717
717
  else
718
718
  found_default_option = select_options.find {|opt| opt[value_field].to_s == default_value.to_s || opt['name'] == default_value.to_s}
719
- found_default_option = select_options.find {|opt| opt[value_field].to_s.start_with?(default_value.to_s) || opt['name'].to_s.start_with?(default_value.to_s)} if !found_default_option
719
+ #found_default_option = select_options.find {|opt| opt[value_field].to_s.start_with?(default_value.to_s) || opt['name'].to_s.start_with?(default_value.to_s)} if !found_default_option
720
720
  if found_default_option
721
721
  default_value = found_default_option['name'] # name is prettier than value
722
722
  end
@@ -1221,7 +1221,10 @@ module Morpheus
1221
1221
  #Readline.input = $stdin
1222
1222
  Readline.completion_append_character = ""
1223
1223
  Readline.basic_word_break_characters = ''
1224
- Readline.completion_proc = proc {|s| Readline::FILENAME_COMPLETION_PROC.call(s) }
1224
+ Readline.completion_proc = proc {|s|
1225
+ # FILENAME_COMPLETION_PROC is nil in newer rubies
1226
+ Readline::FILENAME_COMPLETION_PROC.call(s) rescue []
1227
+ }
1225
1228
  input = Readline.readline("#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? (' (' + option_type['fieldAddOn'] + ') ') : '' }#{optional_label(option_type)}#{option_type['defaultValue'] ? ' ['+option_type['defaultValue'].to_s+']' : ''}: ", false).to_s
1226
1229
  input = input.chomp.strip
1227
1230
  #input = $stdin.gets.chomp!
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "8.0.10"
4
+ VERSION = "8.0.11"
5
5
  end
6
6
  end
data/morpheus-cli.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.required_ruby_version = '>= 2.5.1' # according to http.rb doc
22
+ spec.add_dependency "tins", '~> 1.43.0'
22
23
  spec.add_dependency "public_suffix", "4.0.7" # https://github.com/weppos/publicsuffix-ruby/blob/main/CHANGELOG.md
23
24
  spec.add_dependency "ffi", "1.15.5" # Fix for mismatched deps: https://github.com/ffi/ffi/issues/1103
24
25
  spec.add_development_dependency "bundler", "~> 2.2"
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: 8.0.10
4
+ version: 8.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Estes
@@ -11,8 +11,22 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2025-10-06 00:00:00.000000000 Z
14
+ date: 2025-11-19 00:00:00.000000000 Z
15
15
  dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: tins
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: 1.43.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 1.43.0
16
30
  - !ruby/object:Gem::Dependency
17
31
  name: public_suffix
18
32
  requirement: !ruby/object:Gem::Requirement