morpheus-cli 5.3.1 → 5.3.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/account_groups_interface.rb +0 -6
- data/lib/morpheus/api/accounts_interface.rb +1 -7
- data/lib/morpheus/api/api_client.rb +108 -106
- 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/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/integrations_interface.rb +30 -0
- 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_balancers_interface.rb +0 -6
- 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 +0 -6
- data/lib/morpheus/api/network_security_servers_interface.rb +6 -9
- data/lib/morpheus/api/network_services_interface.rb +0 -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 +0 -6
- 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/reports_interface.rb +0 -6
- data/lib/morpheus/api/roles_interface.rb +0 -6
- 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 +0 -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_sources_interface.rb +0 -6
- data/lib/morpheus/api/users_interface.rb +0 -6
- 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/access_token_command.rb +1 -1
- data/lib/morpheus/cli/account_groups_command.rb +4 -4
- data/lib/morpheus/cli/apps.rb +9 -9
- 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/change_password_command.rb +4 -4
- data/lib/morpheus/cli/cli_command.rb +2 -1
- data/lib/morpheus/cli/clouds.rb +2 -2
- data/lib/morpheus/cli/clusters.rb +2 -2
- 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 +8 -8
- 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 +54 -27
- data/lib/morpheus/cli/integrations_command.rb +567 -1
- data/lib/morpheus/cli/invoices_command.rb +75 -67
- data/lib/morpheus/cli/key_pairs.rb +2 -2
- data/lib/morpheus/cli/library_container_scripts_command.rb +1 -1
- data/lib/morpheus/cli/library_container_templates_command.rb +1 -1
- data/lib/morpheus/cli/library_container_types_command.rb +6 -6
- data/lib/morpheus/cli/library_instance_types_command.rb +4 -4
- data/lib/morpheus/cli/library_layouts_command.rb +5 -5
- data/lib/morpheus/cli/library_option_lists_command.rb +4 -4
- data/lib/morpheus/cli/library_option_types_command.rb +4 -4
- data/lib/morpheus/cli/library_upgrades_command.rb +6 -6
- data/lib/morpheus/cli/license.rb +2 -2
- data/lib/morpheus/cli/load_balancers.rb +1 -1
- data/lib/morpheus/cli/login.rb +3 -1
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +1 -1
- data/lib/morpheus/cli/option_types.rb +5 -1
- 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 +1 -1
- data/lib/morpheus/cli/roles.rb +9 -9
- data/lib/morpheus/cli/security_group_rules.rb +1 -1
- data/lib/morpheus/cli/setup.rb +0 -1
- data/lib/morpheus/cli/tenants_command.rb +3 -3
- data/lib/morpheus/cli/user_groups_command.rb +3 -3
- data/lib/morpheus/cli/user_sources_command.rb +3 -3
- data/lib/morpheus/cli/users.rb +3 -3
- 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
- metadata +2 -2
@@ -48,9 +48,9 @@ class Morpheus::Cli::ArchivesCommand
|
|
48
48
|
|
49
49
|
def connect(opts)
|
50
50
|
@api_client = establish_remote_appliance_connection(opts)
|
51
|
-
@archive_buckets_interface =
|
52
|
-
@archive_files_interface =
|
53
|
-
@options_interface =
|
51
|
+
@archive_buckets_interface = @api_client.archive_buckets
|
52
|
+
@archive_files_interface = @api_client.archive_files
|
53
|
+
@options_interface = @api_client.options
|
54
54
|
# @active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
|
55
55
|
end
|
56
56
|
|
@@ -979,10 +979,10 @@ class Morpheus::Cli::ArchivesCommand
|
|
979
979
|
|
980
980
|
|
981
981
|
print_h2 "Download URLs"
|
982
|
-
private_download_url = "#{@appliance_url}/api/archives/download/#{
|
982
|
+
private_download_url = "#{@appliance_url}/api/archives/download/#{CGI::escape(bucket_id)}" + "/#{CGI::escape(archive_file['filePath'])}".squeeze('/')
|
983
983
|
public_download_url = nil
|
984
984
|
if archive_file['archiveBucket'] && archive_file['archiveBucket']['isPublic']
|
985
|
-
public_download_url = "#{@appliance_url}/public-archives/download/#{
|
985
|
+
public_download_url = "#{@appliance_url}/public-archives/download/#{CGI::escape(bucket_id)}" + "/#{CGI::escape(archive_file['filePath'])}".squeeze('/')
|
986
986
|
end
|
987
987
|
print cyan
|
988
988
|
puts "Private URL: #{private_download_url}"
|
@@ -29,11 +29,11 @@ class Morpheus::Cli::BlueprintsCommand
|
|
29
29
|
|
30
30
|
def connect(opts)
|
31
31
|
@api_client = establish_remote_appliance_connection(opts)
|
32
|
-
@blueprints_interface =
|
33
|
-
@groups_interface =
|
34
|
-
@instances_interface =
|
35
|
-
@instance_types_interface =
|
36
|
-
@options_interface =
|
32
|
+
@blueprints_interface = @api_client.blueprints
|
33
|
+
@groups_interface = @api_client.groups
|
34
|
+
@instances_interface = @api_client.instances
|
35
|
+
@instance_types_interface = @api_client.instance_types
|
36
|
+
@options_interface = @api_client.options
|
37
37
|
@active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
|
38
38
|
@clouds_interface = @api_client.clouds
|
39
39
|
@users_interface = @api_client.users
|
@@ -24,7 +24,7 @@ class Morpheus::Cli::BootScriptsCommand
|
|
24
24
|
|
25
25
|
def connect(opts)
|
26
26
|
@api_client = establish_remote_appliance_connection(opts)
|
27
|
-
@image_builder_interface =
|
27
|
+
@image_builder_interface = @api_client.image_builder
|
28
28
|
@boot_scripts_interface = @image_builder_interface.boot_scripts
|
29
29
|
end
|
30
30
|
|
@@ -19,10 +19,10 @@ class Morpheus::Cli::ChangePasswordCommand
|
|
19
19
|
|
20
20
|
def connect(opts)
|
21
21
|
@api_client = establish_remote_appliance_connection(opts)
|
22
|
-
@whoami_interface =
|
23
|
-
@users_interface =
|
24
|
-
@accounts_interface =
|
25
|
-
@roles_interface =
|
22
|
+
@whoami_interface = @api_client.whoami
|
23
|
+
@users_interface = @api_client.users
|
24
|
+
@accounts_interface = @api_client.accounts
|
25
|
+
@roles_interface = @api_client.roles
|
26
26
|
end
|
27
27
|
|
28
28
|
def handle(args)
|
@@ -1124,6 +1124,7 @@ module Morpheus
|
|
1124
1124
|
if options[:insecure] || appliance[:insecure] || Morpheus::Cli::Shell.insecure
|
1125
1125
|
allow_insecure = true
|
1126
1126
|
end
|
1127
|
+
@verify_ssl = !allow_insecure
|
1127
1128
|
# Morpheus::RestClient.enable_ssl_verification = allow_insecure != true
|
1128
1129
|
if allow_insecure && Morpheus::RestClient.ssl_verification_enabled?
|
1129
1130
|
Morpheus::RestClient.enable_ssl_verification = false
|
@@ -1189,7 +1190,7 @@ module Morpheus
|
|
1189
1190
|
end
|
1190
1191
|
|
1191
1192
|
# ok, connect to the appliance.. actually this just instantiates an ApiClient
|
1192
|
-
api_client = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url)
|
1193
|
+
api_client = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url, @verify_ssl)
|
1193
1194
|
@api_client = api_client # meh, just return w/o setting instance attrs
|
1194
1195
|
return api_client
|
1195
1196
|
end
|
data/lib/morpheus/cli/clouds.rb
CHANGED
@@ -24,8 +24,8 @@ class Morpheus::Cli::Clouds
|
|
24
24
|
|
25
25
|
def connect(opts)
|
26
26
|
@api_client = establish_remote_appliance_connection(opts)
|
27
|
-
@clouds_interface =
|
28
|
-
@groups_interface =
|
27
|
+
@clouds_interface = @api_client.clouds
|
28
|
+
@groups_interface = @api_client.groups
|
29
29
|
@active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
|
30
30
|
# preload stuff
|
31
31
|
get_available_cloud_types()
|
@@ -45,8 +45,8 @@ class Morpheus::Cli::Clusters
|
|
45
45
|
@provision_types_interface = @api_client.provision_types
|
46
46
|
@service_plans_interface = @api_client.service_plans
|
47
47
|
@user_groups_interface = @api_client.user_groups
|
48
|
-
@accounts_interface =
|
49
|
-
@logs_interface =
|
48
|
+
@accounts_interface = @api_client.accounts
|
49
|
+
@logs_interface = @api_client.logs
|
50
50
|
#@active_security_group = ::Morpheus::Cli::SecurityGroups.load_security_group_file
|
51
51
|
end
|
52
52
|
|
@@ -56,8 +56,7 @@ module Morpheus
|
|
56
56
|
# OR whoami should return other wallet info like access token or maybe just the expiration date
|
57
57
|
# for now, it just stores the access token without other wallet info
|
58
58
|
begin
|
59
|
-
|
60
|
-
whoami_interface = Morpheus::WhoamiInterface.new({url: @appliance_url, access_token: options[:remote_token]})
|
59
|
+
whoami_interface = Morpheus::WhoamiInterface.new({url: @appliance_url, access_token: options[:remote_token], verify_ssl: !options[:insecure]})
|
61
60
|
whoami_interface.setopts(options)
|
62
61
|
if options[:dry_run]
|
63
62
|
print_dry_run whoami_interface.dry.get()
|
@@ -104,13 +103,7 @@ module Morpheus
|
|
104
103
|
end
|
105
104
|
if wallet.nil?
|
106
105
|
unless options[:quiet] || options[:no_prompt]
|
107
|
-
#
|
108
|
-
if options[:test_only]
|
109
|
-
print "Test Morpheus Credentials for #{display_appliance(@appliance_name, @appliance_url)}", "\n", reset
|
110
|
-
else
|
111
|
-
print "Enter Morpheus Credentials for #{display_appliance(@appliance_name, @appliance_url)}", "\n", reset
|
112
|
-
end
|
113
|
-
# end
|
106
|
+
print "Enter Morpheus Credentials for #{display_appliance(@appliance_name, @appliance_url)}", "\n", reset
|
114
107
|
if options[:client_id].empty?
|
115
108
|
# print "Client ID: #{required_blue_prompt} #{options[:client_id]}", "\n", reset
|
116
109
|
else
|
@@ -138,7 +131,7 @@ module Morpheus
|
|
138
131
|
return nil
|
139
132
|
end
|
140
133
|
begin
|
141
|
-
auth_interface = Morpheus::AuthInterface.new({url:@appliance_url, client_id: options[:client_id]})
|
134
|
+
auth_interface = Morpheus::AuthInterface.new({url:@appliance_url, client_id: options[:client_id], verify_ssl: !options[:insecure]})
|
142
135
|
auth_interface.setopts(options)
|
143
136
|
if options[:dry_run]
|
144
137
|
print_dry_run auth_interface.dry.login(username, password)
|
@@ -276,7 +269,7 @@ module Morpheus
|
|
276
269
|
username = wallet['username']
|
277
270
|
|
278
271
|
begin
|
279
|
-
auth_interface = Morpheus::AuthInterface.new({url:@appliance_url})
|
272
|
+
auth_interface = Morpheus::AuthInterface.new({url:@appliance_url, client_id: options[:client_id], verify_ssl: !options[:insecure]})
|
280
273
|
auth_interface.setopts(options)
|
281
274
|
if options[:dry_run]
|
282
275
|
print_dry_run auth_interface.dry.use_refresh_token(refresh_token_value)
|
@@ -16,7 +16,7 @@ class Morpheus::Cli::EnvironmentsCommand
|
|
16
16
|
|
17
17
|
def connect(opts)
|
18
18
|
@api_client = establish_remote_appliance_connection(opts)
|
19
|
-
@environments_interface =
|
19
|
+
@environments_interface = @api_client.environments
|
20
20
|
end
|
21
21
|
|
22
22
|
def handle(args)
|
@@ -13,9 +13,9 @@ class Morpheus::Cli::ExecuteSchedulesCommand
|
|
13
13
|
|
14
14
|
def connect(opts)
|
15
15
|
@api_client = establish_remote_appliance_connection(opts)
|
16
|
-
@execute_schedules_interface =
|
17
|
-
@instances_interface =
|
18
|
-
@servers_interface =
|
16
|
+
@execute_schedules_interface = @api_client.execute_schedules
|
17
|
+
@instances_interface = @api_client.instances
|
18
|
+
@servers_interface = @api_client.servers
|
19
19
|
end
|
20
20
|
|
21
21
|
def handle(args)
|
data/lib/morpheus/cli/hosts.rb
CHANGED
@@ -32,14 +32,14 @@ class Morpheus::Cli::Hosts
|
|
32
32
|
@api_client = establish_remote_appliance_connection(opts)
|
33
33
|
@accounts_interface = @api_client.accounts
|
34
34
|
@users_interface = @api_client.users
|
35
|
-
@clouds_interface =
|
36
|
-
@options_interface =
|
37
|
-
@tasks_interface =
|
38
|
-
@task_sets_interface =
|
39
|
-
@servers_interface =
|
40
|
-
@server_types_interface =
|
41
|
-
@logs_interface =
|
42
|
-
@accounts_interface =
|
35
|
+
@clouds_interface = @api_client.clouds
|
36
|
+
@options_interface = @api_client.options
|
37
|
+
@tasks_interface = @api_client.tasks
|
38
|
+
@task_sets_interface = @api_client.task_sets
|
39
|
+
@servers_interface = @api_client.servers
|
40
|
+
@server_types_interface = @api_client.server_types
|
41
|
+
@logs_interface = @api_client.logs
|
42
|
+
@accounts_interface = @api_client.accounts
|
43
43
|
@active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
|
44
44
|
@execution_request_interface = @api_client.execution_request
|
45
45
|
@clusters_interface = @api_client.clusters
|
@@ -30,15 +30,15 @@ class Morpheus::Cli::ImageBuilderCommand
|
|
30
30
|
|
31
31
|
def connect(opts)
|
32
32
|
@api_client = establish_remote_appliance_connection(opts)
|
33
|
-
@image_builder_interface =
|
33
|
+
@image_builder_interface = @api_client.image_builder
|
34
34
|
@image_builds_interface = @image_builder_interface.image_builds
|
35
35
|
@boot_scripts_interface = @image_builder_interface.boot_scripts
|
36
36
|
@preseed_scripts_interface = @image_builder_interface.preseed_scripts
|
37
|
-
@groups_interface =
|
38
|
-
@clouds_interface =
|
39
|
-
@instances_interface =
|
40
|
-
@instance_types_interface =
|
41
|
-
@options_interface =
|
37
|
+
@groups_interface = @api_client.groups
|
38
|
+
@clouds_interface = @api_client.clouds
|
39
|
+
@instances_interface = @api_client.instances
|
40
|
+
@instance_types_interface = @api_client.instance_types
|
41
|
+
@options_interface = @api_client.options
|
42
42
|
@active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
|
43
43
|
end
|
44
44
|
|
@@ -17,7 +17,7 @@ class Morpheus::Cli::InstanceTypes
|
|
17
17
|
|
18
18
|
def connect(opts)
|
19
19
|
@api_client = establish_remote_appliance_connection(opts)
|
20
|
-
@instance_types_interface =
|
20
|
+
@instance_types_interface = @api_client.instance_types
|
21
21
|
end
|
22
22
|
|
23
23
|
def handle(args)
|
@@ -130,6 +130,7 @@ class Morpheus::Cli::Instances
|
|
130
130
|
end
|
131
131
|
opts.on('-a', '--details', "Display all details: plan, stats, etc" ) do
|
132
132
|
options[:details] = true
|
133
|
+
params['details'] = true # get more data from server this way
|
133
134
|
end
|
134
135
|
build_standard_list_options(opts, options)
|
135
136
|
opts.footer = "List instances."
|
@@ -1201,7 +1202,15 @@ class Morpheus::Cli::Instances
|
|
1201
1202
|
options[:details] = true
|
1202
1203
|
options[:include_containers] = true
|
1203
1204
|
options[:include_scaling] = true
|
1205
|
+
options[:include_costs]
|
1204
1206
|
end
|
1207
|
+
opts.on(nil, '--details', "Alias for --all" ) do
|
1208
|
+
options[:details] = true
|
1209
|
+
options[:include_containers] = true
|
1210
|
+
options[:include_scaling] = true
|
1211
|
+
options[:include_costs]
|
1212
|
+
end
|
1213
|
+
opts.add_hidden_option('--details')
|
1205
1214
|
opts.on( nil, '--containers', "Display Instance Containers" ) do
|
1206
1215
|
options[:include_containers] = true
|
1207
1216
|
end
|
@@ -1216,9 +1225,6 @@ class Morpheus::Cli::Instances
|
|
1216
1225
|
opts.on( nil, '--scaling', "Display Instance Scaling Settings" ) do
|
1217
1226
|
options[:include_scaling] = true
|
1218
1227
|
end
|
1219
|
-
opts.on( nil, '--costs', "Display Cost and Price" ) do
|
1220
|
-
options[:include_costs] = true
|
1221
|
-
end
|
1222
1228
|
opts.on('--refresh [SECONDS]', String, "Refresh until status is running,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
|
1223
1229
|
options[:refresh_until_status] ||= "running,failed"
|
1224
1230
|
if !val.to_s.empty?
|
@@ -1250,22 +1256,29 @@ class Morpheus::Cli::Instances
|
|
1250
1256
|
end
|
1251
1257
|
end
|
1252
1258
|
|
1253
|
-
def _get(
|
1254
|
-
|
1259
|
+
def _get(id, options={})
|
1260
|
+
params = {}
|
1261
|
+
params.merge!(parse_query_options(options))
|
1262
|
+
# Use details=true to get more details from the appliance
|
1263
|
+
# if options[:details] || options[:include_containers] || options[:include_scaling]
|
1264
|
+
if options[:details] || options[:include_containers] || options[:include_scaling]
|
1265
|
+
params['details'] = true
|
1266
|
+
end
|
1267
|
+
instance = nil
|
1268
|
+
if id.to_s !~ /\A\d{1,}\Z/
|
1269
|
+
instance = find_instance_by_name_or_id(id)
|
1270
|
+
return 1, "Instance not found by name #{id}" if instance.nil?
|
1271
|
+
id = instance['id']
|
1272
|
+
end
|
1255
1273
|
if options[:dry_run]
|
1256
|
-
@instances_interface.
|
1257
|
-
|
1258
|
-
print_dry_run @instances_interface.dry.get(arg.to_i)
|
1259
|
-
else
|
1260
|
-
print_dry_run @instances_interface.dry.get({name:arg})
|
1261
|
-
end
|
1262
|
-
return
|
1274
|
+
print_dry_run @instances_interface.dry.get(id, params)
|
1275
|
+
return 0, nil
|
1263
1276
|
end
|
1264
|
-
instance = find_instance_by_name_or_id(arg =~ /\A\d{1,}\Z/ ? arg.to_i : arg)
|
1265
1277
|
@instances_interface.setopts(options)
|
1266
|
-
json_response = @instances_interface.get(
|
1278
|
+
json_response = @instances_interface.get(id, params)
|
1267
1279
|
render_response(json_response, options, "instance") do
|
1268
1280
|
instance = json_response['instance']
|
1281
|
+
pricing = instance['instancePrice']
|
1269
1282
|
stats = instance['stats'] || json_response['stats'] || {}
|
1270
1283
|
# load_balancers = json_response['loadBalancers'] || {}
|
1271
1284
|
# metadata tags used to be returned as metadata and are now returned as tags
|
@@ -1283,7 +1296,12 @@ class Morpheus::Cli::Instances
|
|
1283
1296
|
# containers are fetched via separate api call
|
1284
1297
|
containers = nil
|
1285
1298
|
if options[:include_containers]
|
1286
|
-
|
1299
|
+
# todo: can use instance['containerDetails'] in api 5.2.7/5.3.2
|
1300
|
+
if instance['containerDetails']
|
1301
|
+
containers = instance['containerDetails']
|
1302
|
+
else
|
1303
|
+
containers = @instances_interface.containers(instance['id'])['containers']
|
1304
|
+
end
|
1287
1305
|
end
|
1288
1306
|
|
1289
1307
|
# threshold is fetched via separate api call too
|
@@ -1317,8 +1335,20 @@ class Morpheus::Cli::Instances
|
|
1317
1335
|
"Layout" => lambda {|it| it['layout'] ? it['layout']['name'] : '' },
|
1318
1336
|
"Version" => lambda {|it| it['instanceVersion'] },
|
1319
1337
|
"Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' },
|
1320
|
-
|
1321
|
-
|
1338
|
+
"Price" => lambda {|it|
|
1339
|
+
if pricing
|
1340
|
+
pricing['price'] ? format_money(pricing['price'], (pricing['currency'] || 'USD')).to_s + ' per ' + pricing['unit'].to_s : ''
|
1341
|
+
elsif it['hourlyPrice']
|
1342
|
+
format_money(it['hourlyPrice'], (it['currency'] || 'USD')).to_s + ' per hour'
|
1343
|
+
end
|
1344
|
+
},
|
1345
|
+
"Cost" => lambda {|it|
|
1346
|
+
if pricing
|
1347
|
+
pricing['cost'] ? format_money(pricing['cost'], (pricing['currency'] || 'USD')).to_s + ' per ' + pricing['unit'].to_s : ''
|
1348
|
+
elsif it['hourlyCost']
|
1349
|
+
format_money(it['hourlyCost'], (it['currency'] || 'USD')).to_s + ' per hour'
|
1350
|
+
end
|
1351
|
+
},
|
1322
1352
|
"Environment" => 'instanceContext',
|
1323
1353
|
"Labels" => lambda {|it| labels ? labels.join(',') : '' },
|
1324
1354
|
"Tags" => lambda {|it| tags ? tags.collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' },
|
@@ -1330,6 +1360,7 @@ class Morpheus::Cli::Instances
|
|
1330
1360
|
end
|
1331
1361
|
},
|
1332
1362
|
#"Tenant" => lambda {|it| it['tenant'] ? it['tenant']['name'] : '' },
|
1363
|
+
"Apps" => lambda {|it| anded_list(it['apps'] ? it['apps'].collect {|app| app['name'] } : [])},
|
1333
1364
|
"Date Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
1334
1365
|
# "Last Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
1335
1366
|
"Power Schedule" => lambda {|it| (it['powerSchedule'] && it['powerSchedule']['type']) ? it['powerSchedule']['type']['name'] : '' },
|
@@ -1343,12 +1374,17 @@ class Morpheus::Cli::Instances
|
|
1343
1374
|
}
|
1344
1375
|
description_cols.delete("Labels") if labels.nil? || labels.empty?
|
1345
1376
|
description_cols.delete("Tags") if tags.nil? || tags.empty?
|
1377
|
+
description_cols.delete("Apps") if instance['apps'].nil? || instance['apps'].empty?
|
1346
1378
|
description_cols.delete("Power Schedule") if instance['powerSchedule'].nil?
|
1347
1379
|
description_cols.delete("Expire Date") if instance['expireDate'].nil?
|
1348
1380
|
description_cols.delete("Shutdown Date") if instance['shutdownDate'].nil?
|
1349
1381
|
description_cols["Removal Date"] = lambda {|it| format_local_dt(it['removalDate'])} if instance['status'] == 'pendingRemoval'
|
1350
1382
|
description_cols.delete("Last Deployment") if instance['lastDeploy'].nil?
|
1351
1383
|
description_cols.delete("Locked") if instance['locked'] != true
|
1384
|
+
price_value = (pricing ? pricing['price'] : instance['hourlyPrice']).to_i
|
1385
|
+
cost_value = (pricing ? pricing['cost'] : instance['hourlyCost']).to_i
|
1386
|
+
description_cols.delete("Price") if price_value == 0
|
1387
|
+
description_cols.delete("Cost") if cost_value == 0 || cost_value == price_value
|
1352
1388
|
#description_cols.delete("Environment") if instance['instanceContext'].nil?
|
1353
1389
|
print_description_list(description_cols, instance)
|
1354
1390
|
|
@@ -1380,15 +1416,6 @@ class Morpheus::Cli::Instances
|
|
1380
1416
|
print_stats_usage(stats)
|
1381
1417
|
end
|
1382
1418
|
|
1383
|
-
if options[:include_costs]
|
1384
|
-
print_h2 "Instance Cost"
|
1385
|
-
cost_columns = {
|
1386
|
-
"Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
1387
|
-
"Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
|
1388
|
-
}
|
1389
|
-
print_description_list(cost_columns, instance)
|
1390
|
-
end
|
1391
|
-
|
1392
1419
|
print reset, "\n"
|
1393
1420
|
|
1394
1421
|
# if options[:include_lb]
|
@@ -1478,7 +1505,7 @@ class Morpheus::Cli::Instances
|
|
1478
1505
|
print cyan, "Refreshing in #{options[:refresh_interval] > 1 ? options[:refresh_interval].to_i : options[:refresh_interval]} seconds"
|
1479
1506
|
sleep_with_dots(options[:refresh_interval])
|
1480
1507
|
print "\n"
|
1481
|
-
_get(
|
1508
|
+
_get(instance['id'], options)
|
1482
1509
|
end
|
1483
1510
|
end
|
1484
1511
|
end
|
@@ -2,12 +2,12 @@ require 'morpheus/cli/cli_command'
|
|
2
2
|
|
3
3
|
class Morpheus::Cli::IntegrationsCommand
|
4
4
|
include Morpheus::Cli::CliCommand
|
5
|
-
include Morpheus::Cli::AccountsHelper
|
6
5
|
|
7
6
|
set_command_name :'integrations'
|
8
7
|
set_command_description "Integrations: View and manage integrations"
|
9
8
|
|
10
9
|
register_subcommands :list, :get, :add, :update, :remove, :refresh
|
10
|
+
register_subcommands :list_objects, :get_object, :add_object, :remove_object
|
11
11
|
register_subcommands :list_types, :get_type
|
12
12
|
|
13
13
|
def connect(opts)
|
@@ -78,6 +78,9 @@ class Morpheus::Cli::IntegrationsCommand
|
|
78
78
|
options = {}
|
79
79
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
80
80
|
opts.banner = subcommand_usage("[integration]")
|
81
|
+
opts.on('--objects', 'Display exposed objects for the integration.') do
|
82
|
+
options[:show_objects] = true
|
83
|
+
end
|
81
84
|
build_standard_get_options(opts, options)
|
82
85
|
opts.footer = <<-EOT
|
83
86
|
Get details about a specific integration.
|
@@ -101,6 +104,9 @@ EOT
|
|
101
104
|
return 1, "integration not found for #{id}" if integration.nil?
|
102
105
|
id = integration['id']
|
103
106
|
end
|
107
|
+
if options[:show_objects]
|
108
|
+
params['objects'] = true
|
109
|
+
end
|
104
110
|
@integrations_interface.setopts(options)
|
105
111
|
if options[:dry_run]
|
106
112
|
print_dry_run @integrations_interface.dry.get(id, params)
|
@@ -137,6 +143,74 @@ EOT
|
|
137
143
|
show_columns.delete("Service Key") if integration['serviceKey'].nil?
|
138
144
|
show_columns.delete("Auth Key") if integration['authKey'].nil?
|
139
145
|
print_description_list(show_columns, integration, options)
|
146
|
+
|
147
|
+
if options[:show_objects]
|
148
|
+
# they are loaded above with ?objects=true
|
149
|
+
integration_objects = integration['objects']
|
150
|
+
if integration_objects.nil?
|
151
|
+
objects_json_response = @integrations_interface.list_objects(integration['id'], {})
|
152
|
+
integration_objects = objects_json_response[integration_object_list_key]
|
153
|
+
end
|
154
|
+
cloud_objects = integration_objects.select {|it| it['refType'] == "ComputeZone" }
|
155
|
+
library_objects = integration_objects.select {|it| it['refType'] == "InstanceTypeLayout" || it['refType'] == "InstanceType" }
|
156
|
+
blueprint_objects = integration_objects.select {|it| it['refType'] == "AppTemplate" }
|
157
|
+
catalog_objects = integration_objects.select {|it| it['refType'] == "CatalogItemType" }
|
158
|
+
if integration_objects.empty?
|
159
|
+
print reset,"\n"
|
160
|
+
print cyan,"No objects found.",reset,"\n"
|
161
|
+
else
|
162
|
+
# Exposed Clouds
|
163
|
+
if !cloud_objects.empty?
|
164
|
+
print_h2 "Exposed Clouds", [], options
|
165
|
+
list_columns = {
|
166
|
+
# "ID" => 'id',
|
167
|
+
"Name" => 'name',
|
168
|
+
# "Category" => 'category',
|
169
|
+
# "Ref Type" => 'refType',
|
170
|
+
# "Cloud ID" => 'refId',
|
171
|
+
"Group" => lambda {|it| it['group']['name'] rescue nil },
|
172
|
+
}.upcase_keys!
|
173
|
+
print as_pretty_table(cloud_objects, list_columns, options)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Exposed Libraries
|
177
|
+
if !library_objects.empty?
|
178
|
+
# print_h2 "Exposed Libraries", [], options
|
179
|
+
print_h2 "Exposed Layouts", [], options
|
180
|
+
list_columns = {
|
181
|
+
# "ID" => 'id',
|
182
|
+
"Name" => 'name',
|
183
|
+
"Version" => lambda {|it| it['layout']['instanceVersion'] rescue nil },
|
184
|
+
"Instance Type" => lambda {|it| it['layout']['instanceType']['name'] rescue nil },
|
185
|
+
"Provision Type" => lambda {|it| it['layout']['provisionType']['name'] rescue nil },
|
186
|
+
}.upcase_keys!
|
187
|
+
print as_pretty_table(library_objects, list_columns, options)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Exposed Blueprints
|
191
|
+
if !blueprint_objects.empty?
|
192
|
+
print_h2 "Exposed Blueprints", [], options
|
193
|
+
list_columns = {
|
194
|
+
# "ID" => 'id',
|
195
|
+
"Name" => 'name',
|
196
|
+
# "Type" => lambda {|it| it['blueprint']['type'] rescue nil },
|
197
|
+
"Blueprint" => lambda {|it| it['blueprint']['name'] rescue nil },
|
198
|
+
"Group" => lambda {|it| it['group']['name'] rescue nil },
|
199
|
+
}.upcase_keys!
|
200
|
+
print as_pretty_table(blueprint_objects, list_columns, options)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Exposed Catalog Items
|
204
|
+
if !catalog_objects.empty?
|
205
|
+
print_h2 "Exposed Catalog Items", [], options
|
206
|
+
list_columns = {
|
207
|
+
# "ID" => 'id',
|
208
|
+
"Name" => 'name',
|
209
|
+
}.upcase_keys!
|
210
|
+
print as_pretty_table(catalog_objects, list_columns, options)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
140
214
|
print reset,"\n"
|
141
215
|
end
|
142
216
|
return 0, nil
|
@@ -459,6 +533,409 @@ EOT
|
|
459
533
|
return 0, nil
|
460
534
|
end
|
461
535
|
|
536
|
+
## Integration Objects
|
537
|
+
|
538
|
+
def list_objects(args)
|
539
|
+
options = {}
|
540
|
+
params = {}
|
541
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
542
|
+
opts.banner = subcommand_usage("[integration] [search]")
|
543
|
+
opts.on('-t', '--type CODE', "Filter by types: cloud, layout, blueprint, catalog") do |val|
|
544
|
+
params['type'] = [params['type'], val].compact.flatten.collect {|it| it.to_s.strip.split(",") }.flatten.collect {|it| it.to_s.strip }
|
545
|
+
end
|
546
|
+
build_standard_list_options(opts, options)
|
547
|
+
opts.footer = <<-EOT
|
548
|
+
List integration objects.
|
549
|
+
[integration] is required. This is the name or id of an integration.
|
550
|
+
EOT
|
551
|
+
end
|
552
|
+
optparse.parse!(args)
|
553
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
554
|
+
connect(options)
|
555
|
+
|
556
|
+
integration = find_integration_by_name_or_id(args[0])
|
557
|
+
return 1, "integration not found for #{args[0]}" if integration.nil?
|
558
|
+
|
559
|
+
if args.count > 1
|
560
|
+
options[:phrase] = args[1..-1].join(" ")
|
561
|
+
end
|
562
|
+
params.merge!(parse_list_options(options))
|
563
|
+
@integrations_interface.setopts(options)
|
564
|
+
if options[:dry_run]
|
565
|
+
print_dry_run @integrations_interface.dry.list_objects(integration['id'], params)
|
566
|
+
return 0, nil
|
567
|
+
end
|
568
|
+
json_response = @integrations_interface.list_objects(integration['id'], params)
|
569
|
+
render_response(json_response, options, integration_list_key) do
|
570
|
+
integration_objects = json_response[integration_object_list_key]
|
571
|
+
print_h1 "Integration Objects [#{integration['name']}]", parse_list_subtitles(options), options
|
572
|
+
if integration_objects.empty?
|
573
|
+
print cyan,"No objects found.",reset,"\n"
|
574
|
+
else
|
575
|
+
list_columns = {
|
576
|
+
"ID" => 'id',
|
577
|
+
"Name" => 'name',
|
578
|
+
# "Category" => 'category',
|
579
|
+
# "Ref Type" => 'refType',
|
580
|
+
# "Ref ID" => 'refId',
|
581
|
+
# "Type" => lambda {|it| it['type'] },
|
582
|
+
"Type" => lambda {|it| it['type'].to_s.capitalize },
|
583
|
+
"Ref ID" => 'refId',
|
584
|
+
}.upcase_keys!
|
585
|
+
print as_pretty_table(integration_objects, list_columns, options)
|
586
|
+
print_results_pagination(json_response)
|
587
|
+
end
|
588
|
+
print reset,"\n"
|
589
|
+
end
|
590
|
+
return 0, nil
|
591
|
+
end
|
592
|
+
|
593
|
+
def get_object(args)
|
594
|
+
params = {}
|
595
|
+
options = {}
|
596
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
597
|
+
opts.banner = subcommand_usage("[integration] [object]")
|
598
|
+
opts.on( '-c', '--config', "Display config only, for blueprint objects" ) do
|
599
|
+
options[:show_config] = true
|
600
|
+
end
|
601
|
+
build_standard_get_options(opts, options)
|
602
|
+
opts.footer = <<-EOT
|
603
|
+
Get details about a specific integration object.
|
604
|
+
[integration] is required. This is the name or id of an integration.
|
605
|
+
[object] is required. This is the name or id of an integration object.
|
606
|
+
EOT
|
607
|
+
end
|
608
|
+
optparse.parse!(args)
|
609
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
610
|
+
connect(options)
|
611
|
+
optparse.parse!(args)
|
612
|
+
verify_args!(args:args, optparse:optparse, min:2)
|
613
|
+
connect(options)
|
614
|
+
integration = find_integration_by_name_or_id(args[0])
|
615
|
+
return 1, "integration not found for #{args[0]}" if integration.nil?
|
616
|
+
params.merge!(parse_query_options(options))
|
617
|
+
id_list = parse_id_list(args[1..-1])
|
618
|
+
return run_command_for_each_arg(id_list) do |arg|
|
619
|
+
_get_object(integration, arg, params, options)
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
def _get_object(integration, id, params, options)
|
624
|
+
integration_object = nil
|
625
|
+
if id.to_s !~ /\A\d{1,}\Z/
|
626
|
+
integration_object = find_integration_object_by_name_or_id(integration['id'], id)
|
627
|
+
return 1, "integration object not found for #{id}" if integration_object.nil?
|
628
|
+
id = integration_object['id']
|
629
|
+
end
|
630
|
+
@integrations_interface.setopts(options)
|
631
|
+
if options[:dry_run]
|
632
|
+
print_dry_run @integrations_interface.dry.get_object(integration['id'], id, params)
|
633
|
+
return
|
634
|
+
end
|
635
|
+
json_response = @integrations_interface.get_object(integration['id'], id, params)
|
636
|
+
integration_object = json_response[integration_object_object_key]
|
637
|
+
config = integration_object['config']
|
638
|
+
# export just the config as json (default) or yaml
|
639
|
+
if options[:show_config]
|
640
|
+
unless options[:json] || options[:yaml] || options[:csv]
|
641
|
+
options[:json] = :true
|
642
|
+
end
|
643
|
+
return render_with_format(config, options)
|
644
|
+
end
|
645
|
+
render_response(json_response, options, integration_object_object_key) do
|
646
|
+
print_h1 "Integration Object Details", [], options
|
647
|
+
print cyan
|
648
|
+
if integration_object['type'] == 'cloud'
|
649
|
+
show_columns = {
|
650
|
+
"Integration" => lambda {|it| integration['name'] },
|
651
|
+
"Object ID" => 'id',
|
652
|
+
"Name" => 'name',
|
653
|
+
"Type" => lambda {|it| it['type'].to_s.capitalize },
|
654
|
+
# "Cloud" => lambda {|it| it['cloud']['name'] rescue nil },
|
655
|
+
# "Ref Type" => 'refType',
|
656
|
+
"Ref ID" => 'refId',
|
657
|
+
# "Reference" => lambda {|it| ("#{it['refType']}: #{it['refId']}" rescue nil) },
|
658
|
+
"Group" => lambda {|it| it['group']['name'] rescue nil },
|
659
|
+
}
|
660
|
+
print_description_list(show_columns, integration_object, options)
|
661
|
+
print reset,"\n"
|
662
|
+
elsif integration_object['type'] == 'layout'
|
663
|
+
show_columns = {
|
664
|
+
"Integration" => lambda {|it| integration['name'] },
|
665
|
+
"Object ID" => 'id',
|
666
|
+
"Name" => 'name',
|
667
|
+
"Type" => lambda {|it| it['type'].to_s.capitalize },
|
668
|
+
# "Layout" => lambda {|it| it['layout']['name'] rescue nil },
|
669
|
+
# "Ref Type" => 'refType',
|
670
|
+
"Ref ID" => 'refId',
|
671
|
+
# "Reference" => lambda {|it| ("#{it['refType']}: #{it['refId']}" rescue nil) },
|
672
|
+
"Provision Type" => lambda {|it| it['layout']['provisionType']['name'] rescue nil },
|
673
|
+
"Instance Type" => lambda {|it| it['layout']['instanceType']['name'] rescue nil },
|
674
|
+
"Version" => lambda {|it| it['layout']['instanceVersion'] rescue nil },
|
675
|
+
}
|
676
|
+
print_description_list(show_columns, integration_object, options)
|
677
|
+
print reset,"\n"
|
678
|
+
elsif integration_object['type'] == 'blueprint'
|
679
|
+
show_columns = {
|
680
|
+
"Integration" => lambda {|it| integration['name'] },
|
681
|
+
"Object ID" => 'id',
|
682
|
+
"Name" => 'name',
|
683
|
+
"Type" => lambda {|it| it['type'].to_s.capitalize },
|
684
|
+
# "Ref Type" => 'refType',
|
685
|
+
"Ref ID" => 'refId',
|
686
|
+
# "Reference" => lambda {|it| ("#{it['refType']}: #{it['refId']}" rescue nil) },
|
687
|
+
# "Blueprint Type" => lambda {|it| it['blueprint']['type'] rescue nil },
|
688
|
+
"Blueprint" => lambda {|it| it['blueprint']['name'] rescue nil },
|
689
|
+
"Group" => lambda {|it| it['group']['name'] rescue nil },
|
690
|
+
"Default Cloud" => lambda {|it| it['defaultCloud']['name'] rescue nil },
|
691
|
+
"Environment" => lambda {|it| it['environment'] rescue nil },
|
692
|
+
}
|
693
|
+
print_description_list(show_columns, integration_object, options)
|
694
|
+
# print reset,"\n"
|
695
|
+
# print_h2 "App Spec"
|
696
|
+
print_h2 "Config"
|
697
|
+
if config
|
698
|
+
# config_string = integration_object['config'] || ""
|
699
|
+
config_string = config.is_a?(Hash) ? JSON.pretty_generate(config) : config.to_s
|
700
|
+
#print reset,config_string,"\n",reset
|
701
|
+
config_lines = config_string.split("\n")
|
702
|
+
config_line_count = config_lines.size
|
703
|
+
max_lines = 10
|
704
|
+
if config_lines.size > max_lines
|
705
|
+
config_string = config_lines.first(max_lines).join("\n")
|
706
|
+
config_string << "\n\n"
|
707
|
+
config_string << "#{dark}(#{(config_line_count - max_lines)} more lines were not shown, use -c to show the config)#{reset}"
|
708
|
+
#config_string << "\n"
|
709
|
+
end
|
710
|
+
# strip --- yaml header
|
711
|
+
if config_string[0..3] == "---\n"
|
712
|
+
config_string = config_string[4..-1]
|
713
|
+
end
|
714
|
+
print reset,config_string.chomp("\n"),"\n",reset
|
715
|
+
else
|
716
|
+
print reset,"(blank)","\n",reset
|
717
|
+
end
|
718
|
+
print reset,"\n"
|
719
|
+
elsif integration_object['type'] == 'catalog'
|
720
|
+
show_columns = {
|
721
|
+
"Integration" => lambda {|it| integration['name'] },
|
722
|
+
"Object ID" => 'id',
|
723
|
+
"Name" => 'name',
|
724
|
+
"Type" => lambda {|it| it['type'].to_s.capitalize },
|
725
|
+
"Catalog Item" => lambda {|it| it['catalogItemType']['name'] rescue nil },
|
726
|
+
# "Ref Type" => 'refType',
|
727
|
+
# "Ref ID" => 'refId',
|
728
|
+
# "Reference" => lambda {|it| ("#{it['refType']}: #{it['refId']}" rescue nil) },
|
729
|
+
}
|
730
|
+
print_description_list(show_columns, integration_object, options)
|
731
|
+
print reset,"\n"
|
732
|
+
else
|
733
|
+
# Unknown type?
|
734
|
+
show_columns = {
|
735
|
+
"Integration" => lambda {|it| integration['name'] },
|
736
|
+
"Object ID" => 'id',
|
737
|
+
"Name" => 'name',
|
738
|
+
"Type" => lambda {|it| it['type'].to_s.capitalize },
|
739
|
+
"Ref Type" => 'refType',
|
740
|
+
"Ref ID" => 'refId',
|
741
|
+
}
|
742
|
+
print_description_list(show_columns, integration_object, options)
|
743
|
+
print reset,"\n"
|
744
|
+
end
|
745
|
+
end
|
746
|
+
return 0, nil
|
747
|
+
end
|
748
|
+
|
749
|
+
def add_object(args)
|
750
|
+
options = {}
|
751
|
+
params = {}
|
752
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
753
|
+
opts.banner = subcommand_usage("[integration] [name] -t CODE [options]")
|
754
|
+
# opts.on('-t', '--type CODE', "Integration ObjectType code, see `#{command_name} list-types` for available type codes") do |val|
|
755
|
+
# options[:options]['type'] = val
|
756
|
+
# end
|
757
|
+
build_option_type_options(opts, options, add_integration_object_option_types)
|
758
|
+
opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
|
759
|
+
options[:config_file] = val.to_s
|
760
|
+
file_content = nil
|
761
|
+
full_filename = File.expand_path(options[:config_file])
|
762
|
+
if File.exists?(full_filename)
|
763
|
+
file_content = File.read(full_filename)
|
764
|
+
else
|
765
|
+
print_red_alert "File not found: #{full_filename}"
|
766
|
+
return 1
|
767
|
+
end
|
768
|
+
parse_result = parse_json_or_yaml(file_content)
|
769
|
+
config_map = parse_result[:data]
|
770
|
+
if config_map.nil?
|
771
|
+
# todo: bubble up JSON.parse error message
|
772
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
773
|
+
#raise_command_error "Failed to parse config as valid YAML or JSON."
|
774
|
+
else
|
775
|
+
params['config'] = config_map
|
776
|
+
options[:options]['config'] = params['config'] # or file_content
|
777
|
+
end
|
778
|
+
end
|
779
|
+
# build_option_type_options(opts, options, add_integration_object_advanced_option_types)
|
780
|
+
build_standard_add_options(opts, options)
|
781
|
+
opts.footer = <<-EOT
|
782
|
+
Create a new integration object.
|
783
|
+
[integration] is required. This is the name or id of an integration.
|
784
|
+
[name] is required. This is the name of the new integration
|
785
|
+
Configuration options vary by integration type.
|
786
|
+
EOT
|
787
|
+
end
|
788
|
+
optparse.parse!(args)
|
789
|
+
verify_args!(args:args, optparse:optparse, min:1, max:2)
|
790
|
+
options[:options]['name'] = args[1] if args[1]
|
791
|
+
connect(options)
|
792
|
+
integration = find_integration_by_name_or_id(args[0])
|
793
|
+
return 1, "integration not found for #{args[0]}" if integration.nil?
|
794
|
+
payload = {}
|
795
|
+
if options[:payload]
|
796
|
+
payload = options[:payload]
|
797
|
+
payload.deep_merge!({integration_object_object_key => parse_passed_options(options)})
|
798
|
+
else
|
799
|
+
payload.deep_merge!({integration_object_object_key => parse_passed_options(options)})
|
800
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(add_integration_object_option_types(), options[:options], @api_client, options[:params])
|
801
|
+
v_prompt.deep_compact!
|
802
|
+
params.deep_merge!(v_prompt)
|
803
|
+
advanced_config = Morpheus::Cli::OptionTypes.no_prompt(add_integration_object_advanced_option_types, options[:options], @api_client, options[:params])
|
804
|
+
advanced_config.deep_compact!
|
805
|
+
params.deep_merge!(advanced_config)
|
806
|
+
params.booleanize!
|
807
|
+
|
808
|
+
# convert config string to a map
|
809
|
+
# config = params['config']
|
810
|
+
# if config && config.is_a?(String)
|
811
|
+
# parse_result = parse_json_or_yaml(config)
|
812
|
+
# config_map = parse_result[:data]
|
813
|
+
# if config_map.nil?
|
814
|
+
# # todo: bubble up JSON.parse error message
|
815
|
+
# raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
816
|
+
# #raise_command_error "Failed to parse config as valid YAML or JSON."
|
817
|
+
# else
|
818
|
+
# params['config'] = config_map
|
819
|
+
# end
|
820
|
+
# end
|
821
|
+
# if params['config']
|
822
|
+
# config_map = params.delete('config')
|
823
|
+
# params['config'] = as_json(config_map, {:pretty_json => true})
|
824
|
+
# end
|
825
|
+
# if options[:interactive_config]
|
826
|
+
# print_h2 "App Config"
|
827
|
+
# config_map = prompt_app_config(options)
|
828
|
+
# params['config'] = config_map
|
829
|
+
# end
|
830
|
+
|
831
|
+
payload[integration_object_object_key].deep_merge!(params)
|
832
|
+
end
|
833
|
+
@integrations_interface.setopts(options)
|
834
|
+
if options[:dry_run]
|
835
|
+
print_dry_run @integrations_interface.dry.create_object(integration['id'], payload)
|
836
|
+
return 0, nil
|
837
|
+
end
|
838
|
+
json_response = @integrations_interface.create_object(integration['id'], payload)
|
839
|
+
integration_object = json_response[integration_object_object_key]
|
840
|
+
render_response(json_response, options, integration_object_object_key) do
|
841
|
+
print_green_success "Added integration_object #{integration_object['name']}"
|
842
|
+
return _get_object(integration, integration_object["id"], {}, options)
|
843
|
+
end
|
844
|
+
return 0, nil
|
845
|
+
end
|
846
|
+
|
847
|
+
# def update_object(args)
|
848
|
+
# options = {}
|
849
|
+
# params = {}
|
850
|
+
# optparse = Morpheus::Cli::OptionParser.new do |opts|
|
851
|
+
# opts.banner = subcommand_usage("[integration] [object] [options]")
|
852
|
+
# build_option_type_options(opts, options, update_integration_option_types)
|
853
|
+
# build_option_type_options(opts, options, update_integration_advanced_option_types)
|
854
|
+
# build_standard_update_options(opts, options)
|
855
|
+
# opts.footer = <<-EOT
|
856
|
+
# Update an integration.
|
857
|
+
# [integration] is required. This is the name or id of an integration.
|
858
|
+
# [object] is required. This is the name or id of an integration object.
|
859
|
+
# EOT
|
860
|
+
# end
|
861
|
+
# optparse.parse!(args)
|
862
|
+
# verify_args!(args:args, optparse:optparse, count:2)
|
863
|
+
# connect(options)
|
864
|
+
# integration = find_integration_by_name_or_id(args[0])
|
865
|
+
# return 1, "integration not found for #{args[0]}" if integration.nil?
|
866
|
+
# integration_object = find_integration_object_by_name_or_id(integration['id'], args[1])
|
867
|
+
# return 1, "integration object not found for #{args[1]}" if integration_object.nil?
|
868
|
+
# payload = {}
|
869
|
+
# if options[:payload]
|
870
|
+
# payload = options[:payload]
|
871
|
+
# payload.deep_merge!({integration_object_object_key => parse_passed_options(options)})
|
872
|
+
# else
|
873
|
+
# payload.deep_merge!({integration_object_object_key => parse_passed_options(options)})
|
874
|
+
# # do not prompt on update
|
875
|
+
# v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_integration_object_option_types, options[:options], @api_client, options[:params])
|
876
|
+
# v_prompt.deep_compact!
|
877
|
+
# params.deep_merge!(v_prompt)
|
878
|
+
# advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_integration_object_advanced_option_types, options[:options], @api_client, options[:params])
|
879
|
+
# advanced_config.deep_compact!
|
880
|
+
# params.deep_merge!(advanced_config)
|
881
|
+
# # convert checkbox "on" and "off" to true and false
|
882
|
+
# params.booleanize!
|
883
|
+
# # massage association params a bit
|
884
|
+
|
885
|
+
# payload.deep_merge!({integration_object_object_key => params})
|
886
|
+
# if payload[integration_object_object_key].empty? # || options[:no_prompt]
|
887
|
+
# raise_command_error "Specify at least one option to update.\n#{optparse}"
|
888
|
+
# end
|
889
|
+
# end
|
890
|
+
# @integrations_interface.setopts(options)
|
891
|
+
# if options[:dry_run]
|
892
|
+
# print_dry_run @integrations_interface.dry.update_object(integration['id'], integration_object['id'], payload)
|
893
|
+
# return
|
894
|
+
# end
|
895
|
+
# json_response = @integrations_interface.update_object(integration['id'], integration_object['id'], payload)
|
896
|
+
# integration_object = json_response[integration_object_object_key]
|
897
|
+
# render_response(json_response, options, integration_object_object_key) do
|
898
|
+
# print_green_success "Updated integration object #{integration_object['name']}"
|
899
|
+
# return _get_object(integration, integration_object["id"], {}, options)
|
900
|
+
# end
|
901
|
+
# return 0, nil
|
902
|
+
# end
|
903
|
+
|
904
|
+
def remove_object(args)
|
905
|
+
options = {}
|
906
|
+
params = {}
|
907
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
908
|
+
opts.banner = subcommand_usage("[integration] [options]")
|
909
|
+
build_standard_remove_options(opts, options)
|
910
|
+
opts.footer = <<-EOT
|
911
|
+
Delete an integration object.
|
912
|
+
[integration] is required. This is the name or id of an integration.
|
913
|
+
[object] is required. This is the name or id of an integration object.
|
914
|
+
EOT
|
915
|
+
end
|
916
|
+
optparse.parse!(args)
|
917
|
+
verify_args!(args:args, optparse:optparse, count:2)
|
918
|
+
connect(options)
|
919
|
+
integration = find_integration_by_name_or_id(args[0])
|
920
|
+
return 1, "integration not found for #{args[0]}" if integration.nil?
|
921
|
+
integration_object = find_integration_object_by_name_or_id(integration['id'], args[1])
|
922
|
+
return 1, "integration object not found for #{args[1]}" if integration_object.nil?
|
923
|
+
params.merge!(parse_query_options(options))
|
924
|
+
@integrations_interface.setopts(options)
|
925
|
+
if options[:dry_run]
|
926
|
+
print_dry_run @integrations_interface.dry.destroy_object(integration['id'], integration_object['id'], params)
|
927
|
+
return
|
928
|
+
end
|
929
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the integration object #{integration_object['name']}?")
|
930
|
+
return 9, "aborted command"
|
931
|
+
end
|
932
|
+
json_response = @integrations_interface.destroy_object(integration['id'], integration_object['id'], params)
|
933
|
+
render_response(json_response, options) do
|
934
|
+
print_green_success "Removed integration object #{integration_object['name']}"
|
935
|
+
end
|
936
|
+
return 0, nil
|
937
|
+
end
|
938
|
+
|
462
939
|
private
|
463
940
|
|
464
941
|
def format_integration_type(integration)
|
@@ -641,4 +1118,93 @@ EOT
|
|
641
1118
|
end
|
642
1119
|
end
|
643
1120
|
|
1121
|
+
## Integration Object helpers
|
1122
|
+
|
1123
|
+
def add_integration_object_option_types
|
1124
|
+
[
|
1125
|
+
{'code' => 'integrationObject.type', 'shorthand' => '-t', 'switch' => 'type', 'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'optionSource' => 'integrationObjectTypes', 'required' => true, 'description' => "Integration Object Type eg. cloud, layout, blueprint, catalog", 'displayOrder' => 1},
|
1126
|
+
# {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => false, 'description' => 'Display Name of the integration object, default is the name of the referenced object', 'displayOrder' => 2},
|
1127
|
+
{'dependsOnCode' => 'integrationObject.type:cloud', 'switch' => 'group', 'fieldName' => 'group', 'fieldLabel' => 'Group', 'type' => 'select', 'optionSource' => 'groups', 'required' => true, 'description' => 'Group', 'displayOrder' => 3},
|
1128
|
+
{'dependsOnCode' => 'integrationObject.type:cloud', 'switch' => 'cloud', 'fieldName' => 'cloud', 'fieldLabel' => 'Cloud', 'type' => 'select', 'optionSource' => 'clouds', 'required' => true, 'description' => 'Cloud', 'displayOrder' => 4},
|
1129
|
+
{'dependsOnCode' => 'integrationObject.type:layout', 'switch' => 'instance-type', 'fieldName' => 'instanceType', 'fieldLabel' => 'Instance Type', 'type' => 'select', 'optionSource' => 'instanceTypes', 'required' => true, 'description' => 'Instance Type', 'displayOrder' => 5},
|
1130
|
+
{'dependsOnCode' => 'integrationObject.type:layout', 'switch' => 'technology', 'fieldName' => 'zoneType', 'fieldLabel' => 'Cloud Type', 'type' => 'select', 'optionSource' => 'zoneTypes', 'required' => true, 'description' => 'Cloud Type (Technology)', 'displayOrder' => 5},
|
1131
|
+
{'dependsOnCode' => 'integrationObject.type:layout', 'switch' => 'layout', 'fieldName' => 'layout', 'fieldLabel' => 'Layout', 'type' => 'select', 'optionSource' => 'layouts', 'required' => true, 'description' => 'Layout', 'displayOrder' => 6},
|
1132
|
+
{'dependsOnCode' => 'integrationObject.type:blueprint', 'fieldName' => 'name', 'fieldLabel' => 'Catalog Item Name', 'type' => 'text', 'required' => true, 'description' => 'Display Name of the integration object', 'displayOrder' => 7},
|
1133
|
+
{'dependsOnCode' => 'integrationObject.type:blueprint', 'switch' => 'blueprint', 'fieldName' => 'blueprint', 'fieldLabel' => 'Blueprint', 'type' => 'select', 'optionSource' => 'blueprints', 'required' => true, 'description' => 'Blueprint', 'displayOrder' => 8, 'noParams' => true},
|
1134
|
+
{'dependsOnCode' => 'integrationObject.type:blueprint', 'switch' => 'group', 'fieldName' => 'group', 'fieldLabel' => 'Group', 'type' => 'select', 'optionSource' => 'groups', 'required' => true, 'description' => 'Group', 'displayOrder' => 9},
|
1135
|
+
{'dependsOnCode' => 'integrationObject.type:blueprint', 'switch' => 'default-cloud', 'fieldName' => 'defaultCloud', 'fieldLabel' => 'Default Cloud', 'type' => 'select', 'optionSource' => 'clouds', 'required' => false, 'description' => 'Default Cloud', 'displayOrder' => 10},
|
1136
|
+
{'dependsOnCode' => 'integrationObject.type:blueprint', 'switch' => 'environment', 'fieldName' => 'environment', 'fieldLabel' => 'Environment', 'type' => 'select', 'optionSource' => 'environments', 'required' => false, 'description' => 'Environment', 'displayOrder' => 11},
|
1137
|
+
{'dependsOnCode' => 'integrationObject.type:blueprint', 'switch' => 'config', 'fieldName' => 'config', 'fieldLabel' => 'Config', 'type' => 'code-editor', 'required' => true, 'description' => 'Config JSON', 'displayOrder' => 12},
|
1138
|
+
{'dependsOnCode' => 'integrationObject.type:catalog', 'switch' => 'catalog', 'fieldName' => 'catalog', 'fieldLabel' => 'Catalog Item', 'type' => 'select', 'optionSource' => 'catalogItemTypes', 'required' => true, 'description' => 'Catalog Item', 'displayOrder' => 13},
|
1139
|
+
]
|
1140
|
+
end
|
1141
|
+
|
1142
|
+
def add_integration_object_advanced_option_types
|
1143
|
+
[]
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
def update_integration_object_option_types
|
1147
|
+
list = add_integration_object_option_types.collect {|it|
|
1148
|
+
it.delete('required')
|
1149
|
+
it.delete('defaultValue')
|
1150
|
+
it
|
1151
|
+
}
|
1152
|
+
list = list.reject {|it| ["type"].include? it['fieldName'] }
|
1153
|
+
list
|
1154
|
+
end
|
1155
|
+
|
1156
|
+
def update_integration_object_advanced_option_types
|
1157
|
+
add_integration_advanced_option_types.collect {|it|
|
1158
|
+
it.delete('required')
|
1159
|
+
it.delete('defaultValue')
|
1160
|
+
it
|
1161
|
+
}
|
1162
|
+
end
|
1163
|
+
|
1164
|
+
def integration_object_object_key
|
1165
|
+
'object'
|
1166
|
+
end
|
1167
|
+
|
1168
|
+
def integration_object_list_key
|
1169
|
+
'objects'
|
1170
|
+
end
|
1171
|
+
|
1172
|
+
def find_integration_object_by_name_or_id(integration_id, val)
|
1173
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
1174
|
+
return find_integration_object_by_id(integration_id, val)
|
1175
|
+
else
|
1176
|
+
return find_integration_object_by_name(integration_id, val)
|
1177
|
+
end
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
def find_integration_object_by_id(integration_id, id)
|
1181
|
+
begin
|
1182
|
+
json_response = @integrations_interface.get_object(integration_id, id.to_i)
|
1183
|
+
return json_response[integration_object_object_key]
|
1184
|
+
rescue RestClient::Exception => e
|
1185
|
+
if e.response && e.response.code == 404
|
1186
|
+
print_red_alert "integration object not found by id '#{id}'"
|
1187
|
+
else
|
1188
|
+
raise e
|
1189
|
+
end
|
1190
|
+
end
|
1191
|
+
end
|
1192
|
+
|
1193
|
+
def find_integration_object_by_name(integration_id, name)
|
1194
|
+
json_response = @integrations_interface.list_objects(integration_id, {name: name.to_s})
|
1195
|
+
integration_objects = json_response[integration_object_list_key]
|
1196
|
+
if integration_objects.empty?
|
1197
|
+
print_red_alert "integration object not found by name '#{name}'"
|
1198
|
+
return nil
|
1199
|
+
elsif integration_objects.size > 1
|
1200
|
+
print_red_alert "#{integration_objects.size} integration object found by name '#{name}'"
|
1201
|
+
puts_error as_pretty_table(integration_objects, [:id, :name], {color:red})
|
1202
|
+
print_red_alert "Try using ID instead"
|
1203
|
+
print reset,"\n"
|
1204
|
+
return nil
|
1205
|
+
else
|
1206
|
+
return integration_objects[0]
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
|
644
1210
|
end
|