morpheus-cli 4.0.0.1 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api.rb +10 -0
  3. data/lib/morpheus/api/api_client.rb +24 -3
  4. data/lib/morpheus/api/clouds_interface.rb +15 -0
  5. data/lib/morpheus/api/clusters_interface.rb +276 -0
  6. data/lib/morpheus/api/library_compute_type_layouts_interface.rb +26 -0
  7. data/lib/morpheus/api/logs_interface.rb +6 -0
  8. data/lib/morpheus/api/network_subnet_types_interface.rb +26 -0
  9. data/lib/morpheus/api/network_subnets_interface.rb +47 -0
  10. data/lib/morpheus/api/provision_types_interface.rb +6 -0
  11. data/lib/morpheus/api/security_groups_interface.rb +12 -3
  12. data/lib/morpheus/api/servers_interface.rb +15 -0
  13. data/lib/morpheus/api/service_plans_interface.rb +30 -0
  14. data/lib/morpheus/api/subnets_interface.rb +47 -0
  15. data/lib/morpheus/cli.rb +1 -0
  16. data/lib/morpheus/cli/apps.rb +20 -18
  17. data/lib/morpheus/cli/cli_command.rb +5 -1
  18. data/lib/morpheus/cli/clusters.rb +3952 -0
  19. data/lib/morpheus/cli/containers_command.rb +70 -2
  20. data/lib/morpheus/cli/hosts.rb +69 -53
  21. data/lib/morpheus/cli/instances.rb +33 -33
  22. data/lib/morpheus/cli/library_container_types_command.rb +2 -1
  23. data/lib/morpheus/cli/library_option_lists_command.rb +13 -8
  24. data/lib/morpheus/cli/mixins/accounts_helper.rb +43 -0
  25. data/lib/morpheus/cli/mixins/print_helper.rb +10 -2
  26. data/lib/morpheus/cli/mixins/provisioning_helper.rb +53 -3
  27. data/lib/morpheus/cli/networks_command.rb +883 -36
  28. data/lib/morpheus/cli/option_types.rb +37 -14
  29. data/lib/morpheus/cli/roles.rb +78 -77
  30. data/lib/morpheus/cli/user_settings_command.rb +34 -5
  31. data/lib/morpheus/cli/version.rb +1 -1
  32. metadata +10 -2
@@ -21,6 +21,12 @@ module Morpheus::Cli::AccountsHelper
21
21
  @users_interface
22
22
  end
23
23
 
24
+ def user_groups_interface
25
+ # @api_client.users
26
+ raise "#{self.class} has not defined @user_groups_interface" if @user_groups_interface.nil?
27
+ @user_groups_interface
28
+ end
29
+
24
30
  def roles_interface
25
31
  # @api_client.roles
26
32
  raise "#{self.class} has not defined @roles_interface" if @roles_interface.nil?
@@ -179,6 +185,43 @@ module Morpheus::Cli::AccountsHelper
179
185
  user_ids
180
186
  end
181
187
 
188
+ def find_user_group_by_name_or_id(account_id, val)
189
+ if val.to_s =~ /\A\d{1,}\Z/
190
+ return find_user_group_by_id(account_id, val)
191
+ else
192
+ return find_user_group_by_name(account_id, val)
193
+ end
194
+ end
195
+
196
+ def find_user_group_by_id(account_id, id)
197
+ begin
198
+ json_response = @user_groups_interface.get(account_id, id.to_i)
199
+ return json_response['userGroup']
200
+ rescue RestClient::Exception => e
201
+ if e.response && e.response.code == 404
202
+ print_red_alert "User Group not found by id #{id}"
203
+ else
204
+ raise e
205
+ end
206
+ end
207
+ end
208
+
209
+ def find_user_group_by_name(account_id, name)
210
+ user_groups = @user_groups_interface.list(account_id, {name: name.to_s})['userGroups']
211
+ if user_groups.empty?
212
+ print_red_alert "User Group not found by name #{name}"
213
+ return nil
214
+ elsif user_groups.size > 1
215
+ print_red_alert "#{user_groups.size} user groups found by name #{name}"
216
+ print_user_groups_table(user_groups, {color: red})
217
+ print_red_alert "Try using ID instead"
218
+ print reset,"\n"
219
+ return nil
220
+ else
221
+ return user_groups[0]
222
+ end
223
+ end
224
+
182
225
  def print_accounts_table(accounts, options={})
183
226
  table_color = options.key?(:color) ? options[:color] : cyan
184
227
  rows = accounts.collect do |account|
@@ -475,9 +475,17 @@ module Morpheus::Cli::PrintHelper
475
475
  print out
476
476
  return
477
477
  end
478
- opts[:include] ||= [:memory, :storage, :cpu]
478
+ opts[:include] ||= [:cpu, :memory, :storage]
479
+ if opts[:include].include?(:max_cpu)
480
+ cpu_usage = stats['cpuUsagePeak']
481
+ out << cyan + "Max CPU".rjust(label_width, ' ') + ": " + generate_usage_bar(cpu_usage.to_f, 100) + "\n"
482
+ end
483
+ if opts[:include].include?(:avg_cpu)
484
+ cpu_usage = stats['cpuUsageAvg']
485
+ out << cyan + "Avg. CPU".rjust(label_width, ' ') + ": " + generate_usage_bar(cpu_usage.to_f, 100) + "\n"
486
+ end
479
487
  if opts[:include].include?(:cpu)
480
- cpu_usage = (stats['usedCpu'] || stats['cpuUsage'])
488
+ cpu_usage = stats['cpuUsage'] || stats['usedCpu']
481
489
  out << cyan + "CPU".rjust(label_width, ' ') + ": " + generate_usage_bar(cpu_usage.to_f, 100) + "\n"
482
490
  end
483
491
  if opts[:include].include?(:memory)
@@ -208,6 +208,46 @@ module Morpheus::Cli::ProvisioningHelper
208
208
  return instance
209
209
  end
210
210
 
211
+ def find_workflow_by_name_or_id(val)
212
+ if val.to_s =~ /\A\d{1,}\Z/
213
+ return find_workflow_by_id(val)
214
+ else
215
+ return find_workflow_by_name(val)
216
+ end
217
+ end
218
+
219
+ def find_workflow_by_id(id)
220
+ begin
221
+ json_response = @task_sets_interface.get(id.to_i)
222
+ return json_response['taskSet']
223
+ rescue RestClient::Exception => e
224
+ if e.response && e.response.code == 404
225
+ print_red_alert "Workflow not found by id #{id}"
226
+ else
227
+ raise e
228
+ end
229
+ end
230
+ end
231
+
232
+ def find_workflow_by_name(name)
233
+ workflows = @task_sets_interface.get({name: name.to_s})['taskSets']
234
+ if workflows.empty?
235
+ print_red_alert "Workflow not found by name #{name}"
236
+ return nil
237
+ elsif workflows.size > 1
238
+ print_red_alert "#{workflows.size} workflows by name #{name}"
239
+ print_workflows_table(workflows, {color: red})
240
+ print reset,"\n\n"
241
+ return nil
242
+ else
243
+ return workflows[0]
244
+ end
245
+ end
246
+
247
+ def get_provision_type_for_zone_type(zone_type_id)
248
+ @clouds_interface.cloud_type(zone_type_id)['zoneType']['provisionTypes'].first rescue nil
249
+ end
250
+
211
251
  # prompts user for all the configuartion options for a particular instance
212
252
  # returns payload of data for a new instance
213
253
  def prompt_new_instance(options={})
@@ -387,7 +427,8 @@ module Morpheus::Cli::ProvisioningHelper
387
427
  payload['plan'] = {'id' => service_plan["id"], 'code' => service_plan["code"], 'name' => service_plan["name"]}
388
428
  payload['instance']['plan'] = {'id' => service_plan["id"], 'code' => service_plan["code"], 'name' => service_plan["name"]}
389
429
 
390
-
430
+ # determine provision_type
431
+ # provision_type = (layout && layout['provisionType'] ? layout['provisionType'] : nil) || get_provision_type_for_zone_type(cloud['zoneType']['id'])
391
432
 
392
433
  # build option types
393
434
  option_type_list = []
@@ -410,15 +451,17 @@ module Morpheus::Cli::ProvisioningHelper
410
451
 
411
452
  # prompt for resource pool
412
453
  pool_id = nil
454
+ resource_pool = nil
413
455
  has_zone_pools = layout["provisionType"] && layout["provisionType"]["id"] && layout["provisionType"]["hasZonePools"]
414
456
  if has_zone_pools
415
- # pluck out the resourcePoolId option type to prompt for..why the heck is this even needed?
457
+ # pluck out the resourcePoolId option type to prompt for
416
458
  resource_pool_option_type = option_type_list.find {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
417
459
  option_type_list = option_type_list.reject {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
418
460
  resource_pool_option_type ||= {'fieldContext' => 'config', 'fieldName' => 'resourcePoolId', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'optionSource' => 'zonePools', 'required' => true, 'skipSingleOption' => true, 'description' => 'Select resource pool.'}
419
461
  resource_pool_prompt = Morpheus::Cli::OptionTypes.prompt([resource_pool_option_type],options[:options],api_client,{groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], planId: service_plan["id"], layoutId: layout["id"]})
420
462
  resource_pool_prompt.deep_compact!
421
463
  payload.deep_merge!(resource_pool_prompt)
464
+ resource_pool = Morpheus::Cli::OptionTypes.get_last_select()
422
465
  if resource_pool_option_type['fieldContext'] && resource_pool_prompt[resource_pool_option_type['fieldContext']]
423
466
  pool_id = resource_pool_prompt[resource_pool_option_type['fieldContext']][resource_pool_option_type['fieldName']]
424
467
  elsif resource_pool_prompt[resource_pool_option_type['fieldName']]
@@ -426,6 +469,13 @@ module Morpheus::Cli::ProvisioningHelper
426
469
  end
427
470
  end
428
471
 
472
+ # remove host selection for kubernetes
473
+ if resource_pool && resource_pool['providerType'] == 'kubernetes'
474
+ option_type_list = option_type_list.reject {|opt|
475
+ ['provisionServerId'].include?(opt['fieldName'])
476
+ }
477
+ end
478
+
429
479
  # plan_info has this property already..
430
480
  # has_datastore = layout["provisionType"] && layout["provisionType"]["id"] && layout["provisionType"]["hasDatastore"]
431
481
  # service_plan['hasDatastore'] = has_datastore
@@ -628,7 +678,7 @@ module Morpheus::Cli::ProvisioningHelper
628
678
  if plan_info['addVolumes']
629
679
  volume_index = 1
630
680
  has_another_volume = (options[:options] && options[:options]["dataVolume#{volume_index}"]) || (options[:options] && options[:options]['volumes'] && options[:options]['volumes'][volume_index])
631
- add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add data volume?", {:default => false}))
681
+ add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add data volume?", {:default => (options[:defaultAddFirstDataVolume] == true && volume_index == 1)}))
632
682
  while add_another_volume do
633
683
  #puts "Configure Data #{volume_index} Volume"
634
684
 
@@ -12,6 +12,11 @@ class Morpheus::Cli::NetworksCommand
12
12
 
13
13
  register_subcommands :list, :get, :add, :update, :remove #, :generate_pool
14
14
  register_subcommands :'types' => :list_types
15
+ register_subcommands :'get-type' => :get_type
16
+
17
+ register_subcommands :list_subnets, :get_subnet, :add_subnet, :update_subnet, :remove_subnet
18
+ register_subcommands :'subnet-types' => :list_subnet_types
19
+ register_subcommands :'get-subnet-type' => :get_subnet_type
15
20
 
16
21
  # set_default_subcommand :list
17
22
 
@@ -23,6 +28,8 @@ class Morpheus::Cli::NetworksCommand
23
28
  @api_client = establish_remote_appliance_connection(opts)
24
29
  @networks_interface = @api_client.networks
25
30
  @network_types_interface = @api_client.network_types
31
+ @network_subnets_interface = @api_client.network_subnets
32
+ @network_subnet_types_interface = @api_client.network_subnet_types
26
33
  @clouds_interface = @api_client.clouds
27
34
  @options_interface = @api_client.options
28
35
  end
@@ -571,7 +578,8 @@ class Morpheus::Cli::NetworksCommand
571
578
  elsif !options[:quiet]
572
579
  network = json_response['network']
573
580
  print_green_success "Added network #{network['name']}"
574
- get([network['id']])
581
+ get_args = [network['id']] + (options[:remote] ? ["-r",options[:remote]] : [])
582
+ get(get_args)
575
583
  end
576
584
  return 0
577
585
  rescue RestClient::Exception => e
@@ -903,7 +911,8 @@ class Morpheus::Cli::NetworksCommand
903
911
  else
904
912
  network = json_response['network']
905
913
  print_green_success "Updated network #{network['name']}"
906
- get([network['id']])
914
+ get_args = [network['id']] + (options[:remote] ? ["-r",options[:remote]] : [])
915
+ get(get_args)
907
916
  end
908
917
  return 0
909
918
  rescue RestClient::Exception => e
@@ -964,7 +973,7 @@ class Morpheus::Cli::NetworksCommand
964
973
  options[:cloud] = val
965
974
  end
966
975
  build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
967
- opts.footer = "List host types."
976
+ opts.footer = "List network types."
968
977
  end
969
978
  optparse.parse!(args)
970
979
  connect(options)
@@ -990,7 +999,7 @@ class Morpheus::Cli::NetworksCommand
990
999
 
991
1000
  network_types = json_response['networkTypes']
992
1001
 
993
- title = "Morpheus network Types"
1002
+ title = "Morpheus Network Types"
994
1003
  subtitles = []
995
1004
  subtitles += parse_list_subtitles(options)
996
1005
  if options[:cloud]
@@ -1022,52 +1031,890 @@ class Morpheus::Cli::NetworksCommand
1022
1031
  end
1023
1032
  end
1024
1033
 
1025
- private
1034
+ def get_type(args)
1035
+ options = {}
1036
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1037
+ opts.banner = subcommand_usage("[type]")
1038
+ build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
1039
+ opts.footer = "Get details about a network type.\n" +
1040
+ "[type] is required. This is the id or name of a network type."
1041
+ end
1042
+ optparse.parse!(args)
1043
+ connect(options)
1044
+ begin
1045
+ params = {}
1046
+ @network_types_interface.setopts(options)
1047
+ if options[:dry_run]
1048
+ if args[0].to_s =~ /\A\d{1,}\Z/
1049
+ print_dry_run @network_types_interface.dry.get(args[0].to_i)
1050
+ else
1051
+ print_dry_run @network_types_interface.dry.list({name:args[0]})
1052
+ end
1053
+ return
1054
+ end
1026
1055
 
1056
+ network_type = find_network_type_by_name_or_id(args[0])
1057
+ return 1 if network_type.nil?
1058
+ json_response = {'networkType' => network_type} # skip redundant request
1059
+ # json_response = @networks_interface.get(network_type['id'])
1060
+
1061
+ render_result = render_with_format(json_response, options, 'networkType')
1062
+ return 0 if render_result
1027
1063
 
1028
- def find_network_by_name_or_id(val)
1029
- if val.to_s =~ /\A\d{1,}\Z/
1030
- return find_network_by_id(val)
1031
- else
1032
- return find_network_by_name(val)
1064
+ network_type = json_response['networkType']
1065
+
1066
+ title = "Morpheus Network Type"
1067
+
1068
+ print_h1 "Morpheus Network Type", [], options
1069
+
1070
+ print cyan
1071
+ description_cols = {
1072
+ "ID" => 'id',
1073
+ "Name" => 'name',
1074
+ "Code" => 'name',
1075
+ "Description" => 'description',
1076
+ # lots more here
1077
+ "Createable" => lambda {|it| format_boolean(it['creatable']) },
1078
+ "Deletable" => lambda {|it| format_boolean(it['deleteable']) },
1079
+ }
1080
+ print_description_list(description_cols, network_type)
1081
+
1082
+
1083
+ option_types = network_type['optionTypes'] || []
1084
+ option_types = option_types.sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
1085
+ if !option_types.empty?
1086
+ print_h2 "Config Option Types", [], options
1087
+ option_type_cols = {
1088
+ "Name" => lambda {|it| it['fieldContext'].to_s != '' ? "#{it['fieldContext']}.#{it['fieldName']}" : it['fieldName'] },
1089
+ "Label" => lambda {|it| it['fieldLabel'] },
1090
+ "Type" => lambda {|it| it['type'] },
1091
+ }
1092
+ print cyan
1093
+ print as_pretty_table(option_types, option_type_cols)
1094
+ end
1095
+
1096
+ print reset,"\n"
1097
+ return 0
1098
+ rescue RestClient::Exception => e
1099
+ print_rest_exception(e, options)
1100
+ exit 1
1033
1101
  end
1034
1102
  end
1035
1103
 
1036
- def find_network_by_id(id)
1104
+ def list_subnet_types(args)
1105
+ options = {}
1106
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1107
+ opts.banner = subcommand_usage()
1108
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
1109
+ options[:cloud] = val
1110
+ end
1111
+ build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
1112
+ opts.footer = "List subnet types."
1113
+ end
1114
+ optparse.parse!(args)
1115
+ connect(options)
1037
1116
  begin
1038
- json_response = @networks_interface.get(id.to_i)
1039
- return json_response['network']
1117
+ params = {}
1118
+ params.merge!(parse_list_options(options))
1119
+ if options[:cloud]
1120
+ #return network_types_for_cloud(options[:cloud], options)
1121
+ zone = find_zone_by_name_or_id(nil, options[:cloud])
1122
+ #params["zoneTypeId"] = zone['zoneTypeId']
1123
+ params["zoneId"] = zone['id']
1124
+ params["creatable"] = true
1125
+ end
1126
+ @network_subnet_types_interface.setopts(options)
1127
+ if options[:dry_run]
1128
+ print_dry_run @network_subnet_types_interface.dry.list(params)
1129
+ return
1130
+ end
1131
+ json_response = @network_subnet_types_interface.list(params)
1132
+
1133
+ render_result = render_with_format(json_response, options, 'subnetTypes')
1134
+ return 0 if render_result
1135
+
1136
+ subnet_types = json_response['subnetTypes']
1137
+
1138
+ title = "Morpheus Subnet Types"
1139
+ subtitles = []
1140
+ subtitles += parse_list_subtitles(options)
1141
+ if options[:cloud]
1142
+ subtitles << "Cloud: #{options[:cloud]}"
1143
+ end
1144
+ print_h1 title, subtitles
1145
+ if subnet_types.empty?
1146
+ print cyan,"No subnet types found.",reset,"\n"
1147
+ else
1148
+ rows = subnet_types.collect do |subnet_type|
1149
+ {
1150
+ id: subnet_type['id'],
1151
+ code: subnet_type['code'],
1152
+ name: subnet_type['name']
1153
+ }
1154
+ end
1155
+ columns = [:id, :name, :code]
1156
+ print cyan
1157
+ print as_pretty_table(rows, columns, options)
1158
+ print reset
1159
+ print_results_pagination(json_response)
1160
+ end
1161
+ print reset,"\n"
1162
+ return 0
1163
+
1040
1164
  rescue RestClient::Exception => e
1041
- if e.response && e.response.code == 404
1042
- print_red_alert "Network not found by id #{id}"
1043
- return nil
1165
+ print_rest_exception(e, options)
1166
+ exit 1
1167
+ end
1168
+ end
1169
+
1170
+ def get_subnet_type(args)
1171
+ options = {}
1172
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1173
+ opts.banner = subcommand_usage("[type]")
1174
+ build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
1175
+ opts.footer = "Get details about a subnet type.\n" +
1176
+ "[type] is required. This is the id or name of a subnet type."
1177
+ end
1178
+ optparse.parse!(args)
1179
+ connect(options)
1180
+ begin
1181
+ params = {}
1182
+ @network_subnet_types_interface.setopts(options)
1183
+ if options[:dry_run]
1184
+ if args[0].to_s =~ /\A\d{1,}\Z/
1185
+ print_dry_run @network_subnet_types_interface.dry.get(args[0].to_i)
1186
+ else
1187
+ print_dry_run @network_subnet_types_interface.dry.list({name:args[0]})
1188
+ end
1189
+ return
1190
+ end
1191
+
1192
+ subnet_type = find_subnet_type_by_name_or_id(args[0])
1193
+ return 1 if subnet_type.nil?
1194
+ json_response = {'subnetType' => subnet_type} # skip redundant request
1195
+ # json_response = @networks_interface.get(subnet_type['id'])
1196
+
1197
+ render_result = render_with_format(json_response, options, 'subnetType')
1198
+ return 0 if render_result
1199
+
1200
+ subnet_type = json_response['subnetType']
1201
+
1202
+ title = "Morpheus Subnet Type"
1203
+
1204
+ print_h1 "Morpheus Subnet Type", [], options
1205
+
1206
+ print cyan
1207
+ description_cols = {
1208
+ "ID" => 'id',
1209
+ "Name" => 'name',
1210
+ "Code" => 'name',
1211
+ "Description" => 'description',
1212
+ "Createable" => lambda {|it| format_boolean(it['creatable']) },
1213
+ "Deletable" => lambda {|it| format_boolean(it['deleteable']) },
1214
+ }
1215
+ print_description_list(description_cols, subnet_type)
1216
+
1217
+
1218
+
1219
+ option_types = subnet_type['optionTypes'] || []
1220
+ option_types = option_types.sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
1221
+ if !option_types.empty?
1222
+ print_h2 "Config Option Types", [], options
1223
+ option_type_cols = {
1224
+ "Name" => lambda {|it| it['fieldContext'].to_s != '' ? "#{it['fieldContext']}.#{it['fieldName']}" : it['fieldName'] },
1225
+ "Label" => lambda {|it| it['fieldLabel'] },
1226
+ "Type" => lambda {|it| it['type'] },
1227
+ }
1228
+ print cyan
1229
+ print as_pretty_table(option_types, option_type_cols)
1230
+ end
1231
+
1232
+ print reset,"\n"
1233
+ return 0
1234
+ rescue RestClient::Exception => e
1235
+ print_rest_exception(e, options)
1236
+ exit 1
1237
+ end
1238
+ end
1239
+
1240
+
1241
+ def list_subnets(args)
1242
+ options = {}
1243
+ params = {}
1244
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1245
+ opts.banner = subcommand_usage("[network] [subnet]")
1246
+ build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :dry_run, :remote])
1247
+ opts.footer = "Get details about a network." + "\n" +
1248
+ "[network] is required. This is the name or id of a network."
1249
+ end
1250
+ optparse.parse!(args)
1251
+ if args.count != 1
1252
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args}\n#{optparse}"
1253
+ end
1254
+ connect(options)
1255
+ begin
1256
+ network = find_network_by_name_or_id(args[0])
1257
+ return 1 if network.nil?
1258
+
1259
+ params.merge!(parse_list_options(options))
1260
+ @network_subnets_interface.setopts(options)
1261
+ if options[:dry_run]
1262
+ print_dry_run @network_subnets_interface.dry.list(network['id'], params)
1263
+ return
1264
+ end
1265
+ json_response = @network_subnets_interface.list(network['id'], params)
1266
+ subnets = json_response["subnets"]
1267
+ if options[:json]
1268
+ puts as_json(json_response, options, "subnets")
1269
+ return 0
1270
+ elsif options[:yaml]
1271
+ puts as_yaml(json_response, options, "subnets")
1272
+ return 0
1273
+ elsif options[:csv]
1274
+ puts records_as_csv(subnets, options)
1275
+ return 0
1276
+ end
1277
+ title = "Morpheus Subnets"
1278
+ subtitles = []
1279
+ subtitles << "Network: #{network['name']}"
1280
+ subtitles += parse_list_subtitles(options)
1281
+ print_h1 title, subtitles
1282
+
1283
+ if subnets.empty?
1284
+ print cyan,"No subnets found.",reset,"\n"
1044
1285
  else
1045
- raise e
1286
+ subnet_columns = {
1287
+ "ID" => 'id',
1288
+ "Name" => 'name',
1289
+ #"Description" => 'description',
1290
+ "Type" => lambda {|it| it['type']['name'] rescue it['type'] },
1291
+ "CIDR" => lambda {|it| it['cidr'] },
1292
+ "Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
1293
+ "Tenants" => lambda {|it| it['tenants'] ? it['tenants'].collect {|it| it['name'] }.uniq.join(', ') : '' }
1294
+ }
1295
+ print cyan
1296
+ print as_pretty_table(subnets, subnet_columns)
1046
1297
  end
1298
+ print reset,"\n"
1299
+ return 0
1300
+
1301
+ rescue RestClient::Exception => e
1302
+ print_rest_exception(e, options)
1303
+ return 1
1047
1304
  end
1048
1305
  end
1049
1306
 
1050
- def find_network_by_name(name)
1051
- json_response = @networks_interface.list({name: name.to_s})
1052
- networks = json_response['networks']
1053
- if networks.empty?
1054
- print_red_alert "Network not found by name #{name}"
1055
- return nil
1056
- elsif networks.size > 1
1057
- print_red_alert "#{networks.size} networks found by name #{name}"
1058
- # print_networks_table(networks, {color: red})
1059
- rows = networks.collect do |it|
1060
- {id: it['id'], name: it['name']}
1307
+ def get_subnet(args)
1308
+ options = {}
1309
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1310
+ opts.banner = subcommand_usage("[network] [subnet]")
1311
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
1312
+ opts.footer = "Get details about a subnet." + "\n" +
1313
+ "[network] is required. This is the name or id of a network." + "\n" +
1314
+ "[subnet] is required. This is the name or id of a subnet."
1315
+ end
1316
+ optparse.parse!(args)
1317
+ if args.count != 2
1318
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
1319
+ end
1320
+ connect(options)
1321
+ begin
1322
+ network = find_network_by_name_or_id(args[0])
1323
+ return 1 if network.nil?
1324
+
1325
+ @network_subnets_interface.setopts(options)
1326
+ if options[:dry_run]
1327
+ if args[1].to_s =~ /\A\d{1,}\Z/
1328
+ print_dry_run @network_subnets_interface.dry.get(network['id'], args[1].to_i)
1329
+ else
1330
+ print_dry_run @network_subnets_interface.dry.list(network['id'], {name:args[1]})
1331
+ end
1332
+ return
1061
1333
  end
1062
- puts as_pretty_table(rows, [:id, :name], {color:red})
1063
- return nil
1064
- else
1065
- network = networks[0]
1066
- # merge in tenants map
1067
- if json_response['tenants'] && json_response['tenants'][network['id']]
1068
- network['tenants'] = json_response['tenants'][network['id']]
1334
+ subnet = find_subnet_by_name_or_id(network['id'], args[1])
1335
+ return 1 if subnet.nil?
1336
+ json_response = {'subnet' => subnet} # skip redundant request
1337
+ # json_response = @network_subnets_interface.get(network['id'], subnet['id'])
1338
+ subnet = json_response['subnet']
1339
+ if options[:json]
1340
+ puts as_json(json_response, options, "subnet")
1341
+ return 0
1342
+ elsif options[:yaml]
1343
+ puts as_yaml(json_response, options, "subnet")
1344
+ return 0
1345
+ elsif options[:csv]
1346
+ puts records_as_csv([subnet], options)
1347
+ return 0
1069
1348
  end
1070
- return network
1349
+ print_h1 "Subnet Details", [], options
1350
+ print cyan
1351
+ description_cols = {
1352
+ "ID" => 'id',
1353
+ "Name" => 'name',
1354
+ "Description" => 'description',
1355
+ "Type" => lambda {|it| it['type'] ? it['type']['name'] : '' },
1356
+ "Network" => lambda {|it| network['name'] },
1357
+ "Cloud" => lambda {|it| network['zone'] ? network['zone']['name'] : '' },
1358
+ "CIDR" => 'cidr',
1359
+ "Gateway" => 'gateway',
1360
+ "Netmask" => 'netmask',
1361
+ "Subnet" => 'subnetAddress',
1362
+ "Primary DNS" => 'dnsPrimary',
1363
+ "Secondary DNS" => 'dnsSecondary',
1364
+ "Pool" => lambda {|it| it['pool'] ? it['pool']['name'] : '' },
1365
+ "DHCP" => lambda {|it| format_boolean it['dhcpServer'] },
1366
+ #"Allow IP Override" => lambda {|it| it['allowStaticOverride'] ? 'Yes' : 'No' },
1367
+ "Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
1368
+ "Tenants" => lambda {|it| it['tenants'] ? it['tenants'].collect {|it| it['name'] }.uniq.join(', ') : '' },
1369
+ # "Owner" => lambda {|it| it['owner'] ? it['owner']['name'] : '' },
1370
+ }
1371
+ print_description_list(description_cols, subnet)
1372
+
1373
+ if subnet['resourcePermission'].nil?
1374
+ print "\n", "No group access found", "\n"
1375
+ else
1376
+ print_h2 "Group Access"
1377
+ rows = []
1378
+ if subnet['resourcePermission']['all']
1379
+ rows.push({"name" => 'All'})
1380
+ end
1381
+ if subnet['resourcePermission']['sites']
1382
+ subnet['resourcePermission']['sites'].each do |site|
1383
+ rows.push(site)
1384
+ end
1385
+ end
1386
+ rows = rows.collect do |site|
1387
+ {group: site['name'], default: site['default'] ? 'Yes' : ''}
1388
+ end
1389
+ columns = [:group, :default]
1390
+ print cyan
1391
+ print as_pretty_table(rows, columns)
1392
+ end
1393
+
1394
+ print reset,"\n"
1395
+ return 0
1396
+ rescue RestClient::Exception => e
1397
+ print_rest_exception(e, options)
1398
+ return 1
1399
+ end
1400
+ end
1401
+
1402
+ def add_subnet(args)
1403
+ options = {}
1404
+ subnet_type_id = nil
1405
+ tenants = nil
1406
+ group_access_all = nil
1407
+ group_access_list = nil
1408
+ group_defaults_list = nil
1409
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1410
+ opts.banner = subcommand_usage("[network]")
1411
+ opts.on('-t', '--type ID', "Subnet Type Name or ID") do |val|
1412
+ subnet_type_id = val
1413
+ end
1414
+ opts.on('--name VALUE', String, "Name for this subnet") do |val|
1415
+ options[:options]['name'] = val
1416
+ end
1417
+ opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
1418
+ group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
1419
+ end
1420
+ opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list|
1421
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
1422
+ group_access_list = []
1423
+ else
1424
+ group_access_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
1425
+ end
1426
+ end
1427
+ opts.on('--group-defaults LIST', Array, "Group Default Selection, comma separated list of group IDs") do |list|
1428
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
1429
+ group_defaults_list = []
1430
+ else
1431
+ group_defaults_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
1432
+ end
1433
+ end
1434
+ opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
1435
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
1436
+ options['tenants'] = []
1437
+ else
1438
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
1439
+ end
1440
+ end
1441
+ opts.on('--accounts LIST', Array, "alias for --tenants") do |list|
1442
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
1443
+ options['tenants'] = []
1444
+ else
1445
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
1446
+ end
1447
+ end
1448
+ opts.on('--visibility [private|public]', String, "Visibility") do |val|
1449
+ options['visibility'] = val
1450
+ end
1451
+ # opts.on('--active [on|off]', String, "Can be used to disable a subnet") do |val|
1452
+ # options['active'] = val.to_s == 'on' || val.to_s == 'true'
1453
+ # end
1454
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
1455
+ opts.footer = "Create a new subnet." + "\n" +
1456
+ "[network] is required. This is the name or id of a network." #+ "\n" +
1457
+ #"[name] is required and can be passed as --name instead."
1458
+ end
1459
+ optparse.parse!(args)
1460
+ # if args.count < 1 || args.count > 2
1461
+ if args.count != 1
1462
+ raise_command_error "wrong number of arguments, expected 1-2 and got (#{args.count}) #{args}\n#{optparse}"
1463
+ end
1464
+ if args[1]
1465
+ options[:options]['name'] = args[1]
1466
+ end
1467
+ connect(options)
1468
+ begin
1469
+ network = find_network_by_name_or_id(args[0])
1470
+ return 1 if network.nil?
1471
+
1472
+ passed_options = (options[:options] || {}).reject {|k,v| k.is_a?(Symbol) }
1473
+ payload = nil
1474
+ if options[:payload]
1475
+ payload = options[:payload]
1476
+ payload.deep_merge!({'subnet' => passed_options}) unless passed_options.empty?
1477
+
1478
+ else
1479
+ payload = {'subnet' => {}}
1480
+ payload.deep_merge!({'subnet' => passed_options}) unless passed_options.empty?
1481
+
1482
+ # Name
1483
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name for this subnet.'}], options[:options])
1484
+ # payload['subnet']['name'] = v_prompt['name']
1485
+
1486
+ # Subnet Type
1487
+ if !subnet_type_id
1488
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Subnet Type', 'type' => 'select', 'optionSource' => 'subnetTypes', 'required' => true, 'description' => 'Choose a subnet type.'}], options[:options], @api_client, {networkId: network['id']})
1489
+ subnet_type_id = v_prompt['type']
1490
+ end
1491
+ subnet_type = find_subnet_type_by_name_or_id(subnet_type_id)
1492
+ return 1 if subnet_type.nil?
1493
+ payload['subnet']['type'] = {'id' => subnet_type['id'] }
1494
+ #payload['subnet']['type'] = {'code' => subnet_type['code'] }
1495
+
1496
+ subnet_type_option_types = subnet_type['optionTypes']
1497
+ if subnet_type_option_types && subnet_type_option_types.size > 0
1498
+ # prompt for option types
1499
+ subnet_type_params = Morpheus::Cli::OptionTypes.prompt(subnet_type_option_types,options[:options],@api_client, {networkId: network['id']})
1500
+ payload['subnet'].deep_merge!(subnet_type_params)
1501
+
1502
+ else
1503
+ # DEFAULT INPUTS
1504
+
1505
+ # CIDR
1506
+ # if options['cidr']
1507
+ # payload['subnet']['cidr'] = options['cidr']
1508
+ # else
1509
+ # v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cidr', 'fieldLabel' => 'CIDR', 'type' => 'text', 'required' => false, 'description' => ''}], options)
1510
+ # payload['subnet']['cidr'] = v_prompt['cidr']
1511
+ # end
1512
+
1513
+ end
1514
+
1515
+ # Group Access
1516
+ # Group Access (default is All)
1517
+ if group_access_all.nil?
1518
+ if payload['resourcePermissions'].nil?
1519
+ payload['resourcePermissions'] ||= {}
1520
+ payload['resourcePermissions']['all'] = true
1521
+ end
1522
+ else
1523
+ payload['resourcePermissions'] ||= {}
1524
+ payload['resourcePermissions']['all'] = group_access_all
1525
+ end
1526
+ if group_access_list != nil
1527
+ payload['resourcePermissions'] ||= {}
1528
+ payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id|
1529
+ site = {"id" => site_id.to_i}
1530
+ if group_defaults_list && group_defaults_list.include?(site_id)
1531
+ site["default"] = true
1532
+ end
1533
+ site
1534
+ end
1535
+ end
1536
+
1537
+ # Tenants
1538
+ if options['tenants']
1539
+ payload['tenantPermissions'] = {}
1540
+ payload['tenantPermissions']['accounts'] = options['tenants']
1541
+ end
1542
+
1543
+ # Active
1544
+ if options['active'] != nil
1545
+ payload['subnet']['active'] = options['active']
1546
+ end
1547
+
1548
+ # Visibility
1549
+ if options['visibility'] != nil
1550
+ payload['subnet']['visibility'] = options['visibility']
1551
+ end
1552
+
1553
+ end
1554
+
1555
+ @network_subnets_interface.setopts(options)
1556
+ if options[:dry_run]
1557
+ print_dry_run @network_subnets_interface.dry.create(network['id'], payload)
1558
+ return
1559
+ end
1560
+ json_response = @network_subnets_interface.create(network['id'], payload)
1561
+ if options[:json]
1562
+ puts as_json(json_response, options)
1563
+ elsif !options[:quiet]
1564
+ subnet = json_response['subnet']
1565
+ print_green_success "Added subnet #{subnet['name']}"
1566
+ get_args = [network['id'], subnet['id']] + (options[:remote] ? ["-r",options[:remote]] : [])
1567
+ get_subnet(get_args)
1568
+ end
1569
+ return 0
1570
+ rescue RestClient::Exception => e
1571
+ print_rest_exception(e, options)
1572
+ return 1
1573
+ end
1574
+ end
1575
+
1576
+
1577
+ def update_subnet(args)
1578
+ options = {}
1579
+ tenants = nil
1580
+ group_access_all = nil
1581
+ group_access_list = nil
1582
+ group_defaults_list = nil
1583
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1584
+ opts.banner = subcommand_usage("[network] [subnet]")
1585
+ opts.on('--group-access-all [on|off]', String, "Toggle Access for all groups.") do |val|
1586
+ group_access_all = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
1587
+ end
1588
+ opts.on('--group-access LIST', Array, "Group Access, comma separated list of group IDs.") do |list|
1589
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
1590
+ group_access_list = []
1591
+ else
1592
+ group_access_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
1593
+ end
1594
+ end
1595
+ opts.on('--group-defaults LIST', Array, "Group Default Selection, comma separated list of group IDs") do |list|
1596
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
1597
+ group_defaults_list = []
1598
+ else
1599
+ group_defaults_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
1600
+ end
1601
+ end
1602
+ opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
1603
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
1604
+ options['tenants'] = []
1605
+ else
1606
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
1607
+ end
1608
+ end
1609
+ opts.on('--accounts LIST', Array, "alias for --tenants") do |list|
1610
+ if list.size == 1 && list[0] == 'null' # hacky way to clear it
1611
+ options['tenants'] = []
1612
+ else
1613
+ options['tenants'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
1614
+ end
1615
+ end
1616
+ opts.on('--visibility [private|public]', String, "Visibility") do |val|
1617
+ options['visibility'] = val
1618
+ end
1619
+ # opts.on('--active [on|off]', String, "Can be used to disable a network") do |val|
1620
+ # options['active'] = val.to_s == 'on' || val.to_s == 'true'
1621
+ # end
1622
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
1623
+ opts.footer = "Update a subnet." + "\n" +
1624
+ "[network] is required. This is the name or id of a network." + "\n" +
1625
+ "[subnet] is required. This is the name or id of a subnet."
1626
+ end
1627
+ optparse.parse!(args)
1628
+ if args.count != 2
1629
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
1630
+ end
1631
+ connect(options)
1632
+ begin
1633
+ network = find_network_by_name_or_id(args[0])
1634
+ return 1 if network.nil?
1635
+
1636
+ subnet = find_subnet_by_name_or_id(network['id'], args[1])
1637
+ return 1 if subnet.nil?
1638
+
1639
+ # merge -O options into normally parsed options
1640
+ options.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
1641
+
1642
+ # construct payload
1643
+ payload = nil
1644
+ if options[:payload]
1645
+ payload = options[:payload]
1646
+ else
1647
+ # prompt for network options
1648
+ payload = {
1649
+ 'subnet' => {
1650
+ }
1651
+ }
1652
+
1653
+ # allow arbitrary -O options
1654
+ payload['subnet'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
1655
+
1656
+ # Group Access
1657
+ if group_access_all != nil
1658
+ payload['resourcePermissions'] ||= {}
1659
+ payload['resourcePermissions']['all'] = group_access_all
1660
+ end
1661
+ if group_access_list != nil
1662
+ payload['resourcePermissions'] ||= {}
1663
+ payload['resourcePermissions']['sites'] = group_access_list.collect do |site_id|
1664
+ site = {"id" => site_id.to_i}
1665
+ if group_defaults_list && group_defaults_list.include?(site_id)
1666
+ site["default"] = true
1667
+ end
1668
+ site
1669
+ end
1670
+ end
1671
+
1672
+ # Tenants
1673
+ if options['tenants']
1674
+ payload['tenantPermissions'] = {}
1675
+ payload['tenantPermissions']['accounts'] = options['tenants']
1676
+ end
1677
+
1678
+ # Active
1679
+ if options['active'] != nil
1680
+ payload['subnet']['active'] = options['active']
1681
+ end
1682
+
1683
+ # Visibility
1684
+ if options['visibility'] != nil
1685
+ payload['subnet']['visibility'] = options['visibility']
1686
+ end
1687
+
1688
+ end
1689
+
1690
+ @network_subnets_interface.setopts(options)
1691
+ if options[:dry_run]
1692
+ print_dry_run @network_subnets_interface.dry.update(network['id'], subnet['id'], payload)
1693
+ return
1694
+ end
1695
+ json_response = @network_subnets_interface.update(network['id'], subnet['id'], payload)
1696
+ if options[:json]
1697
+ puts as_json(json_response, options)
1698
+ elsif !options[:quiet]
1699
+ subnet = json_response['subnet']
1700
+ print_green_success "Updated subnet #{subnet['name']}"
1701
+ get_args = [network['id'], subnet['id']] + (options[:remote] ? ["-r",options[:remote]] : [])
1702
+ get_subnet(get_args)
1703
+ end
1704
+ return 0
1705
+ rescue RestClient::Exception => e
1706
+ print_rest_exception(e, options)
1707
+ return 1
1708
+ end
1709
+ end
1710
+
1711
+ def remove_subnet(args)
1712
+ options = {}
1713
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
1714
+ opts.banner = subcommand_usage("[network] [subnet]")
1715
+ build_common_options(opts, options, [:account, :auto_confirm, :json, :dry_run, :remote])
1716
+ opts.footer = "Delete a subnet." + "\n" +
1717
+ "[network] is required. This is the name or id of a network." + "\n" +
1718
+ "[subnet] is required. This is the name or id of a subnet."
1719
+ end
1720
+ optparse.parse!(args)
1721
+ if args.count != 2
1722
+ raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args}\n#{optparse}"
1723
+ end
1724
+ connect(options)
1725
+ begin
1726
+ network = find_network_by_name_or_id(args[0])
1727
+ return 1 if network.nil?
1728
+
1729
+ subnet = find_subnet_by_name_or_id(network['id'], args[1])
1730
+ return 1 if subnet.nil?
1731
+
1732
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the subnet: #{subnet['name']}?")
1733
+ return 9, "aborted command"
1734
+ end
1735
+ @network_subnets_interface.setopts(options)
1736
+ if options[:dry_run]
1737
+ print_dry_run @network_subnets_interface.dry.destroy(network['id'], subnet['id'])
1738
+ return 0
1739
+ end
1740
+ json_response = @network_subnets_interface.destroy(network['id'], subnet['id'])
1741
+ if options[:json]
1742
+ puts as_json(json_response, options)
1743
+ else
1744
+ print_green_success "Removed subnet #{subnet['name']}"
1745
+ end
1746
+ return 0
1747
+ rescue RestClient::Exception => e
1748
+ print_rest_exception(e, options)
1749
+ return 1
1750
+ end
1751
+ end
1752
+
1753
+ private
1754
+
1755
+
1756
+ def find_network_by_name_or_id(val)
1757
+ if val.to_s =~ /\A\d{1,}\Z/
1758
+ return find_network_by_id(val)
1759
+ else
1760
+ return find_network_by_name(val)
1761
+ end
1762
+ end
1763
+
1764
+ def find_network_by_id(id)
1765
+ begin
1766
+ json_response = @networks_interface.get(id.to_i)
1767
+ return json_response['network']
1768
+ rescue RestClient::Exception => e
1769
+ if e.response && e.response.code == 404
1770
+ print_red_alert "Network not found by id #{id}"
1771
+ return nil
1772
+ else
1773
+ raise e
1774
+ end
1775
+ end
1776
+ end
1777
+
1778
+ def find_network_by_name(name)
1779
+ json_response = @networks_interface.list({name: name.to_s})
1780
+ networks = json_response['networks']
1781
+ if networks.empty?
1782
+ print_red_alert "Network not found by name #{name}"
1783
+ return nil
1784
+ elsif networks.size > 1
1785
+ print_red_alert "#{networks.size} networks found by name #{name}"
1786
+ rows = networks.collect do |it|
1787
+ {id: it['id'], name: it['name']}
1788
+ end
1789
+ puts as_pretty_table(rows, [:id, :name], {color:red})
1790
+ return nil
1791
+ else
1792
+ network = networks[0]
1793
+ # merge in tenants map
1794
+ if json_response['tenants'] && json_response['tenants'][network['id']]
1795
+ network['tenants'] = json_response['tenants'][network['id']]
1796
+ end
1797
+ return network
1798
+ end
1799
+ end
1800
+
1801
+ def find_network_type_by_name_or_id(val)
1802
+ if val.to_s =~ /\A\d{1,}\Z/
1803
+ return find_network_type_by_id(val)
1804
+ else
1805
+ return find_network_type_by_name(val)
1806
+ end
1807
+ end
1808
+
1809
+ def find_network_type_by_id(id)
1810
+ begin
1811
+ json_response = @network_types_interface.get(id.to_i)
1812
+ return json_response['networkType']
1813
+ rescue RestClient::Exception => e
1814
+ if e.response && e.response.code == 404
1815
+ print_red_alert "Network Type not found by id #{id}"
1816
+ return nil
1817
+ else
1818
+ raise e
1819
+ end
1820
+ end
1821
+ end
1822
+
1823
+ def find_network_type_by_name(name)
1824
+ json_response = @network_types_interface.list({name: name.to_s})
1825
+ network_types = json_response['networkTypes']
1826
+ if network_types.empty?
1827
+ print_red_alert "Network Type not found by name #{name}"
1828
+ return network_types
1829
+ elsif network_types.size > 1
1830
+ print_red_alert "#{network_types.size} network types found by name #{name}"
1831
+ rows = network_types.collect do |it|
1832
+ {id: it['id'], name: it['name']}
1833
+ end
1834
+ puts as_pretty_table(rows, [:id, :name], {color:red})
1835
+ return nil
1836
+ else
1837
+ return network_types[0]
1838
+ end
1839
+ end
1840
+
1841
+ def find_subnet_by_name_or_id(network_id, val)
1842
+ if val.to_s =~ /\A\d{1,}\Z/
1843
+ return find_subnet_by_id(network_id, val)
1844
+ else
1845
+ return find_subnet_by_name(network_id, val)
1846
+ end
1847
+ end
1848
+
1849
+ def find_subnet_by_id(network_id, id)
1850
+ begin
1851
+ json_response = @network_subnets_interface.get(network_id, id.to_i)
1852
+ return json_response['subnet']
1853
+ rescue RestClient::Exception => e
1854
+ if e.response && e.response.code == 404
1855
+ print_red_alert "Subnet not found by id #{id}"
1856
+ return nil
1857
+ else
1858
+ raise e
1859
+ end
1860
+ end
1861
+ end
1862
+
1863
+ def find_subnet_by_name(network_id, name)
1864
+ json_response = @network_subnets_interface.list(network_id, {name: name.to_s})
1865
+ subnets = json_response['subnets']
1866
+ if subnets.empty?
1867
+ print_red_alert "Subnet not found by name #{name}"
1868
+ return nil
1869
+ elsif subnets.size > 1
1870
+ print_red_alert "#{subnets.size} subnets found by name #{name}"
1871
+ rows = subnets.collect do |it|
1872
+ {id: it['id'], name: it['name']}
1873
+ end
1874
+ puts as_pretty_table(rows, [:id, :name], {color:red})
1875
+ return nil
1876
+ else
1877
+ return subnets[0]
1878
+ end
1879
+ end
1880
+
1881
+ def find_subnet_type_by_name_or_id(val)
1882
+ if val.to_s =~ /\A\d{1,}\Z/
1883
+ return find_subnet_type_by_id(val)
1884
+ else
1885
+ return find_subnet_type_by_name(val)
1886
+ end
1887
+ end
1888
+
1889
+ def find_subnet_type_by_id(id)
1890
+ begin
1891
+ json_response = @network_subnet_types_interface.get(id.to_i)
1892
+ return json_response['subnetType']
1893
+ rescue RestClient::Exception => e
1894
+ if e.response && e.response.code == 404
1895
+ print_red_alert "Subnet Type not found by id #{id}"
1896
+ return nil
1897
+ else
1898
+ raise e
1899
+ end
1900
+ end
1901
+ end
1902
+
1903
+ def find_subnet_type_by_name(name)
1904
+ json_response = @network_subnet_types_interface.list({name: name.to_s})
1905
+ subnet_types = json_response['subnetTypes']
1906
+ if subnet_types.empty?
1907
+ print_red_alert "Subnet Type not found by name #{name}"
1908
+ return subnet_types
1909
+ elsif subnet_types.size > 1
1910
+ print_red_alert "#{subnet_types.size} subnet types found by name #{name}"
1911
+ rows = subnet_types.collect do |it|
1912
+ {id: it['id'], name: it['name']}
1913
+ end
1914
+ puts as_pretty_table(rows, [:id, :name], {color:red})
1915
+ return nil
1916
+ else
1917
+ return subnet_types[0]
1071
1918
  end
1072
1919
  end
1073
1920