morpheus-cli 5.3.0.3 → 5.3.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 +4 -4
- data/Dockerfile +1 -1
- data/README.md +1 -3
- data/lib/morpheus/api/account_groups_interface.rb +0 -6
- data/lib/morpheus/api/accounts_interface.rb +4 -36
- data/lib/morpheus/api/api_client.rb +167 -119
- data/lib/morpheus/api/appliance_settings_interface.rb +6 -9
- data/lib/morpheus/api/approvals_interface.rb +5 -8
- data/lib/morpheus/api/apps_interface.rb +0 -7
- data/lib/morpheus/api/archive_buckets_interface.rb +9 -16
- data/lib/morpheus/api/archive_files_interface.rb +0 -6
- data/lib/morpheus/api/auth_interface.rb +4 -4
- data/lib/morpheus/api/backup_settings_interface.rb +5 -8
- data/lib/morpheus/api/blueprints_interface.rb +1 -7
- data/lib/morpheus/api/budgets_interface.rb +0 -6
- data/lib/morpheus/api/certificate_types_interface.rb +14 -0
- data/lib/morpheus/api/certificates_interface.rb +9 -0
- data/lib/morpheus/api/cloud_datastores_interface.rb +0 -6
- data/lib/morpheus/api/cloud_folders_interface.rb +1 -7
- data/lib/morpheus/api/cloud_policies_interface.rb +0 -6
- data/lib/morpheus/api/cloud_resource_pools_interface.rb +0 -6
- data/lib/morpheus/api/clouds_interface.rb +0 -6
- data/lib/morpheus/api/clusters_interface.rb +39 -42
- data/lib/morpheus/api/containers_interface.rb +0 -6
- data/lib/morpheus/api/custom_instance_types_interface.rb +0 -6
- data/lib/morpheus/api/cypher_interface.rb +0 -6
- data/lib/morpheus/api/datastores_interface.rb +4 -7
- data/lib/morpheus/api/deploy_interface.rb +1 -6
- data/lib/morpheus/api/environments_interface.rb +0 -6
- data/lib/morpheus/api/execute_schedules_interface.rb +0 -6
- data/lib/morpheus/api/execution_request_interface.rb +0 -6
- data/lib/morpheus/api/file_copy_request_interface.rb +2 -9
- data/lib/morpheus/api/group_policies_interface.rb +0 -6
- data/lib/morpheus/api/groups_interface.rb +0 -7
- data/lib/morpheus/api/guidance_interface.rb +9 -12
- data/lib/morpheus/api/health_interface.rb +0 -6
- data/lib/morpheus/api/image_builder_boot_scripts_interface.rb +0 -6
- data/lib/morpheus/api/image_builder_image_builds_interface.rb +0 -6
- data/lib/morpheus/api/image_builder_interface.rb +3 -9
- data/lib/morpheus/api/image_builder_preseed_scripts_interface.rb +0 -6
- data/lib/morpheus/api/instance_types_interface.rb +0 -7
- data/lib/morpheus/api/instances_interface.rb +8 -19
- data/lib/morpheus/api/integration_types_interface.rb +14 -0
- data/lib/morpheus/api/integrations_interface.rb +36 -21
- data/lib/morpheus/api/invoice_line_items_interface.rb +4 -9
- data/lib/morpheus/api/jobs_interface.rb +11 -14
- data/lib/morpheus/api/key_pairs_interface.rb +0 -6
- data/lib/morpheus/api/library_cluster_layouts_interface.rb +0 -6
- data/lib/morpheus/api/library_container_scripts_interface.rb +0 -6
- data/lib/morpheus/api/library_container_templates_interface.rb +0 -6
- data/lib/morpheus/api/library_container_types_interface.rb +0 -6
- data/lib/morpheus/api/library_container_upgrades_interface.rb +0 -6
- data/lib/morpheus/api/library_instance_types_interface.rb +0 -6
- data/lib/morpheus/api/library_layouts_interface.rb +0 -6
- data/lib/morpheus/api/library_spec_template_types_interface.rb +0 -6
- data/lib/morpheus/api/library_spec_templates_interface.rb +0 -6
- data/lib/morpheus/api/license_interface.rb +0 -6
- data/lib/morpheus/api/load_balancer_pools_interface.rb +9 -0
- data/lib/morpheus/api/load_balancer_types_interface.rb +9 -0
- data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +9 -0
- data/lib/morpheus/api/load_balancers_interface.rb +4 -59
- data/lib/morpheus/api/log_settings_interface.rb +9 -12
- data/lib/morpheus/api/logs_interface.rb +0 -6
- data/lib/morpheus/api/monitoring_alerts_interface.rb +0 -6
- data/lib/morpheus/api/monitoring_apps_interface.rb +0 -6
- data/lib/morpheus/api/monitoring_checks_interface.rb +0 -6
- data/lib/morpheus/api/monitoring_contacts_interface.rb +0 -6
- data/lib/morpheus/api/monitoring_groups_interface.rb +0 -6
- data/lib/morpheus/api/monitoring_incidents_interface.rb +0 -6
- data/lib/morpheus/api/monitoring_interface.rb +6 -12
- data/lib/morpheus/api/network_domain_records_interface.rb +0 -6
- data/lib/morpheus/api/network_domains_interface.rb +0 -6
- data/lib/morpheus/api/network_groups_interface.rb +0 -6
- data/lib/morpheus/api/network_pool_ips_interface.rb +0 -6
- data/lib/morpheus/api/network_pool_servers_interface.rb +0 -6
- data/lib/morpheus/api/network_pools_interface.rb +0 -6
- data/lib/morpheus/api/network_proxies_interface.rb +0 -6
- data/lib/morpheus/api/network_routers_interface.rb +56 -6
- data/lib/morpheus/api/network_security_servers_interface.rb +6 -9
- data/lib/morpheus/api/network_services_interface.rb +14 -14
- data/lib/morpheus/api/network_subnets_interface.rb +0 -6
- data/lib/morpheus/api/network_types_interface.rb +1 -7
- data/lib/morpheus/api/networks_interface.rb +0 -6
- data/lib/morpheus/api/option_type_lists_interface.rb +18 -12
- data/lib/morpheus/api/option_types_interface.rb +0 -6
- data/lib/morpheus/api/options_interface.rb +0 -6
- data/lib/morpheus/api/packages_interface.rb +0 -6
- data/lib/morpheus/api/policies_interface.rb +1 -8
- data/lib/morpheus/api/power_schedules_interface.rb +0 -6
- data/lib/morpheus/api/price_sets_interface.rb +8 -11
- data/lib/morpheus/api/prices_interface.rb +12 -15
- data/lib/morpheus/api/processes_interface.rb +0 -6
- data/lib/morpheus/api/provision_types_interface.rb +0 -6
- data/lib/morpheus/api/provisioning_license_types_interface.rb +0 -6
- data/lib/morpheus/api/provisioning_licenses_interface.rb +0 -6
- data/lib/morpheus/api/provisioning_settings_interface.rb +6 -9
- data/lib/morpheus/api/read_interface.rb +23 -0
- data/lib/morpheus/api/reports_interface.rb +0 -6
- data/lib/morpheus/api/rest_interface.rb +12 -10
- data/lib/morpheus/api/roles_interface.rb +7 -6
- data/lib/morpheus/api/secondary_read_interface.rb +25 -0
- data/lib/morpheus/api/secondary_rest_interface.rb +42 -0
- data/lib/morpheus/api/security_group_rules_interface.rb +0 -7
- data/lib/morpheus/api/security_groups_interface.rb +0 -6
- data/lib/morpheus/api/server_types_interface.rb +0 -6
- data/lib/morpheus/api/servers_interface.rb +7 -6
- data/lib/morpheus/api/service_plans_interface.rb +11 -14
- data/lib/morpheus/api/storage_providers_interface.rb +9 -16
- data/lib/morpheus/api/subnet_types_interface.rb +1 -7
- data/lib/morpheus/api/subnets_interface.rb +0 -6
- data/lib/morpheus/api/task_sets_interface.rb +0 -6
- data/lib/morpheus/api/tasks_interface.rb +0 -6
- data/lib/morpheus/api/user_groups_interface.rb +0 -6
- data/lib/morpheus/api/user_settings_interface.rb +38 -18
- data/lib/morpheus/api/user_sources_interface.rb +0 -6
- data/lib/morpheus/api/users_interface.rb +0 -6
- data/lib/morpheus/api/vdi_allocations_interface.rb +9 -0
- data/lib/morpheus/api/vdi_apps_interface.rb +9 -0
- data/lib/morpheus/api/vdi_gateways_interface.rb +9 -0
- data/lib/morpheus/api/vdi_interface.rb +28 -0
- data/lib/morpheus/api/vdi_pools_interface.rb +19 -0
- data/lib/morpheus/api/virtual_images_interface.rb +0 -6
- data/lib/morpheus/api/whitelabel_settings_interface.rb +8 -11
- data/lib/morpheus/api/wiki_interface.rb +0 -6
- data/lib/morpheus/cli.rb +10 -2
- data/lib/morpheus/cli/access_token_command.rb +1 -1
- data/lib/morpheus/cli/account_groups_command.rb +4 -4
- data/lib/morpheus/cli/apps.rb +68 -84
- data/lib/morpheus/cli/archives_command.rb +5 -5
- data/lib/morpheus/cli/blueprints_command.rb +5 -5
- data/lib/morpheus/cli/boot_scripts_command.rb +1 -1
- data/lib/morpheus/cli/catalog_item_types_command.rb +13 -13
- data/lib/morpheus/cli/certificates_command.rb +575 -0
- data/lib/morpheus/cli/change_password_command.rb +4 -4
- data/lib/morpheus/cli/cli_command.rb +72 -16
- data/lib/morpheus/cli/clouds.rb +3 -2
- data/lib/morpheus/cli/clusters.rb +3 -3
- data/lib/morpheus/cli/commands/standard/man_command.rb +4 -5
- data/lib/morpheus/cli/credentials.rb +4 -11
- data/lib/morpheus/cli/environments_command.rb +1 -1
- data/lib/morpheus/cli/execute_schedules_command.rb +3 -3
- data/lib/morpheus/cli/hosts.rb +253 -232
- data/lib/morpheus/cli/image_builder_command.rb +6 -6
- data/lib/morpheus/cli/instance_types.rb +1 -1
- data/lib/morpheus/cli/instances.rb +229 -219
- data/lib/morpheus/cli/integrations_command.rb +1155 -42
- data/lib/morpheus/cli/invoices_command.rb +75 -67
- data/lib/morpheus/cli/key_pairs.rb +2 -2
- data/lib/morpheus/cli/library_cluster_layouts_command.rb +2 -3
- data/lib/morpheus/cli/library_container_scripts_command.rb +4 -5
- data/lib/morpheus/cli/library_container_templates_command.rb +5 -1
- data/lib/morpheus/cli/library_container_types_command.rb +8 -9
- data/lib/morpheus/cli/library_instance_types_command.rb +6 -7
- data/lib/morpheus/cli/library_layouts_command.rb +9 -5
- data/lib/morpheus/cli/library_option_lists_command.rb +72 -20
- data/lib/morpheus/cli/library_option_types_command.rb +8 -4
- data/lib/morpheus/cli/library_spec_templates_command.rb +3 -4
- data/lib/morpheus/cli/library_upgrades_command.rb +6 -6
- data/lib/morpheus/cli/license.rb +2 -2
- data/lib/morpheus/cli/load_balancer_types.rb +37 -0
- data/lib/morpheus/cli/load_balancers.rb +149 -314
- data/lib/morpheus/cli/log_settings_command.rb +7 -3
- data/lib/morpheus/cli/login.rb +10 -1
- data/lib/morpheus/cli/mixins/load_balancers_helper.rb +156 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +44 -18
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +4 -4
- data/lib/morpheus/cli/mixins/rest_command.rb +657 -0
- data/lib/morpheus/cli/mixins/vdi_helper.rb +246 -0
- data/lib/morpheus/cli/network_routers_command.rb +1187 -176
- data/lib/morpheus/cli/networks_command.rb +195 -102
- data/lib/morpheus/cli/option_types.rb +66 -71
- data/lib/morpheus/cli/policies_command.rb +0 -1
- data/lib/morpheus/cli/power_schedules_command.rb +3 -3
- data/lib/morpheus/cli/preseed_scripts_command.rb +1 -1
- data/lib/morpheus/cli/remote.rb +2 -2
- data/lib/morpheus/cli/reports_command.rb +4 -1
- data/lib/morpheus/cli/roles.rb +224 -64
- data/lib/morpheus/cli/security_group_rules.rb +1 -1
- data/lib/morpheus/cli/setup.rb +0 -1
- data/lib/morpheus/cli/subnets_command.rb +11 -2
- data/lib/morpheus/cli/tenants_command.rb +21 -23
- data/lib/morpheus/cli/user_groups_command.rb +3 -3
- data/lib/morpheus/cli/user_settings_command.rb +268 -57
- data/lib/morpheus/cli/user_sources_command.rb +3 -3
- data/lib/morpheus/cli/users.rb +3 -3
- data/lib/morpheus/cli/vdi_allocations_command.rb +159 -0
- data/lib/morpheus/cli/vdi_apps_command.rb +317 -0
- data/lib/morpheus/cli/vdi_command.rb +359 -0
- data/lib/morpheus/cli/vdi_gateways_command.rb +290 -0
- data/lib/morpheus/cli/vdi_pools_command.rb +571 -0
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +1 -1
- data/lib/morpheus/cli/whoami.rb +0 -15
- data/lib/morpheus/cli/wiki_command.rb +1 -1
- data/lib/morpheus/ext/string.rb +41 -0
- data/lib/morpheus/formatters.rb +4 -0
- data/lib/morpheus/rest_client.rb +30 -0
- data/lib/morpheus/terminal.rb +15 -7
- metadata +27 -2
|
@@ -6,11 +6,12 @@ class Morpheus::Cli::LogSettingsCommand
|
|
|
6
6
|
|
|
7
7
|
set_command_name :'log-settings'
|
|
8
8
|
|
|
9
|
-
register_subcommands :get, :update
|
|
10
|
-
register_subcommands :enable_integration, :disable_integration, :remove_integration
|
|
9
|
+
register_subcommands :get, :update
|
|
11
10
|
register_subcommands :add_syslog_rule, :remove_syslog_rule
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
# these command are deprecated in 5.3.3 and can be removed
|
|
13
|
+
register_subcommands :enable_integration, :disable_integration, :remove_integration
|
|
14
|
+
set_subcommands_hidden :enable_integration, :disable_integration, :remove_integration
|
|
14
15
|
|
|
15
16
|
def connect(opts)
|
|
16
17
|
@api_client = establish_remote_appliance_connection(opts)
|
|
@@ -186,6 +187,7 @@ class Morpheus::Cli::LogSettingsCommand
|
|
|
186
187
|
end
|
|
187
188
|
|
|
188
189
|
def enable_integration(args)
|
|
190
|
+
print_error yellow,"[DEPRECATED] The command `#{command_name} enable-integration` is deprecated.",reset,"\n"
|
|
189
191
|
options = {}
|
|
190
192
|
|
|
191
193
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
@@ -240,6 +242,7 @@ class Morpheus::Cli::LogSettingsCommand
|
|
|
240
242
|
end
|
|
241
243
|
|
|
242
244
|
def disable_integration(args)
|
|
245
|
+
print_error yellow,"[DEPRECATED] The command `#{command_name} disable-integration` is deprecated.",reset,"\n"
|
|
243
246
|
options = {}
|
|
244
247
|
|
|
245
248
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
@@ -285,6 +288,7 @@ class Morpheus::Cli::LogSettingsCommand
|
|
|
285
288
|
end
|
|
286
289
|
|
|
287
290
|
def remove_integration(args)
|
|
291
|
+
print_error yellow,"[DEPRECATED] The command `#{command_name } remove-integration` is deprecated.",reset,"\n"
|
|
288
292
|
options = {}
|
|
289
293
|
|
|
290
294
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
data/lib/morpheus/cli/login.rb
CHANGED
|
@@ -36,6 +36,13 @@ class Morpheus::Cli::Login
|
|
|
36
36
|
opts.on( '-p', '--password PASSWORD', "Password" ) do |val|
|
|
37
37
|
password = val
|
|
38
38
|
end
|
|
39
|
+
opts.on( '--password-file FILE', String, "Password File, read a file containing the password." ) do |val|
|
|
40
|
+
password_file = File.expand_path(val)
|
|
41
|
+
if !File.exists?(password_file) || !File.file?(password_file) # check readable too
|
|
42
|
+
raise ::OptionParser::InvalidOption.new("File not found: #{password_file}")
|
|
43
|
+
end
|
|
44
|
+
password = File.read(password_file) #.to_s.split("\n").first.strip
|
|
45
|
+
end
|
|
39
46
|
opts.on( '-t', '--test', "Test credentials only, does not update stored credentials for the appliance." ) do
|
|
40
47
|
options[:test_only] = true
|
|
41
48
|
end
|
|
@@ -70,7 +77,9 @@ EOT
|
|
|
70
77
|
# connect(options)
|
|
71
78
|
@api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true, :skip_login => true}))
|
|
72
79
|
|
|
73
|
-
if
|
|
80
|
+
if options[:test_only]
|
|
81
|
+
puts "Testing credentials, your current session will not be modified."
|
|
82
|
+
elsif @remote_appliance[:authenticated]
|
|
74
83
|
puts "You will be automatically logged out of your current session as '#{@remote_appliance[:username]}'"
|
|
75
84
|
end
|
|
76
85
|
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
require 'morpheus/cli/mixins/print_helper'
|
|
2
|
+
require 'morpheus/cli/option_types'
|
|
3
|
+
require 'morpheus/rest_client'
|
|
4
|
+
# Mixin for Morpheus::Cli command classes
|
|
5
|
+
# Provides common methods for load balancer management
|
|
6
|
+
# including load balancers, load balancer types, virtual servers, etc.
|
|
7
|
+
module Morpheus::Cli::LoadBalancersHelper
|
|
8
|
+
|
|
9
|
+
def self.included(klass)
|
|
10
|
+
klass.send :include, Morpheus::Cli::PrintHelper
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def load_balancers_interface
|
|
14
|
+
# @api_client.load_balancers
|
|
15
|
+
raise "#{self.class} has not defined @load_balancers_interface" if @load_balancers_interface.nil?
|
|
16
|
+
@load_balancers_interface
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def load_balancer_types_interface
|
|
20
|
+
# @api_client.load_balancer_types
|
|
21
|
+
raise "#{self.class} has not defined @load_balancer_types_interface" if @load_balancer_types_interface.nil?
|
|
22
|
+
@load_balancer_types_interface
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def load_balancer_object_key
|
|
26
|
+
'loadBalancer'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def load_balancer_list_key
|
|
30
|
+
'loadBalancers'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def load_balancer_label
|
|
34
|
+
'Load Balancer'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def load_balancer_plural_label
|
|
38
|
+
'Load Balancers'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def load_balancer_type_object_key
|
|
42
|
+
'loadBalancerType'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def load_balancer_type_list_key
|
|
46
|
+
'loadBalancerTypes'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def load_balancer_type_label
|
|
50
|
+
'Load Balancer Type'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def load_balancer_type_plural_label
|
|
54
|
+
'Load Balancer Types'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def find_load_balancer_by_name_or_id(val)
|
|
58
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
|
59
|
+
return find_load_balancer_by_id(val)
|
|
60
|
+
else
|
|
61
|
+
return find_load_balancer_by_name(val)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def find_load_balancer_by_id(id)
|
|
66
|
+
begin
|
|
67
|
+
json_response = load_balancers_interface.get(id.to_i)
|
|
68
|
+
return json_response[load_balancer_object_key]
|
|
69
|
+
rescue RestClient::Exception => e
|
|
70
|
+
if e.response && e.response.code == 404
|
|
71
|
+
print_red_alert "Load Balancer not found by id #{id}"
|
|
72
|
+
else
|
|
73
|
+
raise e
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def find_load_balancer_by_name(name)
|
|
79
|
+
lbs = load_balancers_interface.list({name: name.to_s})[load_balancer_list_key]
|
|
80
|
+
if lbs.empty?
|
|
81
|
+
print_red_alert "Load Balancer not found by name #{name}"
|
|
82
|
+
return nil
|
|
83
|
+
elsif lbs.size > 1
|
|
84
|
+
print_red_alert "#{lbs.size} load balancers found by name #{name}"
|
|
85
|
+
#print_lbs_table(lbs, {color: red})
|
|
86
|
+
print reset,"\n\n"
|
|
87
|
+
return nil
|
|
88
|
+
else
|
|
89
|
+
return lbs[0]
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def get_available_load_balancer_types(refresh=false)
|
|
94
|
+
if !@available_load_balancer_types || refresh
|
|
95
|
+
@available_load_balancer_types = load_balancer_types_interface.list({max:1000})[load_balancer_type_list_key]
|
|
96
|
+
end
|
|
97
|
+
return @available_load_balancer_types
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def load_balancer_type_for_name_or_id(val)
|
|
101
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
|
102
|
+
return load_balancer_type_for_id(val)
|
|
103
|
+
else
|
|
104
|
+
return load_balancer_type_for_name(val)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def load_balancer_type_for_id(id)
|
|
109
|
+
return get_available_load_balancer_types().find { |z| z['id'].to_i == id.to_i}
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def load_balancer_type_for_name(name)
|
|
113
|
+
return get_available_load_balancer_types().find { |z| z['name'].downcase == name.downcase || z['code'].downcase == name.downcase}
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def find_load_balancer_type_by_name_or_id(val)
|
|
117
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
|
118
|
+
return find_load_balancer_type_by_id(val)
|
|
119
|
+
else
|
|
120
|
+
return find_load_balancer_type_by_name(val)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def find_load_balancer_type_by_id(id)
|
|
125
|
+
begin
|
|
126
|
+
json_response = load_balancer_types_interface.get(id.to_i)
|
|
127
|
+
return json_response[load_balancer_type_object_key]
|
|
128
|
+
rescue RestClient::Exception => e
|
|
129
|
+
if e.response && e.response.code == 404
|
|
130
|
+
print_red_alert "Load Balancer Type not found by id #{id}"
|
|
131
|
+
return nil
|
|
132
|
+
else
|
|
133
|
+
raise e
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def find_load_balancer_type_by_name(name)
|
|
139
|
+
json_response = load_balancer_types_interface.list({name: name.to_s})
|
|
140
|
+
load_balancer_types = json_response[load_balancer_type_list_key]
|
|
141
|
+
if load_balancer_types.empty?
|
|
142
|
+
print_red_alert "Load Balancer Type not found by name #{name}"
|
|
143
|
+
return load_balancer_types
|
|
144
|
+
elsif load_balancer_types.size > 1
|
|
145
|
+
print_red_alert "#{load_balancer_types.size} load balancer types found by name #{name}"
|
|
146
|
+
rows = load_balancer_types.collect do |it|
|
|
147
|
+
{id: it['id'], name: it['name']}
|
|
148
|
+
end
|
|
149
|
+
puts as_pretty_table(rows, [:id, :name], {color:red})
|
|
150
|
+
return nil
|
|
151
|
+
else
|
|
152
|
+
return load_balancer_types[0]
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
end
|
|
@@ -228,7 +228,8 @@ module Morpheus::Cli::PrintHelper
|
|
|
228
228
|
out << cyan
|
|
229
229
|
if payload
|
|
230
230
|
out << "\n"
|
|
231
|
-
|
|
231
|
+
is_multipart = (payload.is_a?(Hash) && payload[:multipart] == true)
|
|
232
|
+
content_type = (headers && headers['Content-Type']) ? headers['Content-Type'] : (is_multipart ? 'multipart/form-data' : 'application/x-www-form-urlencoded')
|
|
232
233
|
if content_type == 'application/json'
|
|
233
234
|
if payload.is_a?(String)
|
|
234
235
|
begin
|
|
@@ -257,12 +258,21 @@ module Morpheus::Cli::PrintHelper
|
|
|
257
258
|
out << payload
|
|
258
259
|
end
|
|
259
260
|
else
|
|
260
|
-
if content_type == 'application/x-www-form-urlencoded'
|
|
261
|
+
if content_type == 'application/x-www-form-urlencoded' || content_type.to_s.include?('multipart')
|
|
261
262
|
body_str = payload.to_s
|
|
262
263
|
begin
|
|
264
|
+
payload.delete(:multipart) if payload.is_a?(Hash)
|
|
265
|
+
# puts "grailsifying it!"
|
|
266
|
+
payload = Morpheus::RestClient.grails_params(payload)
|
|
267
|
+
payload.each do |k,v|
|
|
268
|
+
if v.is_a?(File)
|
|
269
|
+
payload[k] = "@#{v.path}"
|
|
270
|
+
payload[k] = v.path
|
|
271
|
+
end
|
|
272
|
+
end
|
|
263
273
|
body_str = URI.encode_www_form(payload)
|
|
264
274
|
rescue => ex
|
|
265
|
-
|
|
275
|
+
raise ex
|
|
266
276
|
end
|
|
267
277
|
if options[:scrub]
|
|
268
278
|
out << Morpheus::Logging.scrub_message(body_str)
|
|
@@ -273,7 +283,7 @@ module Morpheus::Cli::PrintHelper
|
|
|
273
283
|
if options[:scrub]
|
|
274
284
|
out << Morpheus::Logging.scrub_message(payload)
|
|
275
285
|
else
|
|
276
|
-
out << payload
|
|
286
|
+
out << payload.to_s
|
|
277
287
|
end
|
|
278
288
|
end
|
|
279
289
|
end
|
|
@@ -327,7 +337,9 @@ module Morpheus::Cli::PrintHelper
|
|
|
327
337
|
else
|
|
328
338
|
out << " -d '#{payload}'"
|
|
329
339
|
end
|
|
340
|
+
out << "\n"
|
|
330
341
|
else
|
|
342
|
+
is_multipart = (payload.is_a?(Hash) && payload[:multipart] == true)
|
|
331
343
|
content_type = headers['Content-Type'] || 'application/x-www-form-urlencoded'
|
|
332
344
|
|
|
333
345
|
if payload.is_a?(File)
|
|
@@ -337,21 +349,22 @@ module Morpheus::Cli::PrintHelper
|
|
|
337
349
|
out << " -d @#{payload.path}"
|
|
338
350
|
elsif payload.is_a?(String)
|
|
339
351
|
out << " -d '#{payload}'"
|
|
340
|
-
|
|
341
|
-
if
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
352
|
+
elsif payload.respond_to?(:map)
|
|
353
|
+
payload.delete(:multipart) if payload.is_a?(Hash)
|
|
354
|
+
# puts "grailsifying it!"
|
|
355
|
+
payload = Morpheus::RestClient.grails_params(payload)
|
|
356
|
+
payload.each do |k,v|
|
|
357
|
+
if v.is_a?(File)
|
|
358
|
+
out << " -F '#{k}=@#{v.path}"
|
|
359
|
+
else
|
|
360
|
+
out << " -d '#{URI.encode_www_form({(k) => v})}'"
|
|
347
361
|
end
|
|
348
|
-
out << "
|
|
349
|
-
else
|
|
350
|
-
out << " -d '#{payload}'"
|
|
362
|
+
out << "\n"
|
|
351
363
|
end
|
|
364
|
+
#body_str = URI.encode_www_form(payload)
|
|
365
|
+
# out << " -d '#{body_str}'"
|
|
352
366
|
end
|
|
353
367
|
end
|
|
354
|
-
out << "\n"
|
|
355
368
|
else
|
|
356
369
|
out << "\n"
|
|
357
370
|
end
|
|
@@ -431,12 +444,13 @@ module Morpheus::Cli::PrintHelper
|
|
|
431
444
|
out = ""
|
|
432
445
|
bars = []
|
|
433
446
|
percent = 0
|
|
447
|
+
percent_sigdig = opts[:percent_sigdig] || 2
|
|
434
448
|
if max_value.to_i == 0
|
|
435
449
|
percent = 0
|
|
436
450
|
else
|
|
437
451
|
percent = ((used_value.to_f / max_value.to_f) * 100)
|
|
438
452
|
end
|
|
439
|
-
percent_label = ((used_value.nil? || max_value.to_f == 0.0) ? "n/a" : "#{percent.round(
|
|
453
|
+
percent_label = ((used_value.nil? || max_value.to_f == 0.0) ? "n/a" : "#{percent.round(percent_sigdig)}%").rjust(6, ' ')
|
|
440
454
|
bar_display = ""
|
|
441
455
|
if percent > 100
|
|
442
456
|
max_bars.times { bars << "|" }
|
|
@@ -674,7 +688,7 @@ module Morpheus::Cli::PrintHelper
|
|
|
674
688
|
else
|
|
675
689
|
# so let's use the passed in column definitions instead of the raw data properties
|
|
676
690
|
# columns = options[:include_fields]
|
|
677
|
-
new_columns =
|
|
691
|
+
new_columns = {}
|
|
678
692
|
options[:include_fields].each do |f|
|
|
679
693
|
matching_column = nil
|
|
680
694
|
# column definitions vary right now, array of symbols/strings/hashes or perhaps a single hash
|
|
@@ -692,7 +706,7 @@ module Morpheus::Cli::PrintHelper
|
|
|
692
706
|
matching_column = columns[matching_key]
|
|
693
707
|
end
|
|
694
708
|
end
|
|
695
|
-
new_columns
|
|
709
|
+
new_columns[f] = matching_column ? matching_column : f
|
|
696
710
|
end
|
|
697
711
|
columns = new_columns
|
|
698
712
|
end
|
|
@@ -1072,6 +1086,7 @@ module Morpheus::Cli::PrintHelper
|
|
|
1072
1086
|
column_defs.each do |column_def|
|
|
1073
1087
|
label = column_def.label
|
|
1074
1088
|
value = column_def.display_method.call(obj)
|
|
1089
|
+
value = value.is_a?(String) ? value : JSON.fast_generate(value)
|
|
1075
1090
|
# value = get_object_value(obj, column_def)
|
|
1076
1091
|
if do_quotes
|
|
1077
1092
|
cells << quote_csv_value(value)
|
|
@@ -1320,4 +1335,15 @@ module Morpheus::Cli::PrintHelper
|
|
|
1320
1335
|
parse_json_or_yaml(config, parsers)
|
|
1321
1336
|
end
|
|
1322
1337
|
|
|
1338
|
+
def format_option_types_table(option_types, options={}, domain_name=nil)
|
|
1339
|
+
columns = [
|
|
1340
|
+
{"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
|
|
1341
|
+
{"FIELD NAME" => lambda {|it| [it['fieldContext'] == domain_name ? nil : it['fieldContext'], it['fieldName']].select {|it| !it.to_s.empty? }.join('.') } },
|
|
1342
|
+
{"TYPE" => lambda {|it| it['type'] } },
|
|
1343
|
+
{"DEFAULT" => lambda {|it| it['defaultValue'] } },
|
|
1344
|
+
{"REQUIRED" => lambda {|it| format_boolean it['required'] } },
|
|
1345
|
+
]
|
|
1346
|
+
as_pretty_table(option_types, columns, options)
|
|
1347
|
+
end
|
|
1348
|
+
|
|
1323
1349
|
end
|
|
@@ -508,7 +508,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
|
508
508
|
if name_prompt['name'].nil? && !options[:name_required]
|
|
509
509
|
break
|
|
510
510
|
else
|
|
511
|
-
if instances_interface.
|
|
511
|
+
if instances_interface.list({name: name_prompt['name']})['instances'].empty?
|
|
512
512
|
instance_name = name_prompt['name']
|
|
513
513
|
else
|
|
514
514
|
print_red_alert "Name must be unique"
|
|
@@ -696,7 +696,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
|
696
696
|
# prompt for service plan
|
|
697
697
|
plan_id = nil
|
|
698
698
|
service_plan = nil
|
|
699
|
-
service_plans_json =
|
|
699
|
+
service_plans_json = instances_interface.service_plans({zoneId: cloud_id, layoutId: layout['id'], siteId: group_id})
|
|
700
700
|
service_plans = service_plans_json["plans"]
|
|
701
701
|
if locked_fields.include?('plan.id')
|
|
702
702
|
plan_id = options[:options]['plan']['id'] rescue nil
|
|
@@ -764,7 +764,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
|
764
764
|
# pluck out the resourcePoolId option type to prompt for
|
|
765
765
|
resource_pool_option_type = option_type_list.find {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
|
766
766
|
option_type_list = option_type_list.reject {|opt| ['resourcePool','resourcePoolId','azureResourceGroupId'].include?(opt['fieldName']) }
|
|
767
|
-
resource_pool_options =
|
|
767
|
+
resource_pool_options = options_interface.options_for_source('zonePools', {groupId: group_id, siteId: group_id, zoneId: cloud_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], planId: service_plan["id"], layoutId: layout["id"]})['data']
|
|
768
768
|
resource_pool = resource_pool_options.find {|opt| opt['id'] == options[:resource_pool].to_i} if options[:resource_pool]
|
|
769
769
|
|
|
770
770
|
if resource_pool
|
|
@@ -1409,7 +1409,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
|
1409
1409
|
if plan_info['addVolumes']
|
|
1410
1410
|
volume_index = current_volumes.size
|
|
1411
1411
|
has_another_volume = options[:options] && options[:options]["dataVolume#{volume_index}"]
|
|
1412
|
-
add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add data volume?"))
|
|
1412
|
+
add_another_volume = has_another_volume || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add data volume?", {:default => false}))
|
|
1413
1413
|
while add_another_volume do
|
|
1414
1414
|
#puts "Configure Data #{volume_index} Volume"
|
|
1415
1415
|
|
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
# RestCommand is a mixin for Morpheus::Cli command classes.
|
|
2
|
+
# Provides basic CRUD commands: list, get, add, update, remove
|
|
3
|
+
# Currently the command class must also include Morpheus::Cli::CliCommand
|
|
4
|
+
# The command class can define a few variables to dictate what the resource
|
|
5
|
+
# is called and the the api interface used to fetch the records. The command class
|
|
6
|
+
# or helper must also provide several methods to provide the default behavior.
|
|
7
|
+
# In the example below, the command (helper) defines the following methods:
|
|
8
|
+
# * load_balancer_object_key() - Key name of object returned by the "get" api endpoint.
|
|
9
|
+
# * load_balancer_list_key() - Key name of array of records returned by the "list" api endpoint.
|
|
10
|
+
# * load_balancer_column_definitions() - Column definitions for the "get" command display output.
|
|
11
|
+
# * load_balancer_list_column_definitions() - Column definitions for the "list" command display output.
|
|
12
|
+
#
|
|
13
|
+
# # An example of a RestCommand for `morpheus load-balancers`.
|
|
14
|
+
# class Morpheus::Cli::LoadBalancers
|
|
15
|
+
#
|
|
16
|
+
# include Morpheus::Cli::CliCommand
|
|
17
|
+
# include Morpheus::Cli::RestCommand
|
|
18
|
+
# include Morpheus::Cli::LoadBalancersHelper
|
|
19
|
+
#
|
|
20
|
+
# # All of the example settings below are redundant
|
|
21
|
+
# # and would be the default values if not set.
|
|
22
|
+
# set_rest_name :load_balancers
|
|
23
|
+
# set_rest_label "Load Balancer"
|
|
24
|
+
# set_rest_plural_label "Load Balancers"
|
|
25
|
+
# set_rest_object_key "load_balancer"
|
|
26
|
+
# set_rest_has_type true
|
|
27
|
+
# set_rest_type "load_balancer_types"
|
|
28
|
+
# register_interfaces :load_balancers, :load_balancer_types
|
|
29
|
+
#
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
module Morpheus::Cli::RestCommand
|
|
33
|
+
def self.included(base)
|
|
34
|
+
#puts "including RestCommand for #{base}"
|
|
35
|
+
#base.send :include, Morpheus::Cli::CliCommand
|
|
36
|
+
base.extend ClassMethods
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
module ClassMethods
|
|
40
|
+
|
|
41
|
+
# rest_name is the plural name of the rest command resource eg. NeatThingsCommand would be "neat_things"
|
|
42
|
+
# It is used to derive all other default rest settings key, label, etc.
|
|
43
|
+
# The default name the command name with underscores `_` instead of dashes `-`.
|
|
44
|
+
def rest_name
|
|
45
|
+
@rest_name || default_rest_name
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def default_rest_name
|
|
49
|
+
self.command_name.to_s.gsub("-", "_")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def rest_name=(v)
|
|
53
|
+
@rest_name = v
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
alias :set_rest_name :rest_name=
|
|
57
|
+
|
|
58
|
+
# rest_key is the singular name of the resource eg. "neat_thing"
|
|
59
|
+
def rest_key
|
|
60
|
+
@rest_key || default_rest_key
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def default_rest_key
|
|
64
|
+
rest_name.chomp("s")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def rest_key=(v)
|
|
68
|
+
@rest_key = v
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
alias :set_rest_key :rest_key=
|
|
72
|
+
|
|
73
|
+
# rest_arg is a label for the arg in the command usage eg. "thing" gets displayed as [thing]
|
|
74
|
+
def rest_arg
|
|
75
|
+
@rest_arg || default_rest_arg
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def default_rest_arg
|
|
79
|
+
rest_key.gsub("_", " ") # "[" + rest_key.gsub("_", " ") + "]"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def rest_arg=(v)
|
|
83
|
+
@rest_arg = v
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
alias :set_rest_arg :rest_arg=
|
|
87
|
+
|
|
88
|
+
# rest_label is the capitalized resource label eg. "Neat Thing"
|
|
89
|
+
def rest_label
|
|
90
|
+
@rest_label || default_rest_label
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def default_rest_label
|
|
94
|
+
rest_key.to_s.split("_").collect {|it| it.to_s.capitalize }.join(" ")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def rest_label=(v)
|
|
98
|
+
@rest_label = v
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
alias :set_rest_label :rest_label=
|
|
102
|
+
|
|
103
|
+
# the plural version of the label eg. "Neat Things"
|
|
104
|
+
def rest_plural_label
|
|
105
|
+
@rest_plural_label || default_rest_plural_label
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def default_rest_plural_label
|
|
109
|
+
#rest_name.to_s.split("_").collect {|it| it.to_s.capitalize }.join(" ")
|
|
110
|
+
rest_label.to_s.pluralize
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def rest_plural_label=(v)
|
|
114
|
+
@rest_plural_label = v
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
alias :set_rest_plural_label :rest_plural_label=
|
|
118
|
+
|
|
119
|
+
# rest_interface_name is the interface name for the resource. eg. "neat_things"
|
|
120
|
+
def rest_interface_name
|
|
121
|
+
@rest_interface_name || default_rest_interface_name
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def default_rest_interface_name
|
|
125
|
+
rest_name
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def rest_interface_name=(v)
|
|
129
|
+
@rest_interface_name = v
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
alias :set_rest_interface_name :rest_interface_name=
|
|
133
|
+
|
|
134
|
+
# rest_has_type indicates a resource has a type. default is false
|
|
135
|
+
def rest_has_type
|
|
136
|
+
@rest_has_type == true
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def default_rest_has_type
|
|
140
|
+
false
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def rest_has_type=(v)
|
|
144
|
+
@rest_has_type = !!v
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
alias :set_rest_has_type :rest_has_type=
|
|
148
|
+
|
|
149
|
+
## duplicated the rest_* settings with rest_type, for the types resource
|
|
150
|
+
|
|
151
|
+
# rest_type_name is the rest_name for the type, only applicable if rest_has_type
|
|
152
|
+
def rest_type_name
|
|
153
|
+
@rest_type_name || default_rest_type_name
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def default_rest_type_name
|
|
157
|
+
rest_key + "_types"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def rest_type_name=(v)
|
|
161
|
+
@rest_type_name = v
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
alias :set_rest_type_name :rest_type_name=
|
|
165
|
+
alias :set_rest_type :rest_type_name=
|
|
166
|
+
#alias :rest_type= :rest_type_name=
|
|
167
|
+
|
|
168
|
+
# rest_type_key is the singular name of the resource eg. "neat_thing"
|
|
169
|
+
def rest_type_key
|
|
170
|
+
@rest_type_key || default_rest_type_key
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def default_rest_type_key
|
|
174
|
+
rest_type_name.chomp("s")
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def rest_type_key=(v)
|
|
178
|
+
@rest_type_key = v
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
alias :set_rest_type_key :rest_type_key=
|
|
182
|
+
|
|
183
|
+
def rest_type_arg
|
|
184
|
+
@rest_type_arg || default_rest_type_arg
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def default_rest_type_arg
|
|
188
|
+
# rest_type_key.gsub("_", " ") # "[" + rest_key.gsub("_", " ") + "]"
|
|
189
|
+
"type" # [type]
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def rest_type_arg=(v)
|
|
193
|
+
@rest_type_arg = v
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
alias :set_rest_type_arg :rest_type_arg=
|
|
197
|
+
|
|
198
|
+
# rest_type_label is the capitalized resource label eg. "Neat Thing"
|
|
199
|
+
def rest_type_label
|
|
200
|
+
@rest_type_label || default_rest_type_label
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def default_rest_type_label
|
|
204
|
+
rest_type_key.to_s.split("_").collect {|it| it.to_s.capitalize }.join(" ")
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def rest_type_label=(v)
|
|
208
|
+
@rest_type_label = v
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
alias :set_rest_type_label :rest_type_label=
|
|
212
|
+
|
|
213
|
+
# the plural version of the label eg. "Neat Things"
|
|
214
|
+
def rest_type_plural_label
|
|
215
|
+
@rest_type_plural_label || default_rest_type_plural_label
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def default_rest_type_plural_label
|
|
219
|
+
#rest_type_name.to_s.split("_").collect {|it| it.to_s.capitalize }.join(" ")
|
|
220
|
+
rest_type_label.to_s.pluralize
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def rest_type_plural_label=(v)
|
|
224
|
+
@rest_type_plural_label = v
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
alias :set_rest_type_plural_label :rest_type_plural_label=
|
|
228
|
+
|
|
229
|
+
# the name of the default interface, matches the rest name eg. "neat_things"
|
|
230
|
+
def rest_type_interface_name
|
|
231
|
+
@rest_type_interface_name || default_rest_type_interface_name
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def default_rest_type_interface_name
|
|
235
|
+
rest_type_name
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def rest_type_interface_name=(v)
|
|
239
|
+
@rest_type_interface_name = v
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
alias :set_rest_type_interface_name :rest_type_interface_name=
|
|
243
|
+
|
|
244
|
+
# set or append to the list of interface names to register for this command
|
|
245
|
+
# The registered interfaces will be pre-loaded into instance variables
|
|
246
|
+
# eg. [:neat_things, :neat_thing_types] will instantiate @neat_things_interface and @neat_thing_types_interface
|
|
247
|
+
def register_interfaces(*interfaces)
|
|
248
|
+
@registered_interfaces ||= []
|
|
249
|
+
interfaces.flatten.each do |it|
|
|
250
|
+
@registered_interfaces << it.to_sym
|
|
251
|
+
end
|
|
252
|
+
# put the default rest_interface first
|
|
253
|
+
if rest_interface_name && !@registered_interfaces.include?(rest_interface_name)
|
|
254
|
+
@registered_interfaces.unshift(rest_interface_name)
|
|
255
|
+
end
|
|
256
|
+
# and also the rest_type_interface
|
|
257
|
+
if rest_has_type && !@registered_interfaces.include?(rest_type_interface_name)
|
|
258
|
+
@registered_interfaces.unshift(rest_type_interface_name)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
alias :register_interface :register_interfaces
|
|
263
|
+
|
|
264
|
+
# get list of interface names that are registered for this command
|
|
265
|
+
# automatically includes the interface for the rest_name and rest_type_name if has_type
|
|
266
|
+
def registered_interfaces
|
|
267
|
+
@registered_interfaces ||= []
|
|
268
|
+
# put the default rest_interface first
|
|
269
|
+
if @registered_interfaces.empty?
|
|
270
|
+
if rest_interface_name
|
|
271
|
+
@registered_interfaces.unshift(rest_interface_name)
|
|
272
|
+
end
|
|
273
|
+
if rest_has_type
|
|
274
|
+
@registered_interfaces.unshift(rest_type_interface_name)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
@registered_interfaces
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# clear the list of registered interfaces, perhaps useful in a command subclass
|
|
281
|
+
def clear_registered_interfaces()
|
|
282
|
+
@registered_interfaces = []
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def rest_name
|
|
288
|
+
self.class.rest_name
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def rest_key
|
|
292
|
+
self.class.rest_key
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def rest_arg
|
|
296
|
+
self.class.rest_arg
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def rest_label
|
|
300
|
+
self.class.rest_label
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def rest_plural_label
|
|
304
|
+
self.class.rest_plural_label
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def rest_interface_name
|
|
308
|
+
self.class.rest_interface_name
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# returns the default rest interface, allows using rest_interface_name = "your"
|
|
312
|
+
# or override this method to return @your_interface if needed
|
|
313
|
+
def rest_interface
|
|
314
|
+
instance_variable_get("@#{rest_interface_name}_interface")
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def rest_object_key
|
|
318
|
+
self.send("#{rest_key}_object_key")
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def rest_list_key
|
|
322
|
+
self.send("#{rest_key}_list_key")
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def rest_column_definitions
|
|
326
|
+
self.send("#{rest_key}_column_definitions")
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def rest_list_column_definitions
|
|
330
|
+
self.send("#{rest_key}_list_column_definitions")
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def rest_find_by_name_or_id(name)
|
|
334
|
+
return self.send("find_#{rest_key}_by_name_or_id", name)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def rest_has_type
|
|
338
|
+
self.class.rest_has_type
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
## duplicated the rest_* settings with rest_type, for the types resource
|
|
342
|
+
|
|
343
|
+
def rest_type_name
|
|
344
|
+
self.class.rest_type_name
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def rest_type_key
|
|
348
|
+
self.class.rest_type_key
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def rest_type_arg
|
|
352
|
+
self.class.rest_type_arg
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def rest_type_label
|
|
356
|
+
self.class.rest_type_label
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def rest_type_plural_label
|
|
360
|
+
self.class.rest_type_plural_label
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def rest_type_interface_name
|
|
364
|
+
self.class.rest_type_interface_name # || "@#{rest_type_name}_interface"
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def rest_type_interface
|
|
368
|
+
instance_variable_get("@#{rest_type_interface_name}_interface")
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def rest_type_object_key
|
|
372
|
+
self.send("#{rest_type_key}_object_key")
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def rest_type_list_key
|
|
376
|
+
self.send("#{rest_type_key}_list_key")
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def rest_type_column_definitions
|
|
380
|
+
self.send("#{rest_type_key}_column_definitions")
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def rest_type_list_column_definitions
|
|
384
|
+
self.send("#{rest_type_key}_list_column_definitions")
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def rest_type_find_by_name_or_id(name)
|
|
388
|
+
return self.send("find_#{rest_type_key}_by_name_or_id", name)
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def registered_interfaces
|
|
392
|
+
self.class.registered_interfaces
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
# standard connect method to establish @api_client
|
|
396
|
+
# and @{name}_interface variables for each registered interface.
|
|
397
|
+
def connect(options)
|
|
398
|
+
@api_client = establish_remote_appliance_connection(options)
|
|
399
|
+
self.class.registered_interfaces.each do |interface_name|
|
|
400
|
+
if interface_name.is_a?(String) || interface_name.is_a?(Symbol)
|
|
401
|
+
instance_variable_set("@#{interface_name}_interface", @api_client.send(interface_name))
|
|
402
|
+
elsif interface_name.is_a?(Hash)
|
|
403
|
+
interface_name.each do |k,v|
|
|
404
|
+
instance_variable_set("#{k}_interface", @api_client.send(v))
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
def handle(args)
|
|
411
|
+
handle_subcommand(args)
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
def list(args)
|
|
415
|
+
params = {}
|
|
416
|
+
options = {}
|
|
417
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
418
|
+
opts.banner = subcommand_usage()
|
|
419
|
+
build_standard_list_options(opts, options)
|
|
420
|
+
opts.footer = "List #{rest_plural_label.downcase}."
|
|
421
|
+
end
|
|
422
|
+
optparse.parse!(args)
|
|
423
|
+
connect(options)
|
|
424
|
+
if args.count > 0
|
|
425
|
+
options[:phrase] = args.join(" ")
|
|
426
|
+
end
|
|
427
|
+
params.merge!(parse_list_options(options))
|
|
428
|
+
rest_interface.setopts(options)
|
|
429
|
+
if options[:dry_run]
|
|
430
|
+
print_dry_run rest_interface.dry.list(params)
|
|
431
|
+
return
|
|
432
|
+
end
|
|
433
|
+
json_response = rest_interface.list(params)
|
|
434
|
+
render_response(json_response, options, rest_list_key) do
|
|
435
|
+
records = json_response[rest_list_key]
|
|
436
|
+
print_h1 "Morpheus #{rest_plural_label}"
|
|
437
|
+
if records.nil? || records.empty?
|
|
438
|
+
print cyan,"No #{rest_plural_label.downcase} found.",reset,"\n"
|
|
439
|
+
else
|
|
440
|
+
print as_pretty_table(records, rest_list_column_definitions.upcase_keys!, options)
|
|
441
|
+
print_results_pagination(json_response) if json_response['meta']
|
|
442
|
+
end
|
|
443
|
+
print reset,"\n"
|
|
444
|
+
end
|
|
445
|
+
return 0, nil
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def get(args)
|
|
449
|
+
params = {}
|
|
450
|
+
options = {}
|
|
451
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
452
|
+
opts.banner = subcommand_usage("[type]")
|
|
453
|
+
build_standard_get_options(opts, options)
|
|
454
|
+
opts.footer = <<-EOT
|
|
455
|
+
Get details about #{a_or_an(rest_label)} #{rest_label.downcase}.
|
|
456
|
+
[#{rest_arg}] is required. This is the name or id of #{a_or_an(rest_label)} #{rest_label.downcase}.
|
|
457
|
+
EOT
|
|
458
|
+
end
|
|
459
|
+
optparse.parse!(args)
|
|
460
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
461
|
+
connect(options)
|
|
462
|
+
params.merge!(parse_query_options(options))
|
|
463
|
+
id_list = parse_id_list(args)
|
|
464
|
+
return run_command_for_each_arg(id_list) do |arg|
|
|
465
|
+
_get(arg, params, options)
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def _get(id, params, options)
|
|
470
|
+
if id !~ /\A\d{1,}\Z/
|
|
471
|
+
record = rest_find_by_name_or_id(id)
|
|
472
|
+
if record.nil?
|
|
473
|
+
raise_command_error "#{rest_label} not found for name '#{id}'"
|
|
474
|
+
end
|
|
475
|
+
id = record['id']
|
|
476
|
+
end
|
|
477
|
+
rest_interface.setopts(options)
|
|
478
|
+
if options[:dry_run]
|
|
479
|
+
print_dry_run rest_interface.dry.get(id, params)
|
|
480
|
+
return
|
|
481
|
+
end
|
|
482
|
+
json_response = rest_interface.get(id, params)
|
|
483
|
+
render_response_for_get(json_response, options)
|
|
484
|
+
return 0, nil
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
def render_response_for_get(json_response, options)
|
|
488
|
+
render_response(json_response, options, rest_object_key) do
|
|
489
|
+
record = json_response[rest_object_key]
|
|
490
|
+
print_h1 rest_label, [], options
|
|
491
|
+
print cyan
|
|
492
|
+
print_description_list(rest_column_definitions, record, options)
|
|
493
|
+
# show config settings...
|
|
494
|
+
if record['optionTypes'] && record['optionTypes'].size > 0
|
|
495
|
+
print_h2 "Option Types", options
|
|
496
|
+
print format_option_types_table(record['optionTypes'], options, rest_object_key)
|
|
497
|
+
end
|
|
498
|
+
print reset,"\n"
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
def add(args)
|
|
503
|
+
record_type_id = nil
|
|
504
|
+
options = {}
|
|
505
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
506
|
+
if rest_has_type
|
|
507
|
+
opts.banner = subcommand_usage("[name] -t TYPE")
|
|
508
|
+
opts.on( '-t', "--#{rest_type_arg} TYPE", "#{rest_type_label}" ) do |val|
|
|
509
|
+
record_type_id = val
|
|
510
|
+
end
|
|
511
|
+
else
|
|
512
|
+
opts.banner = subcommand_usage("[name]")
|
|
513
|
+
end
|
|
514
|
+
# if defined?(add_#{rest_key}_option_types)
|
|
515
|
+
# build_option_type_options(opts, options, add_#{rest_key}_option_types)
|
|
516
|
+
# end
|
|
517
|
+
build_standard_add_options(opts, options)
|
|
518
|
+
end
|
|
519
|
+
optparse.parse!(args)
|
|
520
|
+
# todo: make supporting args[0] optional and more flexible
|
|
521
|
+
# for now args[0] is assumed to be the 'name'
|
|
522
|
+
record_name = nil
|
|
523
|
+
if args[0] # && rest_has_name
|
|
524
|
+
record_name = args[0]
|
|
525
|
+
end
|
|
526
|
+
verify_args!(args:args, optparse:optparse, min:0, max: 1)
|
|
527
|
+
# todo: maybe need a flag to make this required, it could be an option type too, so
|
|
528
|
+
if rest_has_type
|
|
529
|
+
if record_type_id.nil?
|
|
530
|
+
raise_command_error "#{rest_type_label} is required.\n#{optparse}"
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
connect(options)
|
|
534
|
+
if rest_has_type
|
|
535
|
+
record_type = rest_type_find_by_name_or_id(record_type_id)
|
|
536
|
+
if record_type.nil?
|
|
537
|
+
raise_command_error "#{rest_type_label} not found for '#{record_type_id}'.\n#{optparse}"
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
passed_options = parse_passed_options(options)
|
|
541
|
+
payload = {}
|
|
542
|
+
if options[:payload]
|
|
543
|
+
payload = options[:payload]
|
|
544
|
+
payload.deep_merge!({rest_object_key => passed_options})
|
|
545
|
+
else
|
|
546
|
+
record_payload = {}
|
|
547
|
+
if record_name
|
|
548
|
+
record_payload['name'] = record_name
|
|
549
|
+
options[:options]['name'] = record_name # injected for prompt
|
|
550
|
+
end
|
|
551
|
+
if rest_has_type && record_type
|
|
552
|
+
# record_payload['type'] = {'code' => record_type['code']}
|
|
553
|
+
record_payload['type'] = record_type['code']
|
|
554
|
+
options[:options]['type'] = record_type['code'] # injected for prompt
|
|
555
|
+
end
|
|
556
|
+
record_payload.deep_merge!(passed_options)
|
|
557
|
+
# options by type
|
|
558
|
+
my_option_types = record_type ? record_type['optionTypes'] : nil
|
|
559
|
+
if my_option_types && !my_option_types.empty?
|
|
560
|
+
# remove redundant fieldContext
|
|
561
|
+
my_option_types.each do |option_type|
|
|
562
|
+
if option_type['fieldContext'] == rest_object_key
|
|
563
|
+
option_type['fieldContext'] = nil
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, options[:params])
|
|
567
|
+
v_prompt.deep_compact!
|
|
568
|
+
v_prompt.booleanize! # 'on' => true
|
|
569
|
+
record_payload.deep_merge!(v_prompt)
|
|
570
|
+
end
|
|
571
|
+
payload[rest_object_key] = record_payload
|
|
572
|
+
end
|
|
573
|
+
rest_interface.setopts(options)
|
|
574
|
+
if options[:dry_run]
|
|
575
|
+
print_dry_run rest_interface.dry.create(payload)
|
|
576
|
+
return
|
|
577
|
+
end
|
|
578
|
+
json_response = rest_interface.create(payload)
|
|
579
|
+
render_response(json_response, options, rest_object_key) do
|
|
580
|
+
record = json_response[rest_object_key]
|
|
581
|
+
print_green_success "Added #{rest_label.downcase} #{record['name'] || record['id']}"
|
|
582
|
+
return _get(record["id"], {}, options)
|
|
583
|
+
end
|
|
584
|
+
return 0, nil
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
def update(args)
|
|
588
|
+
id = args[0]
|
|
589
|
+
options = {}
|
|
590
|
+
params = {}
|
|
591
|
+
account_name = nil
|
|
592
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
593
|
+
opts.banner = subcommand_usage("[#{rest_arg}] [options]")
|
|
594
|
+
build_standard_update_options(opts, options)
|
|
595
|
+
end
|
|
596
|
+
optparse.parse!(args)
|
|
597
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
598
|
+
connect(options)
|
|
599
|
+
record = rest_find_by_name_or_id(id)
|
|
600
|
+
passed_options = parse_passed_options(options)
|
|
601
|
+
payload = nil
|
|
602
|
+
if options[:payload]
|
|
603
|
+
payload = options[:payload]
|
|
604
|
+
payload.deep_merge!({rest_object_key => passed_options}) unless passed_options.empty?
|
|
605
|
+
else
|
|
606
|
+
record_payload = passed_options
|
|
607
|
+
if record_payload.empty?
|
|
608
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
|
609
|
+
end
|
|
610
|
+
payload[rest_object_key] = record_payload
|
|
611
|
+
end
|
|
612
|
+
rest_interface.setopts(options)
|
|
613
|
+
if options[:dry_run]
|
|
614
|
+
print_dry_run rest_interface.dry.update(record['id'], payload)
|
|
615
|
+
return
|
|
616
|
+
end
|
|
617
|
+
json_response = rest_interface.update(record['id'], payload)
|
|
618
|
+
render_response(json_response, options, rest_object_key) do
|
|
619
|
+
print_green_success "Updated #{rest_label.downcase} #{record['name'] || record['id']}"
|
|
620
|
+
_get(record["id"], {}, options)
|
|
621
|
+
end
|
|
622
|
+
return 0, nil
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
def remove(args)
|
|
626
|
+
id = args[0]
|
|
627
|
+
params = {}
|
|
628
|
+
options = {}
|
|
629
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
630
|
+
opts.banner = subcommand_usage("[#{rest_arg}]")
|
|
631
|
+
build_standard_remove_options(opts, options)
|
|
632
|
+
end
|
|
633
|
+
optparse.parse!(args)
|
|
634
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
635
|
+
connect(options)
|
|
636
|
+
params.merge!(parse_query_options(options))
|
|
637
|
+
record = rest_find_by_name_or_id(id)
|
|
638
|
+
if record.nil?
|
|
639
|
+
return 1, "#{rest_name} not found for '#{id}'"
|
|
640
|
+
end
|
|
641
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the #{rest_label.downcase} #{record['name'] || record['id']}?")
|
|
642
|
+
return 9, "aborted"
|
|
643
|
+
end
|
|
644
|
+
rest_interface.setopts(options)
|
|
645
|
+
if options[:dry_run]
|
|
646
|
+
print_dry_run rest_interface.dry.destroy(record['id'])
|
|
647
|
+
return 0, nil
|
|
648
|
+
end
|
|
649
|
+
json_response = rest_interface.destroy(record['id'], params)
|
|
650
|
+
render_response(json_response, options) do
|
|
651
|
+
print_green_success "Removed #{rest_label.downcase} #{record['name'] || record['id']}"
|
|
652
|
+
end
|
|
653
|
+
return 0, nil
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
end
|
|
657
|
+
|