morpheus-cli 5.3.2 → 5.3.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,6 +8,7 @@ class Morpheus::Cli::NetworksCommand
8
8
  include Morpheus::Cli::CliCommand
9
9
  include Morpheus::Cli::WhoamiHelper
10
10
  include Morpheus::Cli::InfrastructureHelper
11
+ include Morpheus::Cli::ProvisioningHelper
11
12
 
12
13
  set_command_name :networks
13
14
 
@@ -25,6 +26,7 @@ class Morpheus::Cli::NetworksCommand
25
26
  @api_client = establish_remote_appliance_connection(opts)
26
27
  @networks_interface = @api_client.networks
27
28
  @network_types_interface = @api_client.network_types
29
+ @network_services_interface = @api_client.network_services
28
30
  @subnets_interface = @api_client.subnets
29
31
  @subnet_types_interface = @api_client.subnet_types
30
32
  @groups_interface = @api_client.groups
@@ -97,7 +99,7 @@ class Morpheus::Cli::NetworksCommand
97
99
  networks.each do |network|
98
100
  row = {
99
101
  id: network['id'],
100
- name: network['name'],
102
+ name: network['displayName'] || network['name'],
101
103
  type: network['type'] ? network['type']['name'] : '',
102
104
  group: network['group'] ? network['group']['name'] : 'Shared',
103
105
  cloud: network['zone'] ? network['zone']['name'] : '',
@@ -114,7 +116,7 @@ class Morpheus::Cli::NetworksCommand
114
116
  network['subnets'].each do |subnet|
115
117
  subnet_row = {
116
118
  id: subnet['id'],
117
- name: " #{subnet['name']}",
119
+ name: " #{subnet['displayName'] || subnet['name']}",
118
120
  # type: subnet['type'] ? subnet['type']['name'] : '',
119
121
  type: "Subnet",
120
122
  group: network['group'] ? network['group']['name'] : 'Shared',
@@ -288,9 +290,15 @@ class Morpheus::Cli::NetworksCommand
288
290
  opts.on('-t', '--type ID', "Network Type Name or ID") do |val|
289
291
  options['type'] = val
290
292
  end
293
+ opts.on('-s', '--server ID', "Network Server Name or ID") do |val|
294
+ options['server'] = val
295
+ end
291
296
  opts.on('--name VALUE', String, "Name for this network") do |val|
292
297
  options['name'] = val
293
298
  end
299
+ opts.on('--display-name VALUE', String, "Display name for this network") do |val|
300
+ options['displayName'] = val
301
+ end
294
302
  opts.on('--description VALUE', String, "Description of network") do |val|
295
303
  options['description'] = val
296
304
  end
@@ -394,6 +402,17 @@ class Morpheus::Cli::NetworksCommand
394
402
  payload = nil
395
403
  if options[:payload]
396
404
  payload = options[:payload]
405
+
406
+ # backward compat
407
+ if payload['resourcePermissions']
408
+ payload['network'] ||= {}
409
+ payload['network']['resourcePermission'] = payload['resourcePermissions']
410
+ payload.delete('resourcePermissions')
411
+ end
412
+ if payload['network'] && payload['network']['resourcePermissions']
413
+ payload['network']['resourcePermission'] = payload['network']['resourcePermissions']
414
+ payload['network'].delete('resourcePermissions')
415
+ end
397
416
  else
398
417
  # prompt for network options
399
418
  payload = {
@@ -413,6 +432,14 @@ class Morpheus::Cli::NetworksCommand
413
432
  payload['network']['name'] = v_prompt['name']
414
433
  end
415
434
 
435
+ # Display Name
436
+ if options['displayName']
437
+ payload['network']['displayName'] = options['displayName']
438
+ else
439
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'displayName', 'fieldLabel' => 'Display Name', 'type' => 'text', 'required' => false, 'description' => 'Display name for this network.'}], options)
440
+ payload['network']['displayName'] = v_prompt['displayName']
441
+ end
442
+
416
443
  # Description
417
444
  if options['description']
418
445
  payload['network']['description'] = options['description']
@@ -465,42 +492,9 @@ class Morpheus::Cli::NetworksCommand
465
492
  # shared
466
493
  end
467
494
 
468
- # Cloud
469
- cloud = nil
470
- if group
471
- if options[:cloud]
472
- cloud_id = options[:cloud]
473
- cloud = group["clouds"].find {|it| it["id"].to_s == cloud_id.to_s || it["name"].to_s == cloud_id}
474
- if cloud.nil?
475
- print_red_alert "Cloud not found by id #{cloud_id}"
476
- return 1
477
- end
478
- else
479
- api_params = {groupId:group['id']}
480
- cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'optionSource' => 'cloudsForNetworks', 'required' => true, 'description' => 'Select Cloud.'}],options,@api_client,api_params)
481
- cloud_id = cloud_prompt['cloud']
482
- cloud = find_cloud_by_name_or_id(cloud_id) if cloud_id
483
- return 1 if cloud.nil?
484
- end
485
- else
486
- if options[:cloud]
487
- cloud = find_cloud_by_name_or_id(options[:cloud])
488
- # meh, should validate cloud is in the cloudsForNetworks dropdown..
489
- return 1 if cloud.nil?
490
- else
491
- api_params = {}
492
- cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'optionSource' => 'cloudsForNetworks', 'required' => true, 'description' => 'Select Cloud.'}],options,@api_client,api_params)
493
- cloud_id = cloud_prompt['cloud']
494
- cloud = find_cloud_by_name_or_id(cloud_id) if cloud_id
495
- return 1 if cloud.nil?
496
- end
497
- end
498
- payload['network']['zone'] = {'id' => cloud['id']}
499
-
500
495
  # Network Type
501
496
  network_type_id = nil
502
- api_params = {"network.zone.id" => cloud['id']} #{network:{zone:{id: cloud['id']}}}
503
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Network Type', 'type' => 'select', 'optionSource' => 'networkTypesForCloud', 'required' => true, 'description' => 'Choose a network type.'}], options, @api_client, api_params)
497
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Network Type', 'type' => 'select', 'optionSource' => 'creatableNetworkTypes', 'required' => true, 'description' => 'Choose a network type.'}], options, @api_client, {accountId: current_account()['id']})
504
498
  network_type_id = v_prompt['type']
505
499
  if network_type_id.nil? || network_type_id.to_s.empty?
506
500
  print_red_alert "Network Type not found by id '#{options['type']}'"
@@ -517,51 +511,102 @@ class Morpheus::Cli::NetworksCommand
517
511
  return 1
518
512
  end
519
513
 
520
- # CIDR
521
- if options['cidr']
522
- payload['network']['cidr'] = options['cidr']
514
+ if network_type['hasNetworkServer']
515
+ api_params = {networkType: {id: network_type['id']}}
516
+
517
+ # Network Server
518
+ if options['server']
519
+ network_server = @options_interface.options_for_source('networkServer', api_params)['data'].find {|it|
520
+ it['name'] == options['server'] || it['value'].to_s == options['server']
521
+ }
522
+
523
+ if network_server.nil?
524
+ print_red_alert "Network Server not found by name or id '#{options['server']}' for network type '#{options['server']}'"
525
+ return 1
526
+ end
527
+ network_server_id = network_server['value']
528
+ payload['network']['networkServer'] = {'id' => network_server_id}
529
+ else
530
+ network_server_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'server', 'type' => 'select', 'fieldLabel' => 'Network Server', 'optionSource' => 'networkServer', 'required' => true, 'description' => 'Select Network Service.'}],options,@api_client,api_params)
531
+ network_server_id = network_server_prompt['server']
532
+ payload['network']['networkServer'] = {'id' => network_server_id}
533
+ end
523
534
  else
524
- if network_type['cidrEditable']
525
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cidr', 'fieldLabel' => 'CIDR', 'type' => 'text', 'required' => network_type['cidrRequired'], 'description' => ''}], options)
535
+ # Cloud
536
+ cloud = nil
537
+ if group
538
+ if options[:cloud]
539
+ cloud_id = options[:cloud]
540
+ cloud = group["clouds"].find {|it| it["id"].to_s == cloud_id.to_s || it["name"].to_s == cloud_id}
541
+ if cloud.nil?
542
+ print_red_alert "Cloud not found by id #{cloud_id}"
543
+ return 1
544
+ end
545
+ else
546
+ api_params = {groupId:group['id']}
547
+ cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'optionSource' => 'cloudsForNetworks', 'required' => true, 'description' => 'Select Cloud.'}],options,@api_client,api_params)
548
+ cloud_id = cloud_prompt['cloud']
549
+ cloud = find_cloud_by_name_or_id(cloud_id) if cloud_id
550
+ return 1 if cloud.nil?
551
+ end
552
+ else
553
+ if options[:cloud]
554
+ cloud = find_cloud_by_name_or_id(options[:cloud])
555
+ # meh, should validate cloud is in the cloudsForNetworks dropdown..
556
+ return 1 if cloud.nil?
557
+ else
558
+ api_params = {}
559
+ cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'type' => 'select', 'fieldLabel' => 'Cloud', 'optionSource' => 'cloudsForNetworks', 'required' => true, 'description' => 'Select Cloud.'}],options,@api_client,api_params)
560
+ cloud_id = cloud_prompt['cloud']
561
+ cloud = find_cloud_by_name_or_id(cloud_id) if cloud_id
562
+ return 1 if cloud.nil?
563
+ end
564
+ end
565
+ payload['network']['zone'] = {'id' => cloud['id']}
566
+ end
567
+
568
+ # CIDR
569
+ if network_type['hasCidr'] && network_type['cidrEditable']
570
+ if options['cidr']
571
+ payload['network']['cidr'] = options['cidr']
572
+ else
573
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cidr', 'fieldLabel' => network_type['code'] == 'nsxtLogicalSwitch' ? 'Gateway CIDR' : 'CIDR', 'type' => 'text', 'required' => network_type['cidrRequired'], 'description' => ''}], options)
526
574
  payload['network']['cidr'] = v_prompt['cidr']
527
575
  end
528
576
  end
529
577
 
530
578
  # Gateway
531
- if options['gateway']
532
- payload['network']['gateway'] = options['gateway']
533
- else
534
- if network_type['gatewayEditable']
579
+ if network_type['gatewayEditable']
580
+ if options['gateway']
581
+ payload['network']['gateway'] = options['gateway']
582
+ else
535
583
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'gateway', 'fieldLabel' => 'Gateway', 'type' => 'text', 'required' => false, 'description' => ''}], options)
536
584
  payload['network']['gateway'] = v_prompt['gateway']
537
585
  end
538
586
  end
539
587
 
540
- # DNS Primary
541
- if options['dnsPrimary']
542
- payload['network']['dnsPrimary'] = options['dnsPrimary']
543
- else
544
- if network_type['dnsEditable']
588
+ # DNS
589
+ if network_type['dnsEditable']
590
+ if options['dnsPrimary']
591
+ payload['network']['dnsPrimary'] = options['dnsPrimary']
592
+ else
545
593
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'dnsPrimary', 'fieldLabel' => 'DNS Primary', 'type' => 'text', 'required' => false, 'description' => ''}], options)
546
594
  payload['network']['dnsPrimary'] = v_prompt['dnsPrimary']
547
595
  end
548
- end
549
596
 
550
- # DNS Secondary
551
- if options['dnsSecondary']
552
- payload['network']['dnsSecondary'] = options['dnsSecondary']
553
- else
554
- if network_type['dnsEditable']
597
+ if options['dnsSecondary']
598
+ payload['network']['dnsSecondary'] = options['dnsSecondary']
599
+ else
555
600
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'dnsSecondary', 'fieldLabel' => 'DNS Secondary', 'type' => 'text', 'required' => false, 'description' => ''}], options)
556
601
  payload['network']['dnsSecondary'] = v_prompt['dnsSecondary']
557
602
  end
558
603
  end
559
604
 
560
605
  # VLAN ID
561
- if options['vlanId']
562
- payload['network']['vlanId'] = options['vlanId']
563
- else
564
- if network_type['vlanEditable']
606
+ if network_type['vlanIdEditable']
607
+ if options['vlanId']
608
+ payload['network']['vlanId'] = options['vlanId']
609
+ else
565
610
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'vlanId', 'fieldLabel' => 'VLAN ID', 'type' => 'number', 'required' => false, 'description' => ''}], options)
566
611
  payload['network']['vlanId'] = v_prompt['vlanId']
567
612
  end
@@ -570,19 +615,30 @@ class Morpheus::Cli::NetworksCommand
570
615
  # prompt for option types
571
616
  network_type_option_types = network_type['optionTypes']
572
617
  if network_type_option_types && network_type_option_types.size > 0
573
- network_type_params = Morpheus::Cli::OptionTypes.prompt(network_type_option_types,options[:options],@api_client, {zoneId: cloud['id']})
618
+ api_params = {}
619
+ api_params['network.site.id'] = group ? group['id'] : 'shared'
620
+ api_params['network.type.id'] = network_type['id']
621
+ api_params['network.networkServer.id'] = network_server_id if !network_server_id.nil?
622
+ network_type_params = Morpheus::Cli::OptionTypes.prompt(network_type_option_types,options[:options],@api_client, api_params)
574
623
  # network context options belong at network level and not network.network
575
624
  network_context_params = network_type_params.delete('network')
576
625
  payload['network'].deep_merge!(network_context_params) if network_context_params
577
626
  payload['network'].deep_merge!(network_type_params)
627
+ end
578
628
 
629
+ # Active
630
+ if options['active'].nil?
631
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'active', 'fieldLabel' => 'Active', 'type' => 'checkbox', 'required' => false, 'description' => '', 'defaultValue' => true}], options)
632
+ payload['network']['active'] = v_prompt['active']
633
+ else
634
+ payload['network']['active'] = options['active']
579
635
  end
580
636
 
581
637
  # DHCP Server
582
- if options['dhcpServer'] != nil
583
- payload['network']['dhcpServer'] = options['dhcpServer']
584
- else
585
- if network_type['dhcpServerEditable']
638
+ if network_type['dhcpServerEditable']
639
+ if options['dhcpServer'] != nil
640
+ payload['network']['dhcpServer'] = options['dhcpServer']
641
+ else
586
642
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'dhcpServer', 'fieldLabel' => 'DHCP Server', 'type' => 'checkbox', 'required' => false, 'description' => ''}], options)
587
643
  payload['network']['dhcpServer'] = v_prompt['dhcpServer']
588
644
  end
@@ -599,10 +655,10 @@ class Morpheus::Cli::NetworksCommand
599
655
  ## IPAM Options
600
656
 
601
657
  # Network Pool
602
- if options['pool']
603
- payload['network']['pool'] = options['pool'].to_i
604
- else
605
- if network_type['canAssignPool']
658
+ if network_type['canAssignPool']
659
+ if options['pool']
660
+ payload['network']['pool'] = options['pool'].to_i
661
+ else
606
662
  # todo: select dropdown
607
663
  # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pool', 'fieldLabel' => 'Network Pool', 'type' => 'select', 'optionSource' => 'networkPools', 'required' => false, 'description' => ''}], options, @api_client, {zoneId: cloud['id']})
608
664
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'pool', 'fieldLabel' => 'Network Pool', 'type' => 'text', 'required' => false, 'description' => ''}], options)
@@ -620,6 +676,14 @@ class Morpheus::Cli::NetworksCommand
620
676
  payload['network']['networkDomain'] = {'id' => v_prompt['domain'].to_i} unless v_prompt['domain'].to_s.empty?
621
677
  end
622
678
 
679
+ # Search Domains
680
+ if options['searchDomains'] != nil
681
+ payload['network']['searchDomains'] = options['searchDomains']
682
+ else
683
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'searchDomains', 'fieldLabel' => 'Search Domains', 'type' => 'text', 'required' => false, 'description' => ''}], options)
684
+ payload['network']['searchDomains'] = v_prompt['searchDomains']
685
+ end
686
+
623
687
  # Scan Network
624
688
  if options['scanNetwork'] != nil
625
689
  payload['network']['scanNetwork'] = options['scanNetwork']
@@ -654,42 +718,53 @@ class Morpheus::Cli::NetworksCommand
654
718
 
655
719
  # Group Access
656
720
  # Group Access (default is All)
657
- if group_access_all.nil?
658
- if payload['resourcePermissions'].nil?
659
- payload['resourcePermissions'] ||= {}
660
- payload['resourcePermissions']['all'] = true
661
- end
721
+ if !options[:no_prompt] && group_access_all.nil? && group_access_list.nil? && payload['resourcePermission'].nil? && payload['network']['resourcePermission'].nil?
722
+ perm_excludes = ['plans']
723
+ perm_excludes << 'tenants' if options['tenants'] || payload['tenantPermissions'] || payload['network']['tenants']
724
+ perm_excludes << 'visibility' if options['visibility'] || payload['network']['visibility']
725
+ perms = prompt_permissions(options, perm_excludes)
726
+
727
+ payload['network']['resourcePermission'] = perms['resourcePermissions']
728
+ payload['network']['tenants'] = perms['tenantPermissions']['accounts'].collect {|it| {'id': it}} if perms['tenantPermissions']
729
+ payload['network']['visibility'] = perms['resourcePool']['visibility'] if perms['resourcePool']
662
730
  else
663
- payload['resourcePermissions'] ||= {}
664
- payload['resourcePermissions']['all'] = group_access_all
665
- end
666
- if group_access_list != nil
667
- payload['resourcePermissions'] ||= {}
668
- payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id|
669
- site = {"id" => site_id.to_i}
670
- if group_defaults_list && group_defaults_list.include?(site_id)
671
- site["default"] = true
731
+ if !group_access_list.nil?
732
+ payload['network']['resourcePermission'] ||= {}
733
+ payload['network']['resourcePermission']['sites'] = group_access_list.collect do |site_id|
734
+ site = {"id" => site_id.to_i}
735
+ if group_defaults_list && group_defaults_list.include?(site_id)
736
+ site["default"] = true
737
+ end
738
+ site
672
739
  end
673
- site
740
+ elsif !group_access_all.nil?
741
+ payload['network']['resourcePermission'] ||= {}
742
+ payload['network']['resourcePermission']['all'] = group_access_all
743
+ else
744
+ payload['network']['resourcePermission'] ||= {}
745
+ payload['network']['resourcePermission']['all'] = true
674
746
  end
675
747
  end
676
748
 
677
749
  # Tenants
678
- if options['tenants']
679
- payload['tenantPermissions'] = {}
680
- payload['tenantPermissions']['accounts'] = options['tenants']
750
+ if !options[:no_prompt] && options['tenants'].nil? && payload['tenantPermissions'].nil? && payload['network']['tenants'].nil?
751
+ perm_excludes = ['plans', 'groups']
752
+ perm_excludes << 'visibility' if options['visibility'] || payload['network']['visibility']
753
+ perms = prompt_permissions(options, perm_excludes)
754
+
755
+ payload['network']['tenants'] = perms['tenantPermissions']['accounts'].collect {|it| {'id': it}} if perms['tenantPermissions']
756
+ payload['network']['visibility'] = perms['resourcePool']['visibility'] if perms['resourcePool']
757
+ elsif options['tenants']
758
+ payload['network']['tenants'] = options['tenants'].collect {|it| {'id': it}}
681
759
  end
682
760
 
683
- # Active
684
- if options['active'] != nil
685
- payload['network']['active'] = options['active']
686
- end
687
-
688
761
  # Visibility
689
- if options['visibility'] != nil
690
- payload['network']['visibility'] = options['visibility']
762
+ if options['visibility'].nil? && payload['network']['visibility'].nil?
763
+ perms = prompt_permissions(options, ['plans', 'groups', 'tenants'])
764
+ payload['network']['visibility'] = perms['resourcePool'].nil? ? 'private' : perms['resourcePool']['visibility']
765
+ else
766
+ payload['network']['visibility'] = options['visibility'] || 'private'
691
767
  end
692
-
693
768
  end
694
769
 
695
770
  @networks_interface.setopts(options)
@@ -735,6 +810,9 @@ class Morpheus::Cli::NetworksCommand
735
810
  opts.on('--description VALUE', String, "Description of network") do |val|
736
811
  options['description'] = val
737
812
  end
813
+ opts.on('--display-name VALUE', String, "Display name for this network") do |val|
814
+ options['displayName'] = val
815
+ end
738
816
  opts.on('--gateway VALUE', String, "Gateway") do |val|
739
817
  options['gateway'] = val
740
818
  end
@@ -834,6 +912,17 @@ class Morpheus::Cli::NetworksCommand
834
912
  payload = nil
835
913
  if options[:payload]
836
914
  payload = options[:payload]
915
+
916
+ # backward compat
917
+ if payload['resourcePermissions']
918
+ payload['network'] ||= {}
919
+ payload['network']['resourcePermission'] = payload['resourcePermissions']
920
+ payload.delete('resourcePermissions')
921
+ end
922
+ if payload['network'] && payload['network']['resourcePermissions']
923
+ payload['network']['resourcePermission'] = payload['network']['resourcePermissions']
924
+ payload['network'].delete('resourcePermissions')
925
+ end
837
926
  else
838
927
  # prompt for network options
839
928
  payload = {
@@ -879,6 +968,10 @@ class Morpheus::Cli::NetworksCommand
879
968
  # payload['network']['name'] = v_prompt['name']
880
969
  end
881
970
 
971
+ if options['displayName']
972
+ payload['network']['displayName'] = options['displayName']
973
+ end
974
+
882
975
  # Description
883
976
  if options['description']
884
977
  payload['network']['description'] = options['description']
@@ -995,12 +1088,12 @@ class Morpheus::Cli::NetworksCommand
995
1088
 
996
1089
  # Group Access
997
1090
  if group_access_all != nil
998
- payload['resourcePermissions'] ||= {}
999
- payload['resourcePermissions']['all'] = group_access_all
1091
+ payload['network']['resourcePermission'] ||= {}
1092
+ payload['network']['resourcePermission']['all'] = group_access_all
1000
1093
  end
1001
1094
  if group_access_list != nil
1002
- payload['resourcePermissions'] ||= {}
1003
- payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id|
1095
+ payload['network']['resourcePermission'] ||= {}
1096
+ payload['network']['resourcePermission']['sites'] = group_access_list.collect do |site_id|
1004
1097
  site = {"id" => site_id.to_i}
1005
1098
  if group_defaults_list && group_defaults_list.include?(site_id)
1006
1099
  site["default"] = true
@@ -1011,8 +1104,8 @@ class Morpheus::Cli::NetworksCommand
1011
1104
 
1012
1105
  # Tenants
1013
1106
  if options['tenants']
1014
- payload['tenantPermissions'] = {}
1015
- payload['tenantPermissions']['accounts'] = options['tenants']
1107
+ payload['network']['tenants'] = {}
1108
+ payload['network']['tenants'] = options['tenants'].collect {|it| {'id': it}}
1016
1109
  end
1017
1110
 
1018
1111
  # Active