morpheus-cli 5.2.0 → 5.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f4b5a29dcfa1a915ab2d3fed9ad07197d2a760758b2bc3b76e72cf6899c4372
4
- data.tar.gz: 59c981a5aede057b69e08f5c717d27c884bdd64aed84fb81361b35291b3aaf72
3
+ metadata.gz: 4409a856333a1b2957649aac67f62677b943706754ebc810c614fa5f879b120d
4
+ data.tar.gz: bb968663da852f4ea631fc9b0c89c115f6fb1067049585953c33b7c24e4b284a
5
5
  SHA512:
6
- metadata.gz: 678ff7f73923c9883968ee8bba29b8d75d5464a4899ca812477ce943b25f758c74f187a481c781500928206c4d540d5153f858ee4e2242cfb24cc2604be1602d
7
- data.tar.gz: c27881081abb71b05eceb4857280f51a4f838e9a568658baa34385afe7fc2b86be61eb31a070a4e3a9381000337ceb9b11f58fe8572fff8066882225133742ba
6
+ metadata.gz: 2be204c65dd3c2a35ce5ac7170e70a2297aa34ee1348db2fc736a5915a2678c0c45361269a801db228f202e27dcdcfaaf69afc7f49d9eded429c16d5381dd28f
7
+ data.tar.gz: a5018a327ae43078e4661c1c3744e75b6cc1adfc8854ca09d99a0a47f8e0678d2f8914b46d724bd8189011b13a42f2ac5779b3980611af1655cdebc4393a3e53
data/.gitignore CHANGED
@@ -21,3 +21,4 @@ tmp
21
21
  *.a
22
22
  mkmf.log
23
23
  .DS_Store
24
+ .idea
@@ -530,9 +530,10 @@ class Morpheus::Cli::Hosts
530
530
  puts records_as_csv([json_response['server']], options)
531
531
  return 0
532
532
  end
533
- server = json_response['server']
533
+ server = json_response['server'] || json_response['host'] || {}
534
534
  #stats = server['stats'] || json_response['stats'] || {}
535
535
  stats = json_response['stats'] || {}
536
+ tags = server['tags'] || server['metadata']
536
537
  title = "Host Details"
537
538
  print_h1 title, [], options
538
539
  print cyan
@@ -541,6 +542,7 @@ class Morpheus::Cli::Hosts
541
542
  "Name" => 'name',
542
543
  "Hostname" => 'hostname',
543
544
  "Description" => 'description',
545
+ "Tags" => lambda {|it| tags ? format_metadata(tags) : '' },
544
546
  "Owner" => lambda {|it| it['owner'] ? it['owner']['username'] : '' },
545
547
  "Tenant" => lambda {|it| it['account'] ? it['account']['name'] : '' },
546
548
  #"Group" => lambda {|it| it['group'] ? it['group']['name'] : '' },
@@ -564,6 +566,7 @@ class Morpheus::Cli::Hosts
564
566
  # server_columns.delete("Tenant") if multi_tenant != true
565
567
  server_columns.delete("Cost") if server['hourlyCost'].to_f == 0
566
568
  server_columns.delete("Price") if server['hourlyPrice'].to_f == 0 || server['hourlyPrice'] == server['hourlyCost']
569
+ server_columns.delete("Tags") if tags.nil? || tags.empty?
567
570
 
568
571
  print_description_list(server_columns, server)
569
572
 
@@ -990,6 +993,19 @@ class Morpheus::Cli::Hosts
990
993
  opts.on('--power-schedule-type ID', String, "Power Schedule Type ID") do |val|
991
994
  params['powerScheduleType'] = val == "null" ? nil : val
992
995
  end
996
+ opts.on('--tags LIST', String, "Tags in the format 'name:value, name:value'. This will add and remove tags.") do |val|
997
+ options[:tags] = val
998
+ end
999
+ opts.on('--metadata LIST', String, "Alias for --tags.") do |val|
1000
+ options[:tags] = val
1001
+ end
1002
+ opts.add_hidden_option('--metadata')
1003
+ opts.on('--add-tags TAGS', String, "Add Tags in the format 'name:value, name:value'. This will only add/update tags.") do |val|
1004
+ options[:add_tags] = val
1005
+ end
1006
+ opts.on('--remove-tags TAGS', String, "Remove Tags in the format 'name, name:value'. This removes tags, the :value component is optional and must match if passed.") do |val|
1007
+ options[:remove_tags] = val
1008
+ end
993
1009
  # opts.on('--created-by ID', String, "Created By User ID") do |val|
994
1010
  # params['createdById'] = val
995
1011
  # end
@@ -1008,6 +1024,18 @@ class Morpheus::Cli::Hosts
1008
1024
  new_group = nil
1009
1025
  passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
1010
1026
  params.deep_merge!(passed_options) unless passed_options.empty?
1027
+ # metadata tags
1028
+ if options[:tags]
1029
+ params['tags'] = parse_metadata(options[:tags])
1030
+ else
1031
+ # params['tags'] = prompt_metadata(options)
1032
+ end
1033
+ if options[:add_tags]
1034
+ params['addTags'] = parse_metadata(options[:add_tags])
1035
+ end
1036
+ if options[:remove_tags]
1037
+ params['removeTags'] = parse_metadata(options[:remove_tags])
1038
+ end
1011
1039
  payload = nil
1012
1040
  if options[:payload]
1013
1041
  payload = options[:payload]
@@ -1919,7 +1947,8 @@ class Morpheus::Cli::Hosts
1919
1947
  snapshot_column_definitions = {
1920
1948
  "ID" => lambda {|it| it['id'] },
1921
1949
  "Name" => lambda {|it| it['name'] },
1922
- "Description" => lambda {|it| it['snapshotType'] ? (it['snapshotType']['name'] || it['snapshotType']['code']) : '' },
1950
+ "Description" => lambda {|it| it['description'] },
1951
+ # "Type" => lambda {|it| it['snapshotType'] },
1923
1952
  "Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
1924
1953
  "Status" => lambda {|it| format_snapshot_status(it) }
1925
1954
  }
@@ -459,17 +459,58 @@ class Morpheus::Cli::Instances
459
459
  options[:instance_name] = args[0]
460
460
  end
461
461
 
462
- # use active group by default
463
- options[:group] ||= @active_group_id
464
- options[:select_datastore] = true
465
- options[:name_required] = true
466
462
  begin
467
463
  payload = nil
468
464
  if options[:payload]
469
465
  payload = options[:payload]
470
466
  # support -O OPTION switch on top of --payload
471
467
  payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
468
+ # obviously should support every option that prompt supports on top of -- payload as well
469
+ # group, cloud and type for now
470
+ # todo: also support :layout, service_plan, :resource_pool, etc.
471
+ group = nil
472
+ if options[:group]
473
+ group = find_group_by_name_or_id_for_provisioning(options[:group])
474
+ if group.nil?
475
+ return 1, "group not found by #{options[:group]}"
476
+ end
477
+ #payload["siteId"] = group["id"]
478
+ payload.deep_merge!({"instance" => {"site" => {"id" => group["id"]} } })
479
+ end
480
+ if options[:cloud]
481
+ group_id = group ? group["id"] : ((payload["instance"] && payload["instance"]["site"].is_a?(Hash)) ? payload["instance"]["site"]["id"] : nil)
482
+ cloud = find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud])
483
+ if cloud.nil?
484
+ return 1, "cloud not found by #{options[:cloud]}"
485
+ end
486
+ payload["zoneId"] = cloud["id"]
487
+ payload.deep_merge!({"instance" => {"cloud" => cloud["name"] } })
488
+ end
489
+ if options[:cloud]
490
+ group_id = group ? group["id"] : ((payload["instance"] && payload["instance"]["site"].is_a?(Hash)) ? payload["instance"]["site"]["id"] : nil)
491
+ cloud = find_cloud_by_name_or_id_for_provisioning(group_id, options[:cloud])
492
+ if cloud.nil?
493
+ return 1, "cloud not found by #{options[:cloud]}"
494
+ end
495
+ payload["zoneId"] = cloud["id"]
496
+ payload.deep_merge!({"instance" => {"cloud" => cloud["name"] } })
497
+ end
498
+ if options[:instance_type_code]
499
+ # should just use find_instance_type_by_name_or_id
500
+ # note that the api actually will match name name or code
501
+ instance_type = (options[:instance_type_code].to_s =~ /\A\d{1,}\Z/) ? find_instance_type_by_id(options[:instance_type_code]) : find_instance_type_by_code(options[:instance_type_code])
502
+ if instance_type.nil?
503
+ return 1, "instance type not found by #{options[:cloud]}"
504
+ end
505
+ payload.deep_merge!({"instance" => {"type" => instance_type["code"] } })
506
+ payload.deep_merge!({"instance" => {"instanceType" => {"code" => instance_type["code"]} } })
507
+ end
508
+
472
509
  else
510
+ # use active group by default
511
+ options[:group] ||= @active_group_id
512
+ options[:select_datastore] = true
513
+ options[:name_required] = true
473
514
  # prompt for all the instance configuration options
474
515
  # this provisioning helper method handles all (most) of the parsing and prompting
475
516
  # and it relies on the method to exit non-zero on error, like a bad CLOUD or TYPE value
@@ -562,16 +603,17 @@ class Morpheus::Cli::Instances
562
603
  opts.on('--group GROUP', String, "Group Name or ID") do |val|
563
604
  options[:group] = val
564
605
  end
565
- opts.on('--tags LIST', String, "Metadata tags in the format 'ping=pong,flash=bang'") do |val|
566
- options[:metadata] = val
606
+ opts.on('--labels LIST', String, "Labels (keywords) in the format 'foo, bar'") do |val|
607
+ params['labels'] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
567
608
  end
568
- opts.on('--metadata LIST', String, "Metadata tags in the format 'ping=pong,flash=bang'") do |val|
569
- options[:metadata] = val
609
+ opts.on('--tags LIST', String, "Tags in the format 'name:value, name:value'. This will add and remove tags.") do |val|
610
+ options[:tags] = val
570
611
  end
571
- opts.add_hidden_option('--metadata')
572
- opts.on('--labels LIST', String, "Labels (keywords) in the format 'foo, bar'") do |val|
573
- # todo switch this from 'tags' to 'labels'
574
- params['tags'] = val.split(',').collect {|it| it.to_s.strip }.compact.uniq.join(',')
612
+ opts.on('--add-tags TAGS', String, "Add Tags in the format 'name:value, name:value'. This will only add/update tags.") do |val|
613
+ options[:add_tags] = val
614
+ end
615
+ opts.on('--remove-tags TAGS', String, "Remove Tags in the format 'name, name:value'. This removes tags, the :value component is optional and must match if passed.") do |val|
616
+ options[:remove_tags] = val
575
617
  end
576
618
  opts.on('--power-schedule-type ID', String, "Power Schedule Type ID") do |val|
577
619
  params['powerScheduleType'] = val == "null" ? nil : val
@@ -627,32 +669,17 @@ class Morpheus::Cli::Instances
627
669
  payload['instance']['site'] = {'id' => group['id']}
628
670
  end
629
671
  # metadata tags
630
- # if options[:options]['metadata'].is_a?(Array) && !options[:metadata]
631
- # options[:metadata] = options[:options]['metadata']
632
- # end
633
- if options[:metadata]
634
- metadata = []
635
- if options[:metadata] == "[]" || options[:metadata] == "null"
636
- payload['instance']['metadata'] = []
637
- elsif options[:metadata].is_a?(Array)
638
- payload['instance']['metadata'] = options[:metadata]
639
- else
640
- # parse string into format name:value, name:value
641
- # merge IDs from current metadata
642
- # todo: should allow quoted semicolons..
643
- metadata_list = options[:metadata].split(",").select {|it| !it.to_s.empty? }
644
- metadata_list = metadata_list.collect do |it|
645
- metadata_pair = it.split(":")
646
- if metadata_pair.size == 1 && it.include?("=")
647
- metadata_pair = it.split("=")
648
- end
649
- row = {}
650
- row['name'] = metadata_pair[0].to_s.strip
651
- row['value'] = metadata_pair[1].to_s.strip
652
- row
653
- end
654
- payload['instance']['metadata'] = metadata_list
655
- end
672
+ if options[:tags]
673
+ # api version 4.2.5 and later supports tags, older versions expect metadata
674
+ # todo: use tags instead like everywhere else
675
+ # payload['instance']['tags'] = parse_metadata(options[:tags])
676
+ payload['instance']['metadata'] = parse_metadata(options[:tags])
677
+ end
678
+ if options[:add_tags]
679
+ payload['instance']['addTags'] = parse_metadata(options[:add_tags])
680
+ end
681
+ if options[:remove_tags]
682
+ payload['instance']['removeTags'] = parse_metadata(options[:remove_tags])
656
683
  end
657
684
  if payload['instance'].empty? && params.empty? && options[:owner].nil?
658
685
  raise_command_error "Specify at least one option to update.\n#{optparse}"
@@ -1256,11 +1283,14 @@ class Morpheus::Cli::Instances
1256
1283
  # metadata tags used to be returned as metadata and are now returned as tags
1257
1284
  # the problem is tags is what we used to call Labels (keywords)
1258
1285
  # the api will change to tags and labels, so handle the old format as long as metadata is returned.
1259
- tags, labels = nil, nil
1260
- if instance.key?('metadata')
1261
- tags, labels = instance['metadata'], instance['tags']
1286
+ labels = nil
1287
+ tags = nil
1288
+ if instance.key?('labels')
1289
+ labels = instance['labels']
1290
+ tags = instance['tags']
1262
1291
  else
1263
- tags, labels = instance['tags'], instance['labels']
1292
+ labels = instance['tags']
1293
+ tags = instance['metadata']
1264
1294
  end
1265
1295
  # containers are fetched via separate api call
1266
1296
  containers = nil
@@ -1302,7 +1332,7 @@ class Morpheus::Cli::Instances
1302
1332
  # "Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
1303
1333
  # "Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
1304
1334
  "Environment" => 'instanceContext',
1305
- "Labels" => lambda {|it| it['tags'] ? it['tags'].join(',') : '' },
1335
+ "Labels" => lambda {|it| labels ? labels.join(',') : '' },
1306
1336
  "Tags" => lambda {|it| tags ? tags.collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' },
1307
1337
  "Owner" => lambda {|it|
1308
1338
  if it['owner']
@@ -3020,7 +3050,8 @@ EOT
3020
3050
  snapshot_column_definitions = {
3021
3051
  "ID" => lambda {|it| it['id'] },
3022
3052
  "Name" => lambda {|it| it['name'] },
3023
- "Description" => lambda {|it| it['snapshotType'] ? (it['snapshotType']['name'] || it['snapshotType']['code']) : '' },
3053
+ "Description" => lambda {|it| it['description'] },
3054
+ # "Type" => lambda {|it| it['snapshotType'] },
3024
3055
  "Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
3025
3056
  "Status" => lambda {|it| format_snapshot_status(it) }
3026
3057
  }
@@ -272,7 +272,7 @@ class Morpheus::Cli::InvoicesCommand
272
272
  {"ESTIMATE" => lambda {|it| format_boolean(it['estimate']) } },
273
273
  {"ACTIVE" => lambda {|it| format_boolean(it['active']) } },
274
274
  {"ITEMS" => lambda {|it| it['lineItems'].size rescue '' } },
275
- {"TAGS" => lambda {|it| it['metadata'] ? it['metadata'].collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' } },
275
+ {"TAGS" => lambda {|it| (it['metadata'] || it['tags']) ? (it['metadata'] || it['tags']).collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' } },
276
276
  ]
277
277
  if show_projects
278
278
  columns += [
@@ -438,7 +438,7 @@ EOT
438
438
  "Ref Start" => lambda {|it| format_dt(it['refStart']) },
439
439
  "Ref End" => lambda {|it| format_dt(it['refEnd']) },
440
440
  "Items" => lambda {|it| it['lineItems'].size rescue '' },
441
- "Tags" => lambda {|it| it['metadata'] ? it['metadata'].collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' },
441
+ "Tags" => lambda {|it| (it['metadata'] || it['tags']) ? (it['metadata'] || it['tags']).collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' },
442
442
  "Project ID" => lambda {|it| it['project'] ? it['project']['id'] : '' },
443
443
  "Project Name" => lambda {|it| it['project'] ? it['project']['name'] : '' },
444
444
  "Project Tags" => lambda {|it| it['project'] ? format_metadata(it['project']['tags']) : '' },
@@ -454,7 +454,8 @@ EOT
454
454
  description_cols.delete("Project Name")
455
455
  description_cols.delete("Project Tags")
456
456
  end
457
- if invoice['metadata'].nil? || invoice['metadata'].empty?
457
+ tags = (invoice['metadata'] || invoice['tags'])
458
+ if tags.nil? || tags.empty?
458
459
  description_cols.delete("Tags")
459
460
  end
460
461
  if !['ComputeServer','Instance','Container'].include?(invoice['refType'])
@@ -596,14 +596,12 @@ module Morpheus::Cli::ProvisioningHelper
596
596
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'environment', 'fieldLabel' => 'Environment', 'type' => 'select', 'required' => false, 'selectOptions' => get_available_environments()}], options[:options])
597
597
  payload['instance']['instanceContext'] = v_prompt['environment'] if !v_prompt['environment'].empty?
598
598
 
599
- # Labels (Provisioning API still refers to these as tags)
600
- # and tags (metadata tags) is called metadata.
601
- # todo: switch this from 'tags' to labels' when the api changes
599
+ # Labels (used to be called tags)
602
600
  if options[:labels]
603
- payload['instance']['tags'] = options[:labels].is_a?(Array) ? options[:labels] : options[:labels].to_s.split(',').collect {|it| it.to_s.strip }.compact.uniq
601
+ payload['instance']['labels'] = options[:labels].is_a?(Array) ? options[:labels] : options[:labels].to_s.split(',').collect {|it| it.to_s.strip }.compact.uniq
604
602
  else
605
603
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'labels', 'fieldLabel' => 'Labels', 'type' => 'text', 'required' => false}], options[:options])
606
- payload['instance']['tags'] = v_prompt['tags'].split(',').collect {|it| it.to_s.strip }.compact.uniq if !v_prompt['tags'].empty?
604
+ payload['instance']['labels'] = v_prompt['labels'].split(',').collect {|it| it.to_s.strip }.compact.uniq if !v_prompt['labels'].empty?
607
605
  end
608
606
 
609
607
  # Version and Layout
@@ -1693,6 +1691,15 @@ module Morpheus::Cli::ProvisioningHelper
1693
1691
  row = {}
1694
1692
  row['name'] = metadata_pair[0].to_s.strip
1695
1693
  row['value'] = metadata_pair[1].to_s.strip
1694
+ # hacky way to set masked flag to true of false to (masked) in the value itself
1695
+ if(row['value'].include?("(masked)"))
1696
+ row['value'] = row['value'].gsub("(masked)", "").strip
1697
+ row['masked'] = true
1698
+ end
1699
+ if(row['value'].include?("(unmasked)"))
1700
+ row['value'] = row['value'].gsub("(unmasked)", "").strip
1701
+ row['masked'] = false
1702
+ end
1696
1703
  row
1697
1704
  end
1698
1705
  metadata = metadata_list
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Morpheus
3
3
  module Cli
4
- VERSION = "5.2.0"
4
+ VERSION = "5.2.1"
5
5
  end
6
6
  end
@@ -299,7 +299,7 @@ EOT
299
299
  opts.on('--tags LIST', String, "Tags in the format 'name:value, name:value'. This will add and remove tags.") do |val|
300
300
  options[:tags] = val
301
301
  end
302
- opts.on('--add-tags TAGS', String, "Add Tags in the format 'name:value, name:value'. This will only add/update project tags.") do |val|
302
+ opts.on('--add-tags TAGS', String, "Add Tags in the format 'name:value, name:value'. This will only add/update tags.") do |val|
303
303
  options[:add_tags] = val
304
304
  end
305
305
  opts.on('--remove-tags TAGS', String, "Remove Tags in the format 'name, name:value'. This removes tags, the :value component is optional and must match if passed.") do |val|
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: 5.2.0
4
+ version: 5.2.1
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: 2020-11-10 00:00:00.000000000 Z
14
+ date: 2020-11-18 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler